diff --git a/docs/0.9.10.html b/docs/0.9.10.html index 855a05e35..0b760367b 100644 --- a/docs/0.9.10.html +++ b/docs/0.9.10.html @@ -4,7 +4,7 @@ Get started | Serverpod - + diff --git a/docs/0.9.10/capabilities.html b/docs/0.9.10/capabilities.html index 3b65a8bbb..306e50b2d 100644 --- a/docs/0.9.10/capabilities.html +++ b/docs/0.9.10/capabilities.html @@ -4,7 +4,7 @@ Capabilities | Serverpod - + diff --git a/docs/0.9.10/concepts/authentication.html b/docs/0.9.10/concepts/authentication.html index 2aaf36b10..a6501c9d1 100644 --- a/docs/0.9.10/concepts/authentication.html +++ b/docs/0.9.10/concepts/authentication.html @@ -4,7 +4,7 @@ Authentication | Serverpod - + diff --git a/docs/0.9.10/concepts/caching.html b/docs/0.9.10/concepts/caching.html index 487ab81e6..810db1eef 100644 --- a/docs/0.9.10/concepts/caching.html +++ b/docs/0.9.10/concepts/caching.html @@ -4,7 +4,7 @@ Caching | Serverpod - + diff --git a/docs/0.9.10/concepts/database-communication.html b/docs/0.9.10/concepts/database-communication.html index 826ab61e4..96e2193c6 100644 --- a/docs/0.9.10/concepts/database-communication.html +++ b/docs/0.9.10/concepts/database-communication.html @@ -4,7 +4,7 @@ Database communication | Serverpod - + @@ -34,7 +34,7 @@

Finding
var myCompany = await Company.findSingleRow(
session,
where: (t) => t.name.equals('My Company'),
);

Finding multiple rows

To find multiple rows, use the same principle as for finding a single row. Returned will be a List of TableRows.

-
var companies = await Company.find(
tCompany,
where: (t) => t.id < 100,
limit 50,
);
+
var companies = await Company.find(
tCompany,
where: (t) => t.id < 100,
limit: 50,
);

Updating a row

To update a row, use the update method. The object that you update must have its id set to a non null value.

var myCompany = await session.db.findById(tCompany, companyId) as Company?;
myCompany.name = 'New name';
await session.db.update(myCompany);
diff --git a/docs/0.9.10/concepts/file-uploads.html b/docs/0.9.10/concepts/file-uploads.html index d95859ac9..4a922ed13 100644 --- a/docs/0.9.10/concepts/file-uploads.html +++ b/docs/0.9.10/concepts/file-uploads.html @@ -4,7 +4,7 @@ Uploading files | Serverpod - + diff --git a/docs/0.9.10/concepts/logging.html b/docs/0.9.10/concepts/logging.html index e3805e8bf..25943ae63 100644 --- a/docs/0.9.10/concepts/logging.html +++ b/docs/0.9.10/concepts/logging.html @@ -4,7 +4,7 @@ Logging | Serverpod - + diff --git a/docs/0.9.10/concepts/modules.html b/docs/0.9.10/concepts/modules.html index 795c7e536..dbe4b260c 100644 --- a/docs/0.9.10/concepts/modules.html +++ b/docs/0.9.10/concepts/modules.html @@ -4,7 +4,7 @@ Modules | Serverpod - + diff --git a/docs/0.9.10/concepts/serialization.html b/docs/0.9.10/concepts/serialization.html index 49c290d0c..5c5e5c9b0 100644 --- a/docs/0.9.10/concepts/serialization.html +++ b/docs/0.9.10/concepts/serialization.html @@ -4,7 +4,7 @@ Serialization | Serverpod - + diff --git a/docs/0.9.10/concepts/streams.html b/docs/0.9.10/concepts/streams.html index 287179dfd..2c4a28676 100644 --- a/docs/0.9.10/concepts/streams.html +++ b/docs/0.9.10/concepts/streams.html @@ -4,7 +4,7 @@ Streams and messaging | Serverpod - + diff --git a/docs/0.9.10/concepts/webserver.html b/docs/0.9.10/concepts/webserver.html index 4a36ab182..dd17c8cdd 100644 --- a/docs/0.9.10/concepts/webserver.html +++ b/docs/0.9.10/concepts/webserver.html @@ -4,7 +4,7 @@ Web server | Serverpod - + diff --git a/docs/0.9.10/concepts/working-with-endpoints.html b/docs/0.9.10/concepts/working-with-endpoints.html index 6ad7944fb..6751a78a1 100644 --- a/docs/0.9.10/concepts/working-with-endpoints.html +++ b/docs/0.9.10/concepts/working-with-endpoints.html @@ -4,7 +4,7 @@ Working with endpoints | Serverpod - + diff --git a/docs/0.9.10/contribute.html b/docs/0.9.10/contribute.html index 2b51282a8..6c5557282 100644 --- a/docs/0.9.10/contribute.html +++ b/docs/0.9.10/contribute.html @@ -4,7 +4,7 @@ Contribute | Serverpod - + diff --git a/docs/0.9.10/deployments/deploying-to-aws.html b/docs/0.9.10/deployments/deploying-to-aws.html index c44559e8f..804d70d2f 100644 --- a/docs/0.9.10/deployments/deploying-to-aws.html +++ b/docs/0.9.10/deployments/deploying-to-aws.html @@ -4,7 +4,7 @@ Deploying to AWS | Serverpod - + diff --git a/docs/0.9.10/deployments/general.html b/docs/0.9.10/deployments/general.html index 439337edd..e50f801bc 100644 --- a/docs/0.9.10/deployments/general.html +++ b/docs/0.9.10/deployments/general.html @@ -4,7 +4,7 @@ General notes | Serverpod - + diff --git a/docs/0.9.10/roadmap.html b/docs/0.9.10/roadmap.html index 69231ab00..515c84b58 100644 --- a/docs/0.9.10/roadmap.html +++ b/docs/0.9.10/roadmap.html @@ -4,7 +4,7 @@ Roadmap | Serverpod - + diff --git a/docs/0.9.10/support.html b/docs/0.9.10/support.html index ae26144e7..db3643602 100644 --- a/docs/0.9.10/support.html +++ b/docs/0.9.10/support.html @@ -4,7 +4,7 @@ Support & community | Serverpod - + diff --git a/docs/0.9.11.html b/docs/0.9.11.html index 2b3f68792..7b327d39c 100644 --- a/docs/0.9.11.html +++ b/docs/0.9.11.html @@ -4,7 +4,7 @@ Get started | Serverpod - + diff --git a/docs/0.9.11/capabilities.html b/docs/0.9.11/capabilities.html index 598152f7f..f6c6a516b 100644 --- a/docs/0.9.11/capabilities.html +++ b/docs/0.9.11/capabilities.html @@ -4,7 +4,7 @@ Capabilities | Serverpod - + diff --git a/docs/0.9.11/concepts/authentication.html b/docs/0.9.11/concepts/authentication.html index fa103cc3a..44f3c6f63 100644 --- a/docs/0.9.11/concepts/authentication.html +++ b/docs/0.9.11/concepts/authentication.html @@ -4,7 +4,7 @@ Authentication | Serverpod - + diff --git a/docs/0.9.11/concepts/caching.html b/docs/0.9.11/concepts/caching.html index 674a04f1a..3e72a2c0b 100644 --- a/docs/0.9.11/concepts/caching.html +++ b/docs/0.9.11/concepts/caching.html @@ -4,7 +4,7 @@ Caching | Serverpod - + diff --git a/docs/0.9.11/concepts/database-communication.html b/docs/0.9.11/concepts/database-communication.html index a8d82dcde..f5aa16311 100644 --- a/docs/0.9.11/concepts/database-communication.html +++ b/docs/0.9.11/concepts/database-communication.html @@ -4,7 +4,7 @@ Database communication | Serverpod - + @@ -35,7 +35,7 @@

Finding
var myCompany = await Company.findSingleRow(
session,
where: (t) => t.name.equals('My Company'),
);

Finding multiple rows

To find multiple rows, use the same principle as for finding a single row. Returned will be a List of TableRows.

-
var companies = await Company.find(
tCompany,
where: (t) => t.id < 100,
limit 50,
);
+
var companies = await Company.find(
tCompany,
where: (t) => t.id < 100,
limit: 50,
);

Updating a row

To update a row, use the update method. The object that you update must have its id set to a non null value.

var myCompany = await session.db.findById(tCompany, companyId) as Company?;
myCompany.name = 'New name';
await session.db.update(myCompany);
diff --git a/docs/0.9.11/concepts/file-uploads.html b/docs/0.9.11/concepts/file-uploads.html index f390be1c2..be1bb5f45 100644 --- a/docs/0.9.11/concepts/file-uploads.html +++ b/docs/0.9.11/concepts/file-uploads.html @@ -4,7 +4,7 @@ Uploading files | Serverpod - + diff --git a/docs/0.9.11/concepts/logging.html b/docs/0.9.11/concepts/logging.html index 10a3349c6..26cf3bf1b 100644 --- a/docs/0.9.11/concepts/logging.html +++ b/docs/0.9.11/concepts/logging.html @@ -4,7 +4,7 @@ Logging | Serverpod - + diff --git a/docs/0.9.11/concepts/modules.html b/docs/0.9.11/concepts/modules.html index 37608d518..0ce284b5f 100644 --- a/docs/0.9.11/concepts/modules.html +++ b/docs/0.9.11/concepts/modules.html @@ -4,7 +4,7 @@ Modules | Serverpod - + diff --git a/docs/0.9.11/concepts/serialization.html b/docs/0.9.11/concepts/serialization.html index aa040b87a..92f86017b 100644 --- a/docs/0.9.11/concepts/serialization.html +++ b/docs/0.9.11/concepts/serialization.html @@ -4,7 +4,7 @@ Serialization | Serverpod - + diff --git a/docs/0.9.11/concepts/streams.html b/docs/0.9.11/concepts/streams.html index eee05208d..c16f18bd4 100644 --- a/docs/0.9.11/concepts/streams.html +++ b/docs/0.9.11/concepts/streams.html @@ -4,7 +4,7 @@ Streams and messaging | Serverpod - + diff --git a/docs/0.9.11/concepts/webserver.html b/docs/0.9.11/concepts/webserver.html index 06349a164..bfaed3cd0 100644 --- a/docs/0.9.11/concepts/webserver.html +++ b/docs/0.9.11/concepts/webserver.html @@ -4,7 +4,7 @@ Web server | Serverpod - + diff --git a/docs/0.9.11/concepts/working-with-endpoints.html b/docs/0.9.11/concepts/working-with-endpoints.html index 74d6bce6f..ad45da028 100644 --- a/docs/0.9.11/concepts/working-with-endpoints.html +++ b/docs/0.9.11/concepts/working-with-endpoints.html @@ -4,7 +4,7 @@ Working with endpoints | Serverpod - + diff --git a/docs/0.9.11/contribute.html b/docs/0.9.11/contribute.html index 006eed33f..cae45ae88 100644 --- a/docs/0.9.11/contribute.html +++ b/docs/0.9.11/contribute.html @@ -4,7 +4,7 @@ Contribute | Serverpod - + diff --git a/docs/0.9.11/deployments/deploying-to-aws.html b/docs/0.9.11/deployments/deploying-to-aws.html index 8304905e9..167c2afb7 100644 --- a/docs/0.9.11/deployments/deploying-to-aws.html +++ b/docs/0.9.11/deployments/deploying-to-aws.html @@ -4,7 +4,7 @@ Deploying to AWS | Serverpod - + diff --git a/docs/0.9.11/deployments/general.html b/docs/0.9.11/deployments/general.html index c68497911..c92d5b996 100644 --- a/docs/0.9.11/deployments/general.html +++ b/docs/0.9.11/deployments/general.html @@ -4,7 +4,7 @@ General notes | Serverpod - + diff --git a/docs/0.9.11/roadmap.html b/docs/0.9.11/roadmap.html index e275a710f..99f1bd8ee 100644 --- a/docs/0.9.11/roadmap.html +++ b/docs/0.9.11/roadmap.html @@ -4,7 +4,7 @@ Roadmap | Serverpod - + diff --git a/docs/0.9.11/support.html b/docs/0.9.11/support.html index e803b1958..efbb3a194 100644 --- a/docs/0.9.11/support.html +++ b/docs/0.9.11/support.html @@ -4,7 +4,7 @@ Support & community | Serverpod - + diff --git a/docs/0.9.20.html b/docs/0.9.20.html index f789a7c2e..1ed81118e 100644 --- a/docs/0.9.20.html +++ b/docs/0.9.20.html @@ -4,7 +4,7 @@ Get started | Serverpod - + diff --git a/docs/0.9.20/capabilities.html b/docs/0.9.20/capabilities.html index 96e9a245b..632014295 100644 --- a/docs/0.9.20/capabilities.html +++ b/docs/0.9.20/capabilities.html @@ -4,7 +4,7 @@ Capabilities | Serverpod - + diff --git a/docs/0.9.20/concepts/authentication.html b/docs/0.9.20/concepts/authentication.html index 65b3dea97..62b55f73d 100644 --- a/docs/0.9.20/concepts/authentication.html +++ b/docs/0.9.20/concepts/authentication.html @@ -4,7 +4,7 @@ Authentication | Serverpod - + diff --git a/docs/0.9.20/concepts/backward-compatibility.html b/docs/0.9.20/concepts/backward-compatibility.html index a1620e448..e490091a0 100644 --- a/docs/0.9.20/concepts/backward-compatibility.html +++ b/docs/0.9.20/concepts/backward-compatibility.html @@ -4,7 +4,7 @@ Backward compatibility | Serverpod - + diff --git a/docs/0.9.20/concepts/caching.html b/docs/0.9.20/concepts/caching.html index c0b9aa33b..30661bedc 100644 --- a/docs/0.9.20/concepts/caching.html +++ b/docs/0.9.20/concepts/caching.html @@ -4,7 +4,7 @@ Caching | Serverpod - + diff --git a/docs/0.9.20/concepts/database-communication.html b/docs/0.9.20/concepts/database-communication.html index 8b7a743e3..5a98af7ba 100644 --- a/docs/0.9.20/concepts/database-communication.html +++ b/docs/0.9.20/concepts/database-communication.html @@ -4,7 +4,7 @@ Database communication | Serverpod - + @@ -45,7 +45,7 @@

Finding
var myCompany = await Company.findSingleRow(
session,
where: (t) => t.name.equals('My Company'),
);

Finding multiple rows

To find multiple rows, use the same principle as for finding a single row. Returned will be a List of TableRows.

-
var companies = await Company.find(
tCompany,
where: (t) => t.id < 100,
limit 50,
);
+
var companies = await Company.find(
tCompany,
where: (t) => t.id < 100,
limit: 50,
);

Updating a row

To update a row, use the update method. The object that you update must have its id set to a non-null value.

var myCompany = await session.db.findById(tCompany, companyId) as Company?;
myCompany.name = 'New name';
await session.db.update(myCompany);
diff --git a/docs/0.9.20/concepts/file-uploads.html b/docs/0.9.20/concepts/file-uploads.html index 7fdd5f475..3b1227eae 100644 --- a/docs/0.9.20/concepts/file-uploads.html +++ b/docs/0.9.20/concepts/file-uploads.html @@ -4,7 +4,7 @@ Uploading files | Serverpod - + diff --git a/docs/0.9.20/concepts/health-checks.html b/docs/0.9.20/concepts/health-checks.html index 480ed3b95..3143af82b 100644 --- a/docs/0.9.20/concepts/health-checks.html +++ b/docs/0.9.20/concepts/health-checks.html @@ -4,7 +4,7 @@ Health checks | Serverpod - + diff --git a/docs/0.9.20/concepts/logging.html b/docs/0.9.20/concepts/logging.html index 6ca372a3e..93a2033f6 100644 --- a/docs/0.9.20/concepts/logging.html +++ b/docs/0.9.20/concepts/logging.html @@ -4,7 +4,7 @@ Logging | Serverpod - + diff --git a/docs/0.9.20/concepts/modules.html b/docs/0.9.20/concepts/modules.html index a19af542e..d163f7136 100644 --- a/docs/0.9.20/concepts/modules.html +++ b/docs/0.9.20/concepts/modules.html @@ -4,7 +4,7 @@ Modules | Serverpod - + diff --git a/docs/0.9.20/concepts/serialization.html b/docs/0.9.20/concepts/serialization.html index 5020dca5b..21924b5ed 100644 --- a/docs/0.9.20/concepts/serialization.html +++ b/docs/0.9.20/concepts/serialization.html @@ -4,7 +4,7 @@ Serialization | Serverpod - + diff --git a/docs/0.9.20/concepts/streams.html b/docs/0.9.20/concepts/streams.html index f75d83f78..17c90de79 100644 --- a/docs/0.9.20/concepts/streams.html +++ b/docs/0.9.20/concepts/streams.html @@ -4,7 +4,7 @@ Streams and messaging | Serverpod - + diff --git a/docs/0.9.20/concepts/webserver.html b/docs/0.9.20/concepts/webserver.html index 541f2694a..060aa2b73 100644 --- a/docs/0.9.20/concepts/webserver.html +++ b/docs/0.9.20/concepts/webserver.html @@ -4,7 +4,7 @@ Web server | Serverpod - + diff --git a/docs/0.9.20/concepts/working-with-endpoints.html b/docs/0.9.20/concepts/working-with-endpoints.html index 5e030283a..6c26469f3 100644 --- a/docs/0.9.20/concepts/working-with-endpoints.html +++ b/docs/0.9.20/concepts/working-with-endpoints.html @@ -4,7 +4,7 @@ Working with endpoints | Serverpod - + diff --git a/docs/0.9.20/contribute.html b/docs/0.9.20/contribute.html index ab305f669..6d1c53e14 100644 --- a/docs/0.9.20/contribute.html +++ b/docs/0.9.20/contribute.html @@ -4,7 +4,7 @@ Contribute | Serverpod - + diff --git a/docs/0.9.20/deployments/deploying-to-aws.html b/docs/0.9.20/deployments/deploying-to-aws.html index 851d6f23e..1b070cc11 100644 --- a/docs/0.9.20/deployments/deploying-to-aws.html +++ b/docs/0.9.20/deployments/deploying-to-aws.html @@ -4,7 +4,7 @@ Deploying to AWS | Serverpod - + diff --git a/docs/0.9.20/deployments/general.html b/docs/0.9.20/deployments/general.html index 405198533..bcf0294e9 100644 --- a/docs/0.9.20/deployments/general.html +++ b/docs/0.9.20/deployments/general.html @@ -4,7 +4,7 @@ General notes | Serverpod - + diff --git a/docs/0.9.20/roadmap.html b/docs/0.9.20/roadmap.html index a6a5c5da9..57bee7579 100644 --- a/docs/0.9.20/roadmap.html +++ b/docs/0.9.20/roadmap.html @@ -4,7 +4,7 @@ Roadmap | Serverpod - + diff --git a/docs/0.9.20/support.html b/docs/0.9.20/support.html index e8c5de75b..355504f21 100644 --- a/docs/0.9.20/support.html +++ b/docs/0.9.20/support.html @@ -4,7 +4,7 @@ Support & community | Serverpod - + diff --git a/docs/0.9.20/tutorials.html b/docs/0.9.20/tutorials.html index eabbcd704..8ae904169 100644 --- a/docs/0.9.20/tutorials.html +++ b/docs/0.9.20/tutorials.html @@ -4,7 +4,7 @@ Tutorials & Examples | Serverpod - + diff --git a/docs/0.9.21.html b/docs/0.9.21.html index fd143df06..39eedcea6 100644 --- a/docs/0.9.21.html +++ b/docs/0.9.21.html @@ -4,7 +4,7 @@ Get started | Serverpod - + diff --git a/docs/0.9.21/capabilities.html b/docs/0.9.21/capabilities.html index cb972dc97..192858eec 100644 --- a/docs/0.9.21/capabilities.html +++ b/docs/0.9.21/capabilities.html @@ -4,7 +4,7 @@ Capabilities | Serverpod - + diff --git a/docs/0.9.21/concepts/authentication.html b/docs/0.9.21/concepts/authentication.html index a5e4446d5..286e02e00 100644 --- a/docs/0.9.21/concepts/authentication.html +++ b/docs/0.9.21/concepts/authentication.html @@ -4,7 +4,7 @@ Authentication | Serverpod - + diff --git a/docs/0.9.21/concepts/backward-compatibility.html b/docs/0.9.21/concepts/backward-compatibility.html index 01df522cd..832bff411 100644 --- a/docs/0.9.21/concepts/backward-compatibility.html +++ b/docs/0.9.21/concepts/backward-compatibility.html @@ -4,7 +4,7 @@ Backward compatibility | Serverpod - + diff --git a/docs/0.9.21/concepts/caching.html b/docs/0.9.21/concepts/caching.html index 05597ee24..63eb5d88f 100644 --- a/docs/0.9.21/concepts/caching.html +++ b/docs/0.9.21/concepts/caching.html @@ -4,7 +4,7 @@ Caching | Serverpod - + diff --git a/docs/0.9.21/concepts/database-communication.html b/docs/0.9.21/concepts/database-communication.html index 712947e9e..86afc9180 100644 --- a/docs/0.9.21/concepts/database-communication.html +++ b/docs/0.9.21/concepts/database-communication.html @@ -4,7 +4,7 @@ Database communication | Serverpod - + @@ -45,7 +45,7 @@

Finding
var myCompany = await Company.findSingleRow(
session,
where: (t) => t.name.equals('My Company'),
);

Finding multiple rows

To find multiple rows, use the same principle as for finding a single row. Returned will be a List of TableRows.

-
var companies = await Company.find(
tCompany,
where: (t) => t.id < 100,
limit 50,
);
+
var companies = await Company.find(
tCompany,
where: (t) => t.id < 100,
limit: 50,
);

Updating a row

To update a row, use the update method. The object that you update must have its id set to a non-null value.

var myCompany = await session.db.findById(tCompany, companyId) as Company?;
myCompany.name = 'New name';
await session.db.update(myCompany);
diff --git a/docs/0.9.21/concepts/file-uploads.html b/docs/0.9.21/concepts/file-uploads.html index 84e9afb8e..0a1797a05 100644 --- a/docs/0.9.21/concepts/file-uploads.html +++ b/docs/0.9.21/concepts/file-uploads.html @@ -4,7 +4,7 @@ Uploading files | Serverpod - + diff --git a/docs/0.9.21/concepts/health-checks.html b/docs/0.9.21/concepts/health-checks.html index a78985fd4..0f83403cf 100644 --- a/docs/0.9.21/concepts/health-checks.html +++ b/docs/0.9.21/concepts/health-checks.html @@ -4,7 +4,7 @@ Health checks | Serverpod - + diff --git a/docs/0.9.21/concepts/logging.html b/docs/0.9.21/concepts/logging.html index f1ec708cb..250f5e692 100644 --- a/docs/0.9.21/concepts/logging.html +++ b/docs/0.9.21/concepts/logging.html @@ -4,7 +4,7 @@ Logging | Serverpod - + diff --git a/docs/0.9.21/concepts/modules.html b/docs/0.9.21/concepts/modules.html index 5d7cc2f25..5600c79e2 100644 --- a/docs/0.9.21/concepts/modules.html +++ b/docs/0.9.21/concepts/modules.html @@ -4,7 +4,7 @@ Modules | Serverpod - + diff --git a/docs/0.9.21/concepts/serialization.html b/docs/0.9.21/concepts/serialization.html index 421b5c716..d2c511936 100644 --- a/docs/0.9.21/concepts/serialization.html +++ b/docs/0.9.21/concepts/serialization.html @@ -4,7 +4,7 @@ Serialization | Serverpod - + diff --git a/docs/0.9.21/concepts/streams.html b/docs/0.9.21/concepts/streams.html index 5bb358b2f..fa46f55bc 100644 --- a/docs/0.9.21/concepts/streams.html +++ b/docs/0.9.21/concepts/streams.html @@ -4,7 +4,7 @@ Streams and messaging | Serverpod - + diff --git a/docs/0.9.21/concepts/webserver.html b/docs/0.9.21/concepts/webserver.html index 7bbea2ba4..04af99c73 100644 --- a/docs/0.9.21/concepts/webserver.html +++ b/docs/0.9.21/concepts/webserver.html @@ -4,7 +4,7 @@ Web server | Serverpod - + diff --git a/docs/0.9.21/concepts/working-with-endpoints.html b/docs/0.9.21/concepts/working-with-endpoints.html index 83233a393..1910217cc 100644 --- a/docs/0.9.21/concepts/working-with-endpoints.html +++ b/docs/0.9.21/concepts/working-with-endpoints.html @@ -4,7 +4,7 @@ Working with endpoints | Serverpod - + diff --git a/docs/0.9.21/contribute.html b/docs/0.9.21/contribute.html index b84dbc617..06d686a94 100644 --- a/docs/0.9.21/contribute.html +++ b/docs/0.9.21/contribute.html @@ -4,7 +4,7 @@ Contribute | Serverpod - + diff --git a/docs/0.9.21/deployments/deploying-to-aws.html b/docs/0.9.21/deployments/deploying-to-aws.html index 1154c2682..dc175e5d0 100644 --- a/docs/0.9.21/deployments/deploying-to-aws.html +++ b/docs/0.9.21/deployments/deploying-to-aws.html @@ -4,7 +4,7 @@ Deploying to AWS | Serverpod - + diff --git a/docs/0.9.21/deployments/general.html b/docs/0.9.21/deployments/general.html index d00de4be1..89b6fbf18 100644 --- a/docs/0.9.21/deployments/general.html +++ b/docs/0.9.21/deployments/general.html @@ -4,7 +4,7 @@ General notes | Serverpod - + diff --git a/docs/0.9.21/roadmap.html b/docs/0.9.21/roadmap.html index 7f2da09bf..efa5728a8 100644 --- a/docs/0.9.21/roadmap.html +++ b/docs/0.9.21/roadmap.html @@ -4,7 +4,7 @@ Roadmap | Serverpod - + diff --git a/docs/0.9.21/support.html b/docs/0.9.21/support.html index 73f42e8d5..c5275c8bb 100644 --- a/docs/0.9.21/support.html +++ b/docs/0.9.21/support.html @@ -4,7 +4,7 @@ Support & community | Serverpod - + diff --git a/docs/0.9.21/tutorials.html b/docs/0.9.21/tutorials.html index d1480f6b0..8720dec91 100644 --- a/docs/0.9.21/tutorials.html +++ b/docs/0.9.21/tutorials.html @@ -4,7 +4,7 @@ Tutorials & Examples | Serverpod - + diff --git a/docs/0.9.22.html b/docs/0.9.22.html index fb76b4bdc..50247de1d 100644 --- a/docs/0.9.22.html +++ b/docs/0.9.22.html @@ -4,7 +4,7 @@ Get started | Serverpod - + diff --git a/docs/0.9.22/capabilities.html b/docs/0.9.22/capabilities.html index 25e6f50f6..32d4d47e9 100644 --- a/docs/0.9.22/capabilities.html +++ b/docs/0.9.22/capabilities.html @@ -4,7 +4,7 @@ Capabilities | Serverpod - + diff --git a/docs/0.9.22/concepts/authentication.html b/docs/0.9.22/concepts/authentication.html index e9101448d..4e40146c7 100644 --- a/docs/0.9.22/concepts/authentication.html +++ b/docs/0.9.22/concepts/authentication.html @@ -4,7 +4,7 @@ Authentication | Serverpod - + diff --git a/docs/0.9.22/concepts/backward-compatibility.html b/docs/0.9.22/concepts/backward-compatibility.html index 8509e273c..944b950f4 100644 --- a/docs/0.9.22/concepts/backward-compatibility.html +++ b/docs/0.9.22/concepts/backward-compatibility.html @@ -4,7 +4,7 @@ Backward compatibility | Serverpod - + diff --git a/docs/0.9.22/concepts/caching.html b/docs/0.9.22/concepts/caching.html index e4e467180..585e75236 100644 --- a/docs/0.9.22/concepts/caching.html +++ b/docs/0.9.22/concepts/caching.html @@ -4,7 +4,7 @@ Caching | Serverpod - + diff --git a/docs/0.9.22/concepts/database-communication.html b/docs/0.9.22/concepts/database-communication.html index 423b4b97c..40eb79978 100644 --- a/docs/0.9.22/concepts/database-communication.html +++ b/docs/0.9.22/concepts/database-communication.html @@ -4,7 +4,7 @@ Database communication | Serverpod - + @@ -45,7 +45,7 @@

Finding
var myCompany = await Company.findSingleRow(
session,
where: (t) => t.name.equals('My Company'),
);

Finding multiple rows

To find multiple rows, use the same principle as for finding a single row. Returned will be a List of TableRows.

-
var companies = await Company.find(
tCompany,
where: (t) => t.id < 100,
limit 50,
);
+
var companies = await Company.find(
tCompany,
where: (t) => t.id < 100,
limit: 50,
);

Updating a row

To update a row, use the update method. The object that you update must have its id set to a non-null value.

var myCompany = await session.db.findById(tCompany, companyId) as Company?;
myCompany.name = 'New name';
await session.db.update(myCompany);
diff --git a/docs/0.9.22/concepts/file-uploads.html b/docs/0.9.22/concepts/file-uploads.html index 8604f891e..f1871ab17 100644 --- a/docs/0.9.22/concepts/file-uploads.html +++ b/docs/0.9.22/concepts/file-uploads.html @@ -4,7 +4,7 @@ Uploading files | Serverpod - + diff --git a/docs/0.9.22/concepts/health-checks.html b/docs/0.9.22/concepts/health-checks.html index 3d2cd7e00..880607e56 100644 --- a/docs/0.9.22/concepts/health-checks.html +++ b/docs/0.9.22/concepts/health-checks.html @@ -4,7 +4,7 @@ Health checks | Serverpod - + diff --git a/docs/0.9.22/concepts/logging.html b/docs/0.9.22/concepts/logging.html index 99514d2f5..59837414e 100644 --- a/docs/0.9.22/concepts/logging.html +++ b/docs/0.9.22/concepts/logging.html @@ -4,7 +4,7 @@ Logging | Serverpod - + diff --git a/docs/0.9.22/concepts/modules.html b/docs/0.9.22/concepts/modules.html index 335505fab..42ec3324e 100644 --- a/docs/0.9.22/concepts/modules.html +++ b/docs/0.9.22/concepts/modules.html @@ -4,7 +4,7 @@ Modules | Serverpod - + diff --git a/docs/0.9.22/concepts/serialization.html b/docs/0.9.22/concepts/serialization.html index e7870cc7a..b13d5762f 100644 --- a/docs/0.9.22/concepts/serialization.html +++ b/docs/0.9.22/concepts/serialization.html @@ -4,7 +4,7 @@ Serialization | Serverpod - + diff --git a/docs/0.9.22/concepts/streams.html b/docs/0.9.22/concepts/streams.html index 9cbc3c15a..920545857 100644 --- a/docs/0.9.22/concepts/streams.html +++ b/docs/0.9.22/concepts/streams.html @@ -4,7 +4,7 @@ Streams and messaging | Serverpod - + diff --git a/docs/0.9.22/concepts/webserver.html b/docs/0.9.22/concepts/webserver.html index 334dc3d8f..875454913 100644 --- a/docs/0.9.22/concepts/webserver.html +++ b/docs/0.9.22/concepts/webserver.html @@ -4,7 +4,7 @@ Web server | Serverpod - + diff --git a/docs/0.9.22/concepts/working-with-endpoints.html b/docs/0.9.22/concepts/working-with-endpoints.html index 3a5402f53..7fcb0d3ed 100644 --- a/docs/0.9.22/concepts/working-with-endpoints.html +++ b/docs/0.9.22/concepts/working-with-endpoints.html @@ -4,7 +4,7 @@ Working with endpoints | Serverpod - + diff --git a/docs/0.9.22/contribute.html b/docs/0.9.22/contribute.html index 31889dcd7..c410f6d40 100644 --- a/docs/0.9.22/contribute.html +++ b/docs/0.9.22/contribute.html @@ -4,7 +4,7 @@ Contribute | Serverpod - + diff --git a/docs/0.9.22/deployments/deploying-to-aws.html b/docs/0.9.22/deployments/deploying-to-aws.html index 67d46cee7..9ab3540a8 100644 --- a/docs/0.9.22/deployments/deploying-to-aws.html +++ b/docs/0.9.22/deployments/deploying-to-aws.html @@ -4,7 +4,7 @@ Deploying to AWS | Serverpod - + diff --git a/docs/0.9.22/deployments/general.html b/docs/0.9.22/deployments/general.html index c72752337..36e2ee7cd 100644 --- a/docs/0.9.22/deployments/general.html +++ b/docs/0.9.22/deployments/general.html @@ -4,7 +4,7 @@ General notes | Serverpod - + diff --git a/docs/0.9.22/roadmap.html b/docs/0.9.22/roadmap.html index ebd6dcda3..7ec171f21 100644 --- a/docs/0.9.22/roadmap.html +++ b/docs/0.9.22/roadmap.html @@ -4,7 +4,7 @@ Roadmap | Serverpod - + diff --git a/docs/0.9.22/support.html b/docs/0.9.22/support.html index adc4d6cac..40bb11dd0 100644 --- a/docs/0.9.22/support.html +++ b/docs/0.9.22/support.html @@ -4,7 +4,7 @@ Support & community | Serverpod - + diff --git a/docs/0.9.22/tutorials.html b/docs/0.9.22/tutorials.html index e1d248080..3fcecac5d 100644 --- a/docs/0.9.22/tutorials.html +++ b/docs/0.9.22/tutorials.html @@ -4,7 +4,7 @@ Tutorials & Examples | Serverpod - + diff --git a/docs/0.9.5.html b/docs/0.9.5.html index fb0e26a64..0382ebe8c 100644 --- a/docs/0.9.5.html +++ b/docs/0.9.5.html @@ -4,7 +4,7 @@ Get started | Serverpod - + diff --git a/docs/0.9.5/capabilities.html b/docs/0.9.5/capabilities.html index d6d62d8be..7acd5af2f 100644 --- a/docs/0.9.5/capabilities.html +++ b/docs/0.9.5/capabilities.html @@ -4,7 +4,7 @@ Capabilities | Serverpod - + diff --git a/docs/0.9.5/concepts/authentication.html b/docs/0.9.5/concepts/authentication.html index 05eb6b3dc..f7b19701c 100644 --- a/docs/0.9.5/concepts/authentication.html +++ b/docs/0.9.5/concepts/authentication.html @@ -4,7 +4,7 @@ Authentication | Serverpod - + diff --git a/docs/0.9.5/concepts/caching.html b/docs/0.9.5/concepts/caching.html index 8f3af3357..8e8a1c7e7 100644 --- a/docs/0.9.5/concepts/caching.html +++ b/docs/0.9.5/concepts/caching.html @@ -4,7 +4,7 @@ Caching | Serverpod - + diff --git a/docs/0.9.5/concepts/database-communication.html b/docs/0.9.5/concepts/database-communication.html index 4b1791049..2ee93b13a 100644 --- a/docs/0.9.5/concepts/database-communication.html +++ b/docs/0.9.5/concepts/database-communication.html @@ -4,7 +4,7 @@ Database communication | Serverpod - + @@ -34,7 +34,7 @@

Finding
var myCompany = await Company.findSingleRow(
session,
where: (t) => t.name.equals('My Company'),
);

Finding multiple rows

To find multiple rows, use the same principle as for finding a single row. Returned will be a List of TableRows.

-
var companies = await Company.find(
tCompany,
where: (t) => t.id < 100,
limit 50,
);
+
var companies = await Company.find(
tCompany,
where: (t) => t.id < 100,
limit: 50,
);

Updating a row

To update a row, use the update method. The object that you update must have its id set to a non null value.

var myCompany = await session.db.findById(tCompany, companyId) as Company?;
myCompany.name = 'New name';
await session.db.update(myCompany);
diff --git a/docs/0.9.5/concepts/file-uploads.html b/docs/0.9.5/concepts/file-uploads.html index 05b14f35e..38af62059 100644 --- a/docs/0.9.5/concepts/file-uploads.html +++ b/docs/0.9.5/concepts/file-uploads.html @@ -4,7 +4,7 @@ Uploading files | Serverpod - + diff --git a/docs/0.9.5/concepts/logging.html b/docs/0.9.5/concepts/logging.html index b73748650..9b80a074a 100644 --- a/docs/0.9.5/concepts/logging.html +++ b/docs/0.9.5/concepts/logging.html @@ -4,7 +4,7 @@ Logging | Serverpod - + diff --git a/docs/0.9.5/concepts/modules.html b/docs/0.9.5/concepts/modules.html index 5d55506de..cd0dddfa0 100644 --- a/docs/0.9.5/concepts/modules.html +++ b/docs/0.9.5/concepts/modules.html @@ -4,7 +4,7 @@ Modules | Serverpod - + diff --git a/docs/0.9.5/concepts/serialization.html b/docs/0.9.5/concepts/serialization.html index 10a34b8ff..5c36eb888 100644 --- a/docs/0.9.5/concepts/serialization.html +++ b/docs/0.9.5/concepts/serialization.html @@ -4,7 +4,7 @@ Serialization | Serverpod - + diff --git a/docs/0.9.5/concepts/streams.html b/docs/0.9.5/concepts/streams.html index 0fe1f2f15..226b22e1a 100644 --- a/docs/0.9.5/concepts/streams.html +++ b/docs/0.9.5/concepts/streams.html @@ -4,7 +4,7 @@ Streams and messaging | Serverpod - + diff --git a/docs/0.9.5/concepts/working-with-endpoints.html b/docs/0.9.5/concepts/working-with-endpoints.html index c6c8fa594..810db5983 100644 --- a/docs/0.9.5/concepts/working-with-endpoints.html +++ b/docs/0.9.5/concepts/working-with-endpoints.html @@ -4,7 +4,7 @@ Working with endpoints | Serverpod - + diff --git a/docs/0.9.5/contribute.html b/docs/0.9.5/contribute.html index 4144bef8d..7c559c2fe 100644 --- a/docs/0.9.5/contribute.html +++ b/docs/0.9.5/contribute.html @@ -4,7 +4,7 @@ Contribute | Serverpod - + diff --git a/docs/0.9.5/deployments/general.html b/docs/0.9.5/deployments/general.html index f1b093251..607a1f630 100644 --- a/docs/0.9.5/deployments/general.html +++ b/docs/0.9.5/deployments/general.html @@ -4,7 +4,7 @@ General notes | Serverpod - + diff --git a/docs/0.9.5/roadmap.html b/docs/0.9.5/roadmap.html index 10916934d..35f1959f5 100644 --- a/docs/0.9.5/roadmap.html +++ b/docs/0.9.5/roadmap.html @@ -4,7 +4,7 @@ Roadmap | Serverpod - + diff --git a/docs/0.9.6.html b/docs/0.9.6.html index 8a39d1010..fa97df5a6 100644 --- a/docs/0.9.6.html +++ b/docs/0.9.6.html @@ -4,7 +4,7 @@ Get started | Serverpod - + diff --git a/docs/0.9.6/capabilities.html b/docs/0.9.6/capabilities.html index dc549530e..eb444380f 100644 --- a/docs/0.9.6/capabilities.html +++ b/docs/0.9.6/capabilities.html @@ -4,7 +4,7 @@ Capabilities | Serverpod - + diff --git a/docs/0.9.6/concepts/authentication.html b/docs/0.9.6/concepts/authentication.html index 39ee990af..d0932b0db 100644 --- a/docs/0.9.6/concepts/authentication.html +++ b/docs/0.9.6/concepts/authentication.html @@ -4,7 +4,7 @@ Authentication | Serverpod - + diff --git a/docs/0.9.6/concepts/caching.html b/docs/0.9.6/concepts/caching.html index 0cbc9846b..be05c9995 100644 --- a/docs/0.9.6/concepts/caching.html +++ b/docs/0.9.6/concepts/caching.html @@ -4,7 +4,7 @@ Caching | Serverpod - + diff --git a/docs/0.9.6/concepts/database-communication.html b/docs/0.9.6/concepts/database-communication.html index 127747401..de604eaa4 100644 --- a/docs/0.9.6/concepts/database-communication.html +++ b/docs/0.9.6/concepts/database-communication.html @@ -4,7 +4,7 @@ Database communication | Serverpod - + @@ -34,7 +34,7 @@

Finding
var myCompany = await Company.findSingleRow(
session,
where: (t) => t.name.equals('My Company'),
);

Finding multiple rows

To find multiple rows, use the same principle as for finding a single row. Returned will be a List of TableRows.

-
var companies = await Company.find(
tCompany,
where: (t) => t.id < 100,
limit 50,
);
+
var companies = await Company.find(
tCompany,
where: (t) => t.id < 100,
limit: 50,
);

Updating a row

To update a row, use the update method. The object that you update must have its id set to a non null value.

var myCompany = await session.db.findById(tCompany, companyId) as Company?;
myCompany.name = 'New name';
await session.db.update(myCompany);
diff --git a/docs/0.9.6/concepts/file-uploads.html b/docs/0.9.6/concepts/file-uploads.html index b06467062..403fc3ea0 100644 --- a/docs/0.9.6/concepts/file-uploads.html +++ b/docs/0.9.6/concepts/file-uploads.html @@ -4,7 +4,7 @@ Uploading files | Serverpod - + diff --git a/docs/0.9.6/concepts/logging.html b/docs/0.9.6/concepts/logging.html index 1050cd2bc..9c37d8df0 100644 --- a/docs/0.9.6/concepts/logging.html +++ b/docs/0.9.6/concepts/logging.html @@ -4,7 +4,7 @@ Logging | Serverpod - + diff --git a/docs/0.9.6/concepts/modules.html b/docs/0.9.6/concepts/modules.html index f89dbae00..8252dcf1c 100644 --- a/docs/0.9.6/concepts/modules.html +++ b/docs/0.9.6/concepts/modules.html @@ -4,7 +4,7 @@ Modules | Serverpod - + diff --git a/docs/0.9.6/concepts/serialization.html b/docs/0.9.6/concepts/serialization.html index 5e87e110f..b3c4c1794 100644 --- a/docs/0.9.6/concepts/serialization.html +++ b/docs/0.9.6/concepts/serialization.html @@ -4,7 +4,7 @@ Serialization | Serverpod - + diff --git a/docs/0.9.6/concepts/streams.html b/docs/0.9.6/concepts/streams.html index 1684b5ccd..bd1823fbe 100644 --- a/docs/0.9.6/concepts/streams.html +++ b/docs/0.9.6/concepts/streams.html @@ -4,7 +4,7 @@ Streams and messaging | Serverpod - + diff --git a/docs/0.9.6/concepts/working-with-endpoints.html b/docs/0.9.6/concepts/working-with-endpoints.html index 415df24f3..f0a8962d1 100644 --- a/docs/0.9.6/concepts/working-with-endpoints.html +++ b/docs/0.9.6/concepts/working-with-endpoints.html @@ -4,7 +4,7 @@ Working with endpoints | Serverpod - + diff --git a/docs/0.9.6/contribute.html b/docs/0.9.6/contribute.html index 479fc09c2..c05d0d0c6 100644 --- a/docs/0.9.6/contribute.html +++ b/docs/0.9.6/contribute.html @@ -4,7 +4,7 @@ Contribute | Serverpod - + diff --git a/docs/0.9.6/deployments/general.html b/docs/0.9.6/deployments/general.html index 3d3327fa5..1ebf1d4ea 100644 --- a/docs/0.9.6/deployments/general.html +++ b/docs/0.9.6/deployments/general.html @@ -4,7 +4,7 @@ General notes | Serverpod - + diff --git a/docs/0.9.6/roadmap.html b/docs/0.9.6/roadmap.html index 8a57bfadb..116aaeed2 100644 --- a/docs/0.9.6/roadmap.html +++ b/docs/0.9.6/roadmap.html @@ -4,7 +4,7 @@ Roadmap | Serverpod - + diff --git a/docs/0.9.7.html b/docs/0.9.7.html index 4b82839db..643e755bb 100644 --- a/docs/0.9.7.html +++ b/docs/0.9.7.html @@ -4,7 +4,7 @@ Get started | Serverpod - + diff --git a/docs/0.9.7/capabilities.html b/docs/0.9.7/capabilities.html index 3e6caefd7..5752b29b7 100644 --- a/docs/0.9.7/capabilities.html +++ b/docs/0.9.7/capabilities.html @@ -4,7 +4,7 @@ Capabilities | Serverpod - + diff --git a/docs/0.9.7/concepts/authentication.html b/docs/0.9.7/concepts/authentication.html index c295ba91c..52bfd9186 100644 --- a/docs/0.9.7/concepts/authentication.html +++ b/docs/0.9.7/concepts/authentication.html @@ -4,7 +4,7 @@ Authentication | Serverpod - + diff --git a/docs/0.9.7/concepts/caching.html b/docs/0.9.7/concepts/caching.html index 8cdadb936..db9f2fbd3 100644 --- a/docs/0.9.7/concepts/caching.html +++ b/docs/0.9.7/concepts/caching.html @@ -4,7 +4,7 @@ Caching | Serverpod - + diff --git a/docs/0.9.7/concepts/database-communication.html b/docs/0.9.7/concepts/database-communication.html index 2168dd0d1..5048e5d22 100644 --- a/docs/0.9.7/concepts/database-communication.html +++ b/docs/0.9.7/concepts/database-communication.html @@ -4,7 +4,7 @@ Database communication | Serverpod - + @@ -34,7 +34,7 @@

Finding
var myCompany = await Company.findSingleRow(
session,
where: (t) => t.name.equals('My Company'),
);

Finding multiple rows

To find multiple rows, use the same principle as for finding a single row. Returned will be a List of TableRows.

-
var companies = await Company.find(
tCompany,
where: (t) => t.id < 100,
limit 50,
);
+
var companies = await Company.find(
tCompany,
where: (t) => t.id < 100,
limit: 50,
);

Updating a row

To update a row, use the update method. The object that you update must have its id set to a non null value.

var myCompany = await session.db.findById(tCompany, companyId) as Company?;
myCompany.name = 'New name';
await session.db.update(myCompany);
diff --git a/docs/0.9.7/concepts/file-uploads.html b/docs/0.9.7/concepts/file-uploads.html index b299d5e2e..19c5295d4 100644 --- a/docs/0.9.7/concepts/file-uploads.html +++ b/docs/0.9.7/concepts/file-uploads.html @@ -4,7 +4,7 @@ Uploading files | Serverpod - + diff --git a/docs/0.9.7/concepts/logging.html b/docs/0.9.7/concepts/logging.html index f19329061..1e607b848 100644 --- a/docs/0.9.7/concepts/logging.html +++ b/docs/0.9.7/concepts/logging.html @@ -4,7 +4,7 @@ Logging | Serverpod - + diff --git a/docs/0.9.7/concepts/modules.html b/docs/0.9.7/concepts/modules.html index 55134fd4e..67c9e0c1a 100644 --- a/docs/0.9.7/concepts/modules.html +++ b/docs/0.9.7/concepts/modules.html @@ -4,7 +4,7 @@ Modules | Serverpod - + diff --git a/docs/0.9.7/concepts/serialization.html b/docs/0.9.7/concepts/serialization.html index e49dbb67f..9db93027c 100644 --- a/docs/0.9.7/concepts/serialization.html +++ b/docs/0.9.7/concepts/serialization.html @@ -4,7 +4,7 @@ Serialization | Serverpod - + diff --git a/docs/0.9.7/concepts/streams.html b/docs/0.9.7/concepts/streams.html index a41770473..6e94932de 100644 --- a/docs/0.9.7/concepts/streams.html +++ b/docs/0.9.7/concepts/streams.html @@ -4,7 +4,7 @@ Streams and messaging | Serverpod - + diff --git a/docs/0.9.7/concepts/working-with-endpoints.html b/docs/0.9.7/concepts/working-with-endpoints.html index 3cbc4407f..216689104 100644 --- a/docs/0.9.7/concepts/working-with-endpoints.html +++ b/docs/0.9.7/concepts/working-with-endpoints.html @@ -4,7 +4,7 @@ Working with endpoints | Serverpod - + diff --git a/docs/0.9.7/contribute.html b/docs/0.9.7/contribute.html index 655e4ddd6..e06c1172a 100644 --- a/docs/0.9.7/contribute.html +++ b/docs/0.9.7/contribute.html @@ -4,7 +4,7 @@ Contribute | Serverpod - + diff --git a/docs/0.9.7/deployments/general.html b/docs/0.9.7/deployments/general.html index 7aecfab66..6210888cc 100644 --- a/docs/0.9.7/deployments/general.html +++ b/docs/0.9.7/deployments/general.html @@ -4,7 +4,7 @@ General notes | Serverpod - + diff --git a/docs/0.9.7/roadmap.html b/docs/0.9.7/roadmap.html index e36f3389f..ffe8f2597 100644 --- a/docs/0.9.7/roadmap.html +++ b/docs/0.9.7/roadmap.html @@ -4,7 +4,7 @@ Roadmap | Serverpod - + diff --git a/docs/0.9.7/support.html b/docs/0.9.7/support.html index 3c5d0d02a..37338fceb 100644 --- a/docs/0.9.7/support.html +++ b/docs/0.9.7/support.html @@ -4,7 +4,7 @@ Support | Serverpod - + diff --git a/docs/0.9.8.html b/docs/0.9.8.html index b553133ca..78a570345 100644 --- a/docs/0.9.8.html +++ b/docs/0.9.8.html @@ -4,7 +4,7 @@ Get started | Serverpod - + diff --git a/docs/0.9.8/capabilities.html b/docs/0.9.8/capabilities.html index 395f43045..205ae74d0 100644 --- a/docs/0.9.8/capabilities.html +++ b/docs/0.9.8/capabilities.html @@ -4,7 +4,7 @@ Capabilities | Serverpod - + diff --git a/docs/0.9.8/concepts/authentication.html b/docs/0.9.8/concepts/authentication.html index 9e21e4129..c7cb1215d 100644 --- a/docs/0.9.8/concepts/authentication.html +++ b/docs/0.9.8/concepts/authentication.html @@ -4,7 +4,7 @@ Authentication | Serverpod - + diff --git a/docs/0.9.8/concepts/caching.html b/docs/0.9.8/concepts/caching.html index 9473fa639..1da422c24 100644 --- a/docs/0.9.8/concepts/caching.html +++ b/docs/0.9.8/concepts/caching.html @@ -4,7 +4,7 @@ Caching | Serverpod - + diff --git a/docs/0.9.8/concepts/database-communication.html b/docs/0.9.8/concepts/database-communication.html index 1d70a6575..63ede929e 100644 --- a/docs/0.9.8/concepts/database-communication.html +++ b/docs/0.9.8/concepts/database-communication.html @@ -4,7 +4,7 @@ Database communication | Serverpod - + @@ -34,7 +34,7 @@

Finding
var myCompany = await Company.findSingleRow(
session,
where: (t) => t.name.equals('My Company'),
);

Finding multiple rows

To find multiple rows, use the same principle as for finding a single row. Returned will be a List of TableRows.

-
var companies = await Company.find(
tCompany,
where: (t) => t.id < 100,
limit 50,
);
+
var companies = await Company.find(
tCompany,
where: (t) => t.id < 100,
limit: 50,
);

Updating a row

To update a row, use the update method. The object that you update must have its id set to a non null value.

var myCompany = await session.db.findById(tCompany, companyId) as Company?;
myCompany.name = 'New name';
await session.db.update(myCompany);
diff --git a/docs/0.9.8/concepts/file-uploads.html b/docs/0.9.8/concepts/file-uploads.html index 7e5eb6d1c..0ae1cb5d8 100644 --- a/docs/0.9.8/concepts/file-uploads.html +++ b/docs/0.9.8/concepts/file-uploads.html @@ -4,7 +4,7 @@ Uploading files | Serverpod - + diff --git a/docs/0.9.8/concepts/logging.html b/docs/0.9.8/concepts/logging.html index 29dc12255..077d86c30 100644 --- a/docs/0.9.8/concepts/logging.html +++ b/docs/0.9.8/concepts/logging.html @@ -4,7 +4,7 @@ Logging | Serverpod - + diff --git a/docs/0.9.8/concepts/modules.html b/docs/0.9.8/concepts/modules.html index f71b23da0..2cd97e644 100644 --- a/docs/0.9.8/concepts/modules.html +++ b/docs/0.9.8/concepts/modules.html @@ -4,7 +4,7 @@ Modules | Serverpod - + diff --git a/docs/0.9.8/concepts/serialization.html b/docs/0.9.8/concepts/serialization.html index 401a3053a..416538cbe 100644 --- a/docs/0.9.8/concepts/serialization.html +++ b/docs/0.9.8/concepts/serialization.html @@ -4,7 +4,7 @@ Serialization | Serverpod - + diff --git a/docs/0.9.8/concepts/streams.html b/docs/0.9.8/concepts/streams.html index 4f9aae797..380cdc3a8 100644 --- a/docs/0.9.8/concepts/streams.html +++ b/docs/0.9.8/concepts/streams.html @@ -4,7 +4,7 @@ Streams and messaging | Serverpod - + diff --git a/docs/0.9.8/concepts/working-with-endpoints.html b/docs/0.9.8/concepts/working-with-endpoints.html index 5c7d94252..d56cf8b73 100644 --- a/docs/0.9.8/concepts/working-with-endpoints.html +++ b/docs/0.9.8/concepts/working-with-endpoints.html @@ -4,7 +4,7 @@ Working with endpoints | Serverpod - + diff --git a/docs/0.9.8/contribute.html b/docs/0.9.8/contribute.html index 78fc8f5ab..803da5c17 100644 --- a/docs/0.9.8/contribute.html +++ b/docs/0.9.8/contribute.html @@ -4,7 +4,7 @@ Contribute | Serverpod - + diff --git a/docs/0.9.8/deployments/deploying-to-aws.html b/docs/0.9.8/deployments/deploying-to-aws.html index beb983682..cdab6db40 100644 --- a/docs/0.9.8/deployments/deploying-to-aws.html +++ b/docs/0.9.8/deployments/deploying-to-aws.html @@ -4,7 +4,7 @@ Deploying to AWS | Serverpod - + diff --git a/docs/0.9.8/deployments/general.html b/docs/0.9.8/deployments/general.html index 222e5da42..ed95ad679 100644 --- a/docs/0.9.8/deployments/general.html +++ b/docs/0.9.8/deployments/general.html @@ -4,7 +4,7 @@ General notes | Serverpod - + diff --git a/docs/0.9.8/roadmap.html b/docs/0.9.8/roadmap.html index 7282d8166..339f31bea 100644 --- a/docs/0.9.8/roadmap.html +++ b/docs/0.9.8/roadmap.html @@ -4,7 +4,7 @@ Roadmap | Serverpod - + diff --git a/docs/0.9.8/support.html b/docs/0.9.8/support.html index 49c91d381..a44eb1a4b 100644 --- a/docs/0.9.8/support.html +++ b/docs/0.9.8/support.html @@ -4,7 +4,7 @@ Support | Serverpod - + diff --git a/docs/0.9.9.html b/docs/0.9.9.html index b8730137a..0358d9c66 100644 --- a/docs/0.9.9.html +++ b/docs/0.9.9.html @@ -4,7 +4,7 @@ Get started | Serverpod - + diff --git a/docs/0.9.9/capabilities.html b/docs/0.9.9/capabilities.html index d13b46e6b..e17a634e0 100644 --- a/docs/0.9.9/capabilities.html +++ b/docs/0.9.9/capabilities.html @@ -4,7 +4,7 @@ Capabilities | Serverpod - + diff --git a/docs/0.9.9/concepts/authentication.html b/docs/0.9.9/concepts/authentication.html index 8f5424b64..538f866fc 100644 --- a/docs/0.9.9/concepts/authentication.html +++ b/docs/0.9.9/concepts/authentication.html @@ -4,7 +4,7 @@ Authentication | Serverpod - + diff --git a/docs/0.9.9/concepts/caching.html b/docs/0.9.9/concepts/caching.html index 1729e0b96..2f9bbe95d 100644 --- a/docs/0.9.9/concepts/caching.html +++ b/docs/0.9.9/concepts/caching.html @@ -4,7 +4,7 @@ Caching | Serverpod - + diff --git a/docs/0.9.9/concepts/database-communication.html b/docs/0.9.9/concepts/database-communication.html index 4baf32bb3..a8124bd46 100644 --- a/docs/0.9.9/concepts/database-communication.html +++ b/docs/0.9.9/concepts/database-communication.html @@ -4,7 +4,7 @@ Database communication | Serverpod - + @@ -34,7 +34,7 @@

Finding
var myCompany = await Company.findSingleRow(
session,
where: (t) => t.name.equals('My Company'),
);

Finding multiple rows

To find multiple rows, use the same principle as for finding a single row. Returned will be a List of TableRows.

-
var companies = await Company.find(
tCompany,
where: (t) => t.id < 100,
limit 50,
);
+
var companies = await Company.find(
tCompany,
where: (t) => t.id < 100,
limit: 50,
);

Updating a row

To update a row, use the update method. The object that you update must have its id set to a non null value.

var myCompany = await session.db.findById(tCompany, companyId) as Company?;
myCompany.name = 'New name';
await session.db.update(myCompany);
diff --git a/docs/0.9.9/concepts/file-uploads.html b/docs/0.9.9/concepts/file-uploads.html index f5f91efc7..85ab68766 100644 --- a/docs/0.9.9/concepts/file-uploads.html +++ b/docs/0.9.9/concepts/file-uploads.html @@ -4,7 +4,7 @@ Uploading files | Serverpod - + diff --git a/docs/0.9.9/concepts/logging.html b/docs/0.9.9/concepts/logging.html index 48858e88f..5003250bc 100644 --- a/docs/0.9.9/concepts/logging.html +++ b/docs/0.9.9/concepts/logging.html @@ -4,7 +4,7 @@ Logging | Serverpod - + diff --git a/docs/0.9.9/concepts/modules.html b/docs/0.9.9/concepts/modules.html index b9fff58e5..8233ded3e 100644 --- a/docs/0.9.9/concepts/modules.html +++ b/docs/0.9.9/concepts/modules.html @@ -4,7 +4,7 @@ Modules | Serverpod - + diff --git a/docs/0.9.9/concepts/serialization.html b/docs/0.9.9/concepts/serialization.html index d3f93cad0..2a92613ab 100644 --- a/docs/0.9.9/concepts/serialization.html +++ b/docs/0.9.9/concepts/serialization.html @@ -4,7 +4,7 @@ Serialization | Serverpod - + diff --git a/docs/0.9.9/concepts/streams.html b/docs/0.9.9/concepts/streams.html index 4f3e80273..146777fec 100644 --- a/docs/0.9.9/concepts/streams.html +++ b/docs/0.9.9/concepts/streams.html @@ -4,7 +4,7 @@ Streams and messaging | Serverpod - + diff --git a/docs/0.9.9/concepts/webserver.html b/docs/0.9.9/concepts/webserver.html index 65347ca3d..68df0735c 100644 --- a/docs/0.9.9/concepts/webserver.html +++ b/docs/0.9.9/concepts/webserver.html @@ -4,7 +4,7 @@ Web server | Serverpod - + diff --git a/docs/0.9.9/concepts/working-with-endpoints.html b/docs/0.9.9/concepts/working-with-endpoints.html index 3bf25a029..78b91b713 100644 --- a/docs/0.9.9/concepts/working-with-endpoints.html +++ b/docs/0.9.9/concepts/working-with-endpoints.html @@ -4,7 +4,7 @@ Working with endpoints | Serverpod - + diff --git a/docs/0.9.9/contribute.html b/docs/0.9.9/contribute.html index 1663cf40a..ee57664fa 100644 --- a/docs/0.9.9/contribute.html +++ b/docs/0.9.9/contribute.html @@ -4,7 +4,7 @@ Contribute | Serverpod - + diff --git a/docs/0.9.9/deployments/deploying-to-aws.html b/docs/0.9.9/deployments/deploying-to-aws.html index 6f4b67376..e15bae994 100644 --- a/docs/0.9.9/deployments/deploying-to-aws.html +++ b/docs/0.9.9/deployments/deploying-to-aws.html @@ -4,7 +4,7 @@ Deploying to AWS | Serverpod - + diff --git a/docs/0.9.9/deployments/general.html b/docs/0.9.9/deployments/general.html index cc17be1cd..ff7a7428a 100644 --- a/docs/0.9.9/deployments/general.html +++ b/docs/0.9.9/deployments/general.html @@ -4,7 +4,7 @@ General notes | Serverpod - + diff --git a/docs/0.9.9/roadmap.html b/docs/0.9.9/roadmap.html index e27423123..9d0e7700a 100644 --- a/docs/0.9.9/roadmap.html +++ b/docs/0.9.9/roadmap.html @@ -4,7 +4,7 @@ Roadmap | Serverpod - + diff --git a/docs/0.9.9/support.html b/docs/0.9.9/support.html index 861f7cb1f..cf88c418b 100644 --- a/docs/0.9.9/support.html +++ b/docs/0.9.9/support.html @@ -4,7 +4,7 @@ Support & community | Serverpod - + diff --git a/docs/1.0.0.html b/docs/1.0.0.html index f6476ec95..8acf1a0f6 100644 --- a/docs/1.0.0.html +++ b/docs/1.0.0.html @@ -4,7 +4,7 @@ Get started | Serverpod - + diff --git a/docs/1.0.0/capabilities.html b/docs/1.0.0/capabilities.html index 16740a976..83f23365c 100644 --- a/docs/1.0.0/capabilities.html +++ b/docs/1.0.0/capabilities.html @@ -4,7 +4,7 @@ Capabilities | Serverpod - + diff --git a/docs/1.0.0/concepts/authentication.html b/docs/1.0.0/concepts/authentication.html index a0f53c528..ef37fd2c6 100644 --- a/docs/1.0.0/concepts/authentication.html +++ b/docs/1.0.0/concepts/authentication.html @@ -4,7 +4,7 @@ Authentication | Serverpod - + diff --git a/docs/1.0.0/concepts/backward-compatibility.html b/docs/1.0.0/concepts/backward-compatibility.html index 2a033ad91..fa3b64efc 100644 --- a/docs/1.0.0/concepts/backward-compatibility.html +++ b/docs/1.0.0/concepts/backward-compatibility.html @@ -4,7 +4,7 @@ Backward compatibility | Serverpod - + diff --git a/docs/1.0.0/concepts/caching.html b/docs/1.0.0/concepts/caching.html index b66c2d396..c84590642 100644 --- a/docs/1.0.0/concepts/caching.html +++ b/docs/1.0.0/concepts/caching.html @@ -4,7 +4,7 @@ Caching | Serverpod - + diff --git a/docs/1.0.0/concepts/database-communication.html b/docs/1.0.0/concepts/database-communication.html index 1fd6f039a..3ba1d663b 100644 --- a/docs/1.0.0/concepts/database-communication.html +++ b/docs/1.0.0/concepts/database-communication.html @@ -4,7 +4,7 @@ Database communication | Serverpod - + @@ -45,7 +45,7 @@

Finding
var myCompany = await Company.findSingleRow(
session,
where: (t) => t.name.equals('My Company'),
);

Finding multiple rows

To find multiple rows, use the same principle as for finding a single row. Returned will be a List of TableRows.

-
var companies = await Company.find(
tCompany,
where: (t) => t.id < 100,
limit 50,
);
+
var companies = await Company.find(
tCompany,
where: (t) => t.id < 100,
limit: 50,
);

Updating a row

To update a row, use the update method. The object that you update must have its id set to a non-null value.

var myCompany = await session.db.findById(tCompany, companyId) as Company?;
myCompany.name = 'New name';
await session.db.update(myCompany);
diff --git a/docs/1.0.0/concepts/file-uploads.html b/docs/1.0.0/concepts/file-uploads.html index 6a45c20e4..4a7d1516c 100644 --- a/docs/1.0.0/concepts/file-uploads.html +++ b/docs/1.0.0/concepts/file-uploads.html @@ -4,7 +4,7 @@ Uploading files | Serverpod - + diff --git a/docs/1.0.0/concepts/health-checks.html b/docs/1.0.0/concepts/health-checks.html index 9f18b896a..6dacf6c28 100644 --- a/docs/1.0.0/concepts/health-checks.html +++ b/docs/1.0.0/concepts/health-checks.html @@ -4,7 +4,7 @@ Health checks | Serverpod - + diff --git a/docs/1.0.0/concepts/logging.html b/docs/1.0.0/concepts/logging.html index 729a82098..3644e72c0 100644 --- a/docs/1.0.0/concepts/logging.html +++ b/docs/1.0.0/concepts/logging.html @@ -4,7 +4,7 @@ Logging | Serverpod - + diff --git a/docs/1.0.0/concepts/modules.html b/docs/1.0.0/concepts/modules.html index 4dc87b2cd..57ce464b4 100644 --- a/docs/1.0.0/concepts/modules.html +++ b/docs/1.0.0/concepts/modules.html @@ -4,7 +4,7 @@ Modules | Serverpod - + diff --git a/docs/1.0.0/concepts/serialization.html b/docs/1.0.0/concepts/serialization.html index ef1b49377..5ddb35f7c 100644 --- a/docs/1.0.0/concepts/serialization.html +++ b/docs/1.0.0/concepts/serialization.html @@ -4,7 +4,7 @@ Serialization | Serverpod - + diff --git a/docs/1.0.0/concepts/streams.html b/docs/1.0.0/concepts/streams.html index 36e7a4ddd..6a55fcc03 100644 --- a/docs/1.0.0/concepts/streams.html +++ b/docs/1.0.0/concepts/streams.html @@ -4,7 +4,7 @@ Streams and messaging | Serverpod - + diff --git a/docs/1.0.0/concepts/webserver.html b/docs/1.0.0/concepts/webserver.html index 4e607e063..2eca692df 100644 --- a/docs/1.0.0/concepts/webserver.html +++ b/docs/1.0.0/concepts/webserver.html @@ -4,7 +4,7 @@ Web server | Serverpod - + diff --git a/docs/1.0.0/concepts/working-with-endpoints.html b/docs/1.0.0/concepts/working-with-endpoints.html index db93bc1ee..85d717377 100644 --- a/docs/1.0.0/concepts/working-with-endpoints.html +++ b/docs/1.0.0/concepts/working-with-endpoints.html @@ -4,7 +4,7 @@ Working with endpoints | Serverpod - + diff --git a/docs/1.0.0/contribute.html b/docs/1.0.0/contribute.html index d42e81ee0..c5b2891ba 100644 --- a/docs/1.0.0/contribute.html +++ b/docs/1.0.0/contribute.html @@ -4,7 +4,7 @@ Contribute | Serverpod - + diff --git a/docs/1.0.0/deployments/deploying-to-aws.html b/docs/1.0.0/deployments/deploying-to-aws.html index 448fd658b..91614901c 100644 --- a/docs/1.0.0/deployments/deploying-to-aws.html +++ b/docs/1.0.0/deployments/deploying-to-aws.html @@ -4,7 +4,7 @@ Deploying to AWS | Serverpod - + diff --git a/docs/1.0.0/deployments/general.html b/docs/1.0.0/deployments/general.html index ff4e1d9ec..0c8bbf319 100644 --- a/docs/1.0.0/deployments/general.html +++ b/docs/1.0.0/deployments/general.html @@ -4,7 +4,7 @@ General notes | Serverpod - + diff --git a/docs/1.0.0/roadmap.html b/docs/1.0.0/roadmap.html index 719520949..ca31b5f3b 100644 --- a/docs/1.0.0/roadmap.html +++ b/docs/1.0.0/roadmap.html @@ -4,7 +4,7 @@ Roadmap | Serverpod - + diff --git a/docs/1.0.0/support.html b/docs/1.0.0/support.html index a00a1dea0..3fe6315b1 100644 --- a/docs/1.0.0/support.html +++ b/docs/1.0.0/support.html @@ -4,7 +4,7 @@ Support & community | Serverpod - + diff --git a/docs/1.0.0/tutorials.html b/docs/1.0.0/tutorials.html index 50dc65732..2ba9cb6fe 100644 --- a/docs/1.0.0/tutorials.html +++ b/docs/1.0.0/tutorials.html @@ -4,7 +4,7 @@ Tutorials & Examples | Serverpod - + diff --git a/docs/1.1.0.html b/docs/1.1.0.html index 06c3ceda2..419498353 100644 --- a/docs/1.1.0.html +++ b/docs/1.1.0.html @@ -4,7 +4,7 @@ Get started | Serverpod - + diff --git a/docs/1.1.0/capabilities.html b/docs/1.1.0/capabilities.html index 85a2a7e1b..6297e1183 100644 --- a/docs/1.1.0/capabilities.html +++ b/docs/1.1.0/capabilities.html @@ -4,7 +4,7 @@ Capabilities | Serverpod - + diff --git a/docs/1.1.0/concepts/authentication.html b/docs/1.1.0/concepts/authentication.html index 6b86cd5ba..47c212acf 100644 --- a/docs/1.1.0/concepts/authentication.html +++ b/docs/1.1.0/concepts/authentication.html @@ -4,7 +4,7 @@ Authentication | Serverpod - + diff --git a/docs/1.1.0/concepts/backward-compatibility.html b/docs/1.1.0/concepts/backward-compatibility.html index 58460eea9..267a760c9 100644 --- a/docs/1.1.0/concepts/backward-compatibility.html +++ b/docs/1.1.0/concepts/backward-compatibility.html @@ -4,7 +4,7 @@ Backward compatibility | Serverpod - + diff --git a/docs/1.1.0/concepts/caching.html b/docs/1.1.0/concepts/caching.html index d33dd8feb..21a843600 100644 --- a/docs/1.1.0/concepts/caching.html +++ b/docs/1.1.0/concepts/caching.html @@ -4,7 +4,7 @@ Caching | Serverpod - + diff --git a/docs/1.1.0/concepts/database-communication.html b/docs/1.1.0/concepts/database-communication.html index d07657a48..bc21e8aa3 100644 --- a/docs/1.1.0/concepts/database-communication.html +++ b/docs/1.1.0/concepts/database-communication.html @@ -4,7 +4,7 @@ Database communication | Serverpod - + @@ -45,7 +45,7 @@

Finding
var myCompany = await Company.findSingleRow(
session,
where: (t) => t.name.equals('My Company'),
);

Finding multiple rows

To find multiple rows, use the same principle as for finding a single row. Returned will be a List of TableRows.

-
var companies = await Company.find(
tCompany,
where: (t) => t.id < 100,
limit 50,
);
+
var companies = await Company.find(
tCompany,
where: (t) => t.id < 100,
limit: 50,
);

Updating a row

To update a row, use the update method. The object that you update must have its id set to a non-null value.

var myCompany = await session.db.findById(tCompany, companyId) as Company?;
myCompany.name = 'New name';
await session.db.update(myCompany);
diff --git a/docs/1.1.0/concepts/exceptions.html b/docs/1.1.0/concepts/exceptions.html index 0e619c1a9..49ccedba7 100644 --- a/docs/1.1.0/concepts/exceptions.html +++ b/docs/1.1.0/concepts/exceptions.html @@ -4,7 +4,7 @@ Error handling and exceptions | Serverpod - + diff --git a/docs/1.1.0/concepts/file-uploads.html b/docs/1.1.0/concepts/file-uploads.html index 34dbbbbb9..c52838a7a 100644 --- a/docs/1.1.0/concepts/file-uploads.html +++ b/docs/1.1.0/concepts/file-uploads.html @@ -4,7 +4,7 @@ Uploading files | Serverpod - + diff --git a/docs/1.1.0/concepts/health-checks.html b/docs/1.1.0/concepts/health-checks.html index 3c6ea6d85..ac091d4e6 100644 --- a/docs/1.1.0/concepts/health-checks.html +++ b/docs/1.1.0/concepts/health-checks.html @@ -4,7 +4,7 @@ Health checks | Serverpod - + diff --git a/docs/1.1.0/concepts/logging.html b/docs/1.1.0/concepts/logging.html index 4f6328b01..7d70e380a 100644 --- a/docs/1.1.0/concepts/logging.html +++ b/docs/1.1.0/concepts/logging.html @@ -4,7 +4,7 @@ Logging | Serverpod - + diff --git a/docs/1.1.0/concepts/modules.html b/docs/1.1.0/concepts/modules.html index 46fe10d93..962564531 100644 --- a/docs/1.1.0/concepts/modules.html +++ b/docs/1.1.0/concepts/modules.html @@ -4,7 +4,7 @@ Modules | Serverpod - + diff --git a/docs/1.1.0/concepts/serialization.html b/docs/1.1.0/concepts/serialization.html index 7ec951fa8..1b06f9652 100644 --- a/docs/1.1.0/concepts/serialization.html +++ b/docs/1.1.0/concepts/serialization.html @@ -4,7 +4,7 @@ Serialization | Serverpod - + diff --git a/docs/1.1.0/concepts/sessions.html b/docs/1.1.0/concepts/sessions.html index ed78ff1c9..9e69b6fbf 100644 --- a/docs/1.1.0/concepts/sessions.html +++ b/docs/1.1.0/concepts/sessions.html @@ -4,7 +4,7 @@ Sessions | Serverpod - + diff --git a/docs/1.1.0/concepts/streams.html b/docs/1.1.0/concepts/streams.html index 48c048122..d1f0a3801 100644 --- a/docs/1.1.0/concepts/streams.html +++ b/docs/1.1.0/concepts/streams.html @@ -4,7 +4,7 @@ Streams and messaging | Serverpod - + diff --git a/docs/1.1.0/concepts/webserver.html b/docs/1.1.0/concepts/webserver.html index 350285649..5d2d2ed6e 100644 --- a/docs/1.1.0/concepts/webserver.html +++ b/docs/1.1.0/concepts/webserver.html @@ -4,7 +4,7 @@ Web server | Serverpod - + diff --git a/docs/1.1.0/concepts/working-with-endpoints.html b/docs/1.1.0/concepts/working-with-endpoints.html index adf45bd7e..31aa958dd 100644 --- a/docs/1.1.0/concepts/working-with-endpoints.html +++ b/docs/1.1.0/concepts/working-with-endpoints.html @@ -4,7 +4,7 @@ Working with endpoints | Serverpod - + diff --git a/docs/1.1.0/contribute.html b/docs/1.1.0/contribute.html index 015db993a..176c820db 100644 --- a/docs/1.1.0/contribute.html +++ b/docs/1.1.0/contribute.html @@ -4,7 +4,7 @@ Contribute | Serverpod - + diff --git a/docs/1.1.0/deployments/deploying-to-aws.html b/docs/1.1.0/deployments/deploying-to-aws.html index 7d43f73bc..d4221a244 100644 --- a/docs/1.1.0/deployments/deploying-to-aws.html +++ b/docs/1.1.0/deployments/deploying-to-aws.html @@ -4,7 +4,7 @@ AWS EC2 with Terraform | Serverpod - + diff --git a/docs/1.1.0/deployments/deploying-to-gce-terraform.html b/docs/1.1.0/deployments/deploying-to-gce-terraform.html index f91858819..e5ac77e16 100644 --- a/docs/1.1.0/deployments/deploying-to-gce-terraform.html +++ b/docs/1.1.0/deployments/deploying-to-gce-terraform.html @@ -4,7 +4,7 @@ Google Cloud Engine with Terraform | Serverpod - + diff --git a/docs/1.1.0/deployments/deploying-to-gcr-console.html b/docs/1.1.0/deployments/deploying-to-gcr-console.html index b4f929515..3242e19f0 100644 --- a/docs/1.1.0/deployments/deploying-to-gcr-console.html +++ b/docs/1.1.0/deployments/deploying-to-gcr-console.html @@ -4,7 +4,7 @@ Google Cloud Run with CGP Console | Serverpod - + diff --git a/docs/1.1.0/deployments/deployment-strategy.html b/docs/1.1.0/deployments/deployment-strategy.html index 0428abce3..2defdf24a 100644 --- a/docs/1.1.0/deployments/deployment-strategy.html +++ b/docs/1.1.0/deployments/deployment-strategy.html @@ -4,7 +4,7 @@ Choosing deployment strategy | Serverpod - + diff --git a/docs/1.1.0/deployments/general.html b/docs/1.1.0/deployments/general.html index 79b835ff3..cad3eb75a 100644 --- a/docs/1.1.0/deployments/general.html +++ b/docs/1.1.0/deployments/general.html @@ -4,7 +4,7 @@ Hosting elsewhere | Serverpod - + diff --git a/docs/1.1.0/insights.html b/docs/1.1.0/insights.html index 30697bf53..9c5dbde27 100644 --- a/docs/1.1.0/insights.html +++ b/docs/1.1.0/insights.html @@ -4,7 +4,7 @@ Serverpod Insights | Serverpod - + diff --git a/docs/1.1.0/roadmap.html b/docs/1.1.0/roadmap.html index a124e8cd7..cc0499829 100644 --- a/docs/1.1.0/roadmap.html +++ b/docs/1.1.0/roadmap.html @@ -4,7 +4,7 @@ Roadmap | Serverpod - + diff --git a/docs/1.1.0/support.html b/docs/1.1.0/support.html index 073752597..1ae848b83 100644 --- a/docs/1.1.0/support.html +++ b/docs/1.1.0/support.html @@ -4,7 +4,7 @@ Support & community | Serverpod - + diff --git a/docs/1.1.0/tutorials.html b/docs/1.1.0/tutorials.html index 4cadb77aa..3036e44a4 100644 --- a/docs/1.1.0/tutorials.html +++ b/docs/1.1.0/tutorials.html @@ -4,7 +4,7 @@ Tutorials & Examples | Serverpod - + diff --git a/docs/1.1.1.html b/docs/1.1.1.html index e42ea1302..64ef0780b 100644 --- a/docs/1.1.1.html +++ b/docs/1.1.1.html @@ -4,7 +4,7 @@ Installing Serverpod | Serverpod - + diff --git a/docs/1.1.1/capabilities.html b/docs/1.1.1/capabilities.html index d513228a7..50a2d0c58 100644 --- a/docs/1.1.1/capabilities.html +++ b/docs/1.1.1/capabilities.html @@ -4,7 +4,7 @@ Capabilities | Serverpod - + diff --git a/docs/1.1.1/concepts/authentication/basics.html b/docs/1.1.1/concepts/authentication/basics.html index 15e661e29..d7a3d23c9 100644 --- a/docs/1.1.1/concepts/authentication/basics.html +++ b/docs/1.1.1/concepts/authentication/basics.html @@ -4,7 +4,7 @@ The basics | Serverpod - + diff --git a/docs/1.1.1/concepts/authentication/providers/apple.html b/docs/1.1.1/concepts/authentication/providers/apple.html index 6a115442c..e8fe91e72 100644 --- a/docs/1.1.1/concepts/authentication/providers/apple.html +++ b/docs/1.1.1/concepts/authentication/providers/apple.html @@ -4,7 +4,7 @@ Apple | Serverpod - + diff --git a/docs/1.1.1/concepts/authentication/providers/email.html b/docs/1.1.1/concepts/authentication/providers/email.html index 2c28c807a..792a211e6 100644 --- a/docs/1.1.1/concepts/authentication/providers/email.html +++ b/docs/1.1.1/concepts/authentication/providers/email.html @@ -4,7 +4,7 @@ Email | Serverpod - + diff --git a/docs/1.1.1/concepts/authentication/providers/firebase.html b/docs/1.1.1/concepts/authentication/providers/firebase.html index 5c44ab208..7dae3d181 100644 --- a/docs/1.1.1/concepts/authentication/providers/firebase.html +++ b/docs/1.1.1/concepts/authentication/providers/firebase.html @@ -4,7 +4,7 @@ Firebase | Serverpod - + diff --git a/docs/1.1.1/concepts/authentication/providers/google.html b/docs/1.1.1/concepts/authentication/providers/google.html index 9264064b3..d07be7a85 100644 --- a/docs/1.1.1/concepts/authentication/providers/google.html +++ b/docs/1.1.1/concepts/authentication/providers/google.html @@ -4,7 +4,7 @@ Google | Serverpod - + diff --git a/docs/1.1.1/concepts/authentication/setup.html b/docs/1.1.1/concepts/authentication/setup.html index b4c98ab14..a2d63b6c1 100644 --- a/docs/1.1.1/concepts/authentication/setup.html +++ b/docs/1.1.1/concepts/authentication/setup.html @@ -4,7 +4,7 @@ Setup | Serverpod - + diff --git a/docs/1.1.1/concepts/authentication/working-with-users.html b/docs/1.1.1/concepts/authentication/working-with-users.html index ba7bbbd56..2af2c02e1 100644 --- a/docs/1.1.1/concepts/authentication/working-with-users.html +++ b/docs/1.1.1/concepts/authentication/working-with-users.html @@ -4,7 +4,7 @@ Working with users | Serverpod - + diff --git a/docs/1.1.1/concepts/backward-compatibility.html b/docs/1.1.1/concepts/backward-compatibility.html index 8248a4ce1..1593441dc 100644 --- a/docs/1.1.1/concepts/backward-compatibility.html +++ b/docs/1.1.1/concepts/backward-compatibility.html @@ -4,7 +4,7 @@ Backward compatibility | Serverpod - + diff --git a/docs/1.1.1/concepts/caching.html b/docs/1.1.1/concepts/caching.html index 63cd9659f..931459134 100644 --- a/docs/1.1.1/concepts/caching.html +++ b/docs/1.1.1/concepts/caching.html @@ -4,7 +4,7 @@ Caching | Serverpod - + diff --git a/docs/1.1.1/concepts/database-communication.html b/docs/1.1.1/concepts/database-communication.html index f07b1cf51..40c193207 100644 --- a/docs/1.1.1/concepts/database-communication.html +++ b/docs/1.1.1/concepts/database-communication.html @@ -4,7 +4,7 @@ Database communication | Serverpod - + @@ -45,7 +45,7 @@

Finding
var myCompany = await Company.findSingleRow(
session,
where: (t) => t.name.equals('My Company'),
);

Finding multiple rows

To find multiple rows, use the same principle as for finding a single row. Returned will be a List of TableRows.

-
var companies = await Company.find(
session,
where: (t) => t.id < 100,
limit 50,
);
+
var companies = await Company.find(
session,
where: (t) => t.id < 100,
limit: 50,
);

Updating a row

To update a row, use the update method. The object that you update must have its id set to a non-null value.

var myCompany = await Company.findById(session, companyId);
myCompany.name = 'New name';
await session.db.update(myCompany);
diff --git a/docs/1.1.1/concepts/exceptions.html b/docs/1.1.1/concepts/exceptions.html index 49c0733f8..f025c7360 100644 --- a/docs/1.1.1/concepts/exceptions.html +++ b/docs/1.1.1/concepts/exceptions.html @@ -4,7 +4,7 @@ Error handling and exceptions | Serverpod - + diff --git a/docs/1.1.1/concepts/file-uploads.html b/docs/1.1.1/concepts/file-uploads.html index 743661c6a..4c826ced4 100644 --- a/docs/1.1.1/concepts/file-uploads.html +++ b/docs/1.1.1/concepts/file-uploads.html @@ -4,7 +4,7 @@ Uploading files | Serverpod - + diff --git a/docs/1.1.1/concepts/health-checks.html b/docs/1.1.1/concepts/health-checks.html index 15404300b..78be48eb2 100644 --- a/docs/1.1.1/concepts/health-checks.html +++ b/docs/1.1.1/concepts/health-checks.html @@ -4,7 +4,7 @@ Health checks | Serverpod - + diff --git a/docs/1.1.1/concepts/logging.html b/docs/1.1.1/concepts/logging.html index 96e8330db..50b9bc6bd 100644 --- a/docs/1.1.1/concepts/logging.html +++ b/docs/1.1.1/concepts/logging.html @@ -4,7 +4,7 @@ Logging | Serverpod - + diff --git a/docs/1.1.1/concepts/modules.html b/docs/1.1.1/concepts/modules.html index e3bdff62c..0395ce19a 100644 --- a/docs/1.1.1/concepts/modules.html +++ b/docs/1.1.1/concepts/modules.html @@ -4,7 +4,7 @@ Modules | Serverpod - + diff --git a/docs/1.1.1/concepts/serialization.html b/docs/1.1.1/concepts/serialization.html index a74023e21..d68dc4eaa 100644 --- a/docs/1.1.1/concepts/serialization.html +++ b/docs/1.1.1/concepts/serialization.html @@ -4,7 +4,7 @@ Serialization | Serverpod - + diff --git a/docs/1.1.1/concepts/sessions.html b/docs/1.1.1/concepts/sessions.html index a40cf3984..71f77e341 100644 --- a/docs/1.1.1/concepts/sessions.html +++ b/docs/1.1.1/concepts/sessions.html @@ -4,7 +4,7 @@ Sessions | Serverpod - + diff --git a/docs/1.1.1/concepts/streams.html b/docs/1.1.1/concepts/streams.html index c56df3830..6884fb89e 100644 --- a/docs/1.1.1/concepts/streams.html +++ b/docs/1.1.1/concepts/streams.html @@ -4,7 +4,7 @@ Streams and messaging | Serverpod - + diff --git a/docs/1.1.1/concepts/webserver.html b/docs/1.1.1/concepts/webserver.html index ed8865db2..714a9a082 100644 --- a/docs/1.1.1/concepts/webserver.html +++ b/docs/1.1.1/concepts/webserver.html @@ -4,7 +4,7 @@ Web server | Serverpod - + diff --git a/docs/1.1.1/concepts/working-with-endpoints.html b/docs/1.1.1/concepts/working-with-endpoints.html index 7e2989080..85b01f26a 100644 --- a/docs/1.1.1/concepts/working-with-endpoints.html +++ b/docs/1.1.1/concepts/working-with-endpoints.html @@ -4,7 +4,7 @@ Working with endpoints | Serverpod - + diff --git a/docs/1.1.1/contribute.html b/docs/1.1.1/contribute.html index 19f4e7ff0..078ed594e 100644 --- a/docs/1.1.1/contribute.html +++ b/docs/1.1.1/contribute.html @@ -4,7 +4,7 @@ Contribute | Serverpod - + diff --git a/docs/1.1.1/deployments/deploying-to-aws.html b/docs/1.1.1/deployments/deploying-to-aws.html index a7d136699..77ecf0ce0 100644 --- a/docs/1.1.1/deployments/deploying-to-aws.html +++ b/docs/1.1.1/deployments/deploying-to-aws.html @@ -4,7 +4,7 @@ AWS EC2 with Terraform | Serverpod - + diff --git a/docs/1.1.1/deployments/deploying-to-gce-terraform.html b/docs/1.1.1/deployments/deploying-to-gce-terraform.html index a039f770b..f8413c554 100644 --- a/docs/1.1.1/deployments/deploying-to-gce-terraform.html +++ b/docs/1.1.1/deployments/deploying-to-gce-terraform.html @@ -4,7 +4,7 @@ Google Cloud Engine with Terraform | Serverpod - + diff --git a/docs/1.1.1/deployments/deploying-to-gcr-console.html b/docs/1.1.1/deployments/deploying-to-gcr-console.html index 9b54b287c..f8883b477 100644 --- a/docs/1.1.1/deployments/deploying-to-gcr-console.html +++ b/docs/1.1.1/deployments/deploying-to-gcr-console.html @@ -4,7 +4,7 @@ Google Cloud Run with CGP Console | Serverpod - + diff --git a/docs/1.1.1/deployments/deployment-strategy.html b/docs/1.1.1/deployments/deployment-strategy.html index 176912a94..067b1d1d5 100644 --- a/docs/1.1.1/deployments/deployment-strategy.html +++ b/docs/1.1.1/deployments/deployment-strategy.html @@ -4,7 +4,7 @@ Choosing deployment strategy | Serverpod - + diff --git a/docs/1.1.1/deployments/general.html b/docs/1.1.1/deployments/general.html index e99e466b8..9c9aad415 100644 --- a/docs/1.1.1/deployments/general.html +++ b/docs/1.1.1/deployments/general.html @@ -4,7 +4,7 @@ Hosting elsewhere | Serverpod - + diff --git a/docs/1.1.1/get-started.html b/docs/1.1.1/get-started.html index 64db65e5d..4a4a32a9e 100644 --- a/docs/1.1.1/get-started.html +++ b/docs/1.1.1/get-started.html @@ -4,7 +4,7 @@ Get started | Serverpod - + diff --git a/docs/1.1.1/insights.html b/docs/1.1.1/insights.html index 21d463ff7..a7f878f82 100644 --- a/docs/1.1.1/insights.html +++ b/docs/1.1.1/insights.html @@ -4,7 +4,7 @@ Serverpod Insights | Serverpod - + diff --git a/docs/1.1.1/roadmap.html b/docs/1.1.1/roadmap.html index 9dc5ca550..cf37884f0 100644 --- a/docs/1.1.1/roadmap.html +++ b/docs/1.1.1/roadmap.html @@ -4,7 +4,7 @@ Roadmap | Serverpod - + diff --git a/docs/1.1.1/support.html b/docs/1.1.1/support.html index 012753009..b47968fde 100644 --- a/docs/1.1.1/support.html +++ b/docs/1.1.1/support.html @@ -4,7 +4,7 @@ Support & community | Serverpod - + diff --git a/docs/1.1.1/tutorials/authentication.html b/docs/1.1.1/tutorials/authentication.html index 38e98993d..77c85b3e9 100644 --- a/docs/1.1.1/tutorials/authentication.html +++ b/docs/1.1.1/tutorials/authentication.html @@ -4,7 +4,7 @@ Authentication | Serverpod - + diff --git a/docs/1.1.1/tutorials/code-example.html b/docs/1.1.1/tutorials/code-example.html index da5d5a6ea..f63a69b63 100644 --- a/docs/1.1.1/tutorials/code-example.html +++ b/docs/1.1.1/tutorials/code-example.html @@ -4,7 +4,7 @@ Code examples | Serverpod - + diff --git a/docs/1.1.1/tutorials/first-app.html b/docs/1.1.1/tutorials/first-app.html index 6de4b5cf3..893bd17f8 100644 --- a/docs/1.1.1/tutorials/first-app.html +++ b/docs/1.1.1/tutorials/first-app.html @@ -4,7 +4,7 @@ Build your first app | Serverpod - + diff --git a/docs/1.1.1/tutorials/videos.html b/docs/1.1.1/tutorials/videos.html index 04ef48869..9c6ab5934 100644 --- a/docs/1.1.1/tutorials/videos.html +++ b/docs/1.1.1/tutorials/videos.html @@ -4,7 +4,7 @@ Videos | Serverpod - + diff --git a/docs/404.html b/docs/404.html index 31b64371d..d6c019398 100644 --- a/docs/404.html +++ b/docs/404.html @@ -4,7 +4,7 @@ Serverpod - + diff --git a/docs/assets/js/056b386b.3eb1996f.js b/docs/assets/js/056b386b.3eb1996f.js new file mode 100644 index 000000000..212ae7562 --- /dev/null +++ b/docs/assets/js/056b386b.3eb1996f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkserverpod_docs=self.webpackChunkserverpod_docs||[]).push([[8571],{95429:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>t,metadata:()=>r,toc:()=>l});var s=a(85893),i=a(11151);const t={},o="Database communication",r={id:"concepts/database-communication",title:"Database communication",description:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files.",source:"@site/versioned_docs/version-0.9.7/03-concepts/03-database-communication.md",sourceDirName:"03-concepts",slug:"/concepts/database-communication",permalink:"/0.9.7/concepts/database-communication",draft:!1,unlisted:!1,editUrl:"https://github.com/serverpod/serverpod_docs/tree/main/versioned_docs/version-0.9.7/03-concepts/03-database-communication.md",tags:[],version:"0.9.7",sidebarPosition:3,frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Serialization",permalink:"/0.9.7/concepts/serialization"},next:{title:"Caching",permalink:"/0.9.7/concepts/caching"}},d={},l=[{value:"Database mappings",id:"database-mappings",level:2},{value:"Database indexes",id:"database-indexes",level:3},{value:"Making queries",id:"making-queries",level:2},{value:"Inserting a table row",id:"inserting-a-table-row",level:3},{value:"Finding a single row",id:"finding-a-single-row",level:3},{value:"Finding multiple rows",id:"finding-multiple-rows",level:3},{value:"Updating a row",id:"updating-a-row",level:3},{value:"Deleting rows",id:"deleting-rows",level:3},{value:"Creating expressions",id:"creating-expressions",level:3},{value:"Transactions",id:"transactions",level:3},{value:"Executing raw queries",id:"executing-raw-queries",level:3}];function c(e){const n={code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,i.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"database-communication",children:"Database communication"}),"\n",(0,s.jsx)(n.p,{children:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files."}),"\n",(0,s.jsx)(n.h2,{id:"database-mappings",children:"Database mappings"}),"\n",(0,s.jsxs)(n.p,{children:["It's possible to map serializable classes straight to tables in your database. To do this, add the ",(0,s.jsx)(n.code,{children:"table"})," key to your yaml file:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n employees: List\n"})}),"\n",(0,s.jsxs)(n.p,{children:["When running ",(0,s.jsx)(n.code,{children:"serverpod generate"}),", the database schema will be saved in the ",(0,s.jsx)(n.code,{children:"generated/tables.pgsql"})," file. You can use this to create the corresponding database tables."]}),"\n",(0,s.jsxs)(n.p,{children:["In some cases, you want to save a field to the database, but it should never be sent to the server. You can exclude it from the protocol by adding the ",(0,s.jsx)(n.code,{children:"database"})," flag to the type."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: UserData\nfields:\n name: String\n password: String, database\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Likewise, if you only want a field to be accessible in the protocol but not stored in the server, you can add the ",(0,s.jsx)(n.code,{children:"api"})," flag. By default, a field is accessible to both the API and the database."]}),"\n",(0,s.jsx)(n.h3,{id:"database-indexes",children:"Database indexes"}),"\n",(0,s.jsx)(n.p,{children:"For performance reasons, you may want to add indexes to your database tables. You add these in the yaml-files defining the serializable objects."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n employees: List\nindexes:\n company_name_idx:\n fields: name\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"fields"})," key holds a comma-separated list of column names. In addition, it's possible to add a type key (default is ",(0,s.jsx)(n.code,{children:"btree"}),"), and a ",(0,s.jsx)(n.code,{children:"unique"})," key (default is ",(0,s.jsx)(n.code,{children:"false"}),")."]}),"\n",(0,s.jsx)(n.h2,{id:"making-queries",children:"Making queries"}),"\n",(0,s.jsxs)(n.p,{children:["For the communication to work, you need to have generated serializable classes with the ",(0,s.jsx)(n.code,{children:"table"})," key set, and the corresponding table must have been created in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"inserting-a-table-row",children:"Inserting a table row"}),"\n",(0,s.jsxs)(n.p,{children:["Insert a new row in the database by calling the insert method of the ",(0,s.jsx)(n.code,{children:"db"})," field in your ",(0,s.jsx)(n.code,{children:"Session"})," object."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myRow = Company(name: 'Serverpod corp.', employees: []);\nawait Company.insert(session, myRow);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["After the object has been inserted, it's ",(0,s.jsx)(n.code,{children:"id"})," field is set from its row in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"finding-a-single-row",children:"Finding a single row"}),"\n",(0,s.jsxs)(n.p,{children:["You can find a single row, either by its ",(0,s.jsx)(n.code,{children:"id"})," or using an expression. You need to pass a reference to the a session in the call. Tables are accessible through generated serializable classes."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findById(session, companyId);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If no matching row is found, ",(0,s.jsx)(n.code,{children:"null"})," is returned. You can also search for rows using expressions with the ",(0,s.jsx)(n.code,{children:"where"})," parameter. The ",(0,s.jsx)(n.code,{children:"where"})," parameter is a typed expression builder. The builder's parameter, ",(0,s.jsx)(n.code,{children:"t"}),", contains a description of the table which gives access to the table's columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findSingleRow(\n session,\n where: (t) => t.name.equals('My Company'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"finding-multiple-rows",children:"Finding multiple rows"}),"\n",(0,s.jsxs)(n.p,{children:["To find multiple rows, use the same principle as for finding a single row. Returned will be a ",(0,s.jsx)(n.code,{children:"List"})," of ",(0,s.jsx)(n.code,{children:"TableRow"}),"s."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var companies = await Company.find(\n tCompany,\n where: (t) => t.id < 100,\n limit: 50,\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"updating-a-row",children:"Updating a row"}),"\n",(0,s.jsxs)(n.p,{children:["To update a row, use the ",(0,s.jsx)(n.code,{children:"update"})," method. The object that you update must have its ",(0,s.jsx)(n.code,{children:"id"})," set to a non ",(0,s.jsx)(n.code,{children:"null"})," value."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await session.db.findById(tCompany, companyId) as Company?;\nmyCompany.name = 'New name';\nawait session.db.update(myCompany);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"deleting-rows",children:"Deleting rows"}),"\n",(0,s.jsxs)(n.p,{children:["Deleting a single row works similarly to the ",(0,s.jsx)(n.code,{children:"update"})," method, but you can also delete rows using the where parameter."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// Delete a single row\nawait Company.deleteRow(session, myCompany);\n\n// Delete all rows where the company name ends with 'Ltd'\nawait Company.delete(\n where: (t) => t.name.like('%Ltd'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"creating-expressions",children:"Creating expressions"}),"\n",(0,s.jsxs)(n.p,{children:["To find or delete specific rows, most often, expressions are needed. Serverpod makes it easy to build expressions that are statically type-checked. Columns are referenced using the global table descriptor objects. The table descriptors, ",(0,s.jsx)(n.code,{children:"t"})," are passed to the expression builder function. The ",(0,s.jsx)(n.code,{children:">"}),", ",(0,s.jsx)(n.code,{children:">="}),", ",(0,s.jsx)(n.code,{children:"<"}),", ",(0,s.jsx)(n.code,{children:"<="}),", ",(0,s.jsx)(n.code,{children:"&"}),", and ",(0,s.jsx)(n.code,{children:"|"})," operators are overridden to make it easier to work with column values. When using the operators, it's a good practice to place them within a set of parentheses as the precedence rules are not always what would be expected. These are some examples of expressions."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// The name column of the Company table equals 'My company')\nt.name.equals('My company')\n\n// Companies founded at or after 2020\nt.foundedDate >= DateTime.utc(2020)\n\n// Companies with number of employees between 10 and 100\n(t.numEmployees > 10) & (t.numEmployees <= 100)\n\n// Companies that has the founded date set\nt.foundedDate.notEquals(null)\n"})}),"\n",(0,s.jsx)(n.h3,{id:"transactions",children:"Transactions"}),"\n",(0,s.jsx)(n.p,{children:"Docs coming."}),"\n",(0,s.jsx)(n.h3,{id:"executing-raw-queries",children:"Executing raw queries"}),"\n",(0,s.jsxs)(n.p,{children:["Sometimes more advanced tasks need to be performed on the database. For those occasions, it's possible to run raw SQL queries on the database. Use the ",(0,s.jsx)(n.code,{children:"query"})," method. A ",(0,s.jsx)(n.code,{children:"List>"})," will be returned with rows and columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var result = await session.db.query('SELECT * FROM mytable WHERE ...');\n"})})]})}function h(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},11151:(e,n,a)=>{a.d(n,{Z:()=>r,a:()=>o});var s=a(67294);const i={},t=s.createContext(i);function o(e){const n=s.useContext(t);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/4c781063.f02dc04a.js b/docs/assets/js/4c781063.f02dc04a.js new file mode 100644 index 000000000..5204c4076 --- /dev/null +++ b/docs/assets/js/4c781063.f02dc04a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkserverpod_docs=self.webpackChunkserverpod_docs||[]).push([[9639],{75556:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>r,contentTitle:()=>o,default:()=>h,frontMatter:()=>t,metadata:()=>d,toc:()=>l});var s=a(85893),i=a(11151);const t={},o="Database communication",d={id:"concepts/database-communication",title:"Database communication",description:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files.",source:"@site/versioned_docs/version-0.9.11/03-concepts/03-database-communication.md",sourceDirName:"03-concepts",slug:"/concepts/database-communication",permalink:"/0.9.11/concepts/database-communication",draft:!1,unlisted:!1,editUrl:"https://github.com/serverpod/serverpod_docs/tree/main/versioned_docs/version-0.9.11/03-concepts/03-database-communication.md",tags:[],version:"0.9.11",sidebarPosition:3,frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Serialization",permalink:"/0.9.11/concepts/serialization"},next:{title:"Caching",permalink:"/0.9.11/concepts/caching"}},r={},l=[{value:"Database mappings",id:"database-mappings",level:2},{value:"Database indexes",id:"database-indexes",level:3},{value:"Making queries",id:"making-queries",level:2},{value:"Inserting a table row",id:"inserting-a-table-row",level:3},{value:"Finding a single row",id:"finding-a-single-row",level:3},{value:"Finding multiple rows",id:"finding-multiple-rows",level:3},{value:"Updating a row",id:"updating-a-row",level:3},{value:"Deleting rows",id:"deleting-rows",level:3},{value:"Creating expressions",id:"creating-expressions",level:3},{value:"Transactions",id:"transactions",level:3},{value:"Executing raw queries",id:"executing-raw-queries",level:3}];function c(e){const n={admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,i.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"database-communication",children:"Database communication"}),"\n",(0,s.jsx)(n.p,{children:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files."}),"\n",(0,s.jsx)(n.h2,{id:"database-mappings",children:"Database mappings"}),"\n",(0,s.jsxs)(n.p,{children:["It's possible to map serializable classes straight to tables in your database. To do this, add the ",(0,s.jsx)(n.code,{children:"table"})," key to your yaml file:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n employees: List\n"})}),"\n",(0,s.jsxs)(n.p,{children:["When running ",(0,s.jsx)(n.code,{children:"serverpod generate"}),", the database schema will be saved in the ",(0,s.jsx)(n.code,{children:"generated/tables.pgsql"})," file. You can use this to create the corresponding database tables."]}),"\n",(0,s.jsxs)(n.p,{children:["In some cases, you want to save a field to the database, but it should never be sent to the server. You can exclude it from the protocol by adding the ",(0,s.jsx)(n.code,{children:"database"})," flag to the type."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: UserData\nfields:\n name: String\n password: String?, database\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Likewise, if you only want a field to be accessible in the protocol but not stored in the server, you can add the ",(0,s.jsx)(n.code,{children:"api"})," flag. By default, a field is accessible to both the API and the database."]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["If you use the ",(0,s.jsx)(n.code,{children:"database"})," or ",(0,s.jsx)(n.code,{children:"api"})," options the field must be nullable."]})}),"\n",(0,s.jsx)(n.h3,{id:"database-indexes",children:"Database indexes"}),"\n",(0,s.jsx)(n.p,{children:"For performance reasons, you may want to add indexes to your database tables. You add these in the yaml-files defining the serializable objects."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n employees: List\nindexes:\n company_name_idx:\n fields: name\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"fields"})," key holds a comma-separated list of column names. In addition, it's possible to add a type key (default is ",(0,s.jsx)(n.code,{children:"btree"}),"), and a ",(0,s.jsx)(n.code,{children:"unique"})," key (default is ",(0,s.jsx)(n.code,{children:"false"}),")."]}),"\n",(0,s.jsx)(n.h2,{id:"making-queries",children:"Making queries"}),"\n",(0,s.jsxs)(n.p,{children:["For the communication to work, you need to have generated serializable classes with the ",(0,s.jsx)(n.code,{children:"table"})," key set, and the corresponding table must have been created in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"inserting-a-table-row",children:"Inserting a table row"}),"\n",(0,s.jsxs)(n.p,{children:["Insert a new row in the database by calling the insert method of the ",(0,s.jsx)(n.code,{children:"db"})," field in your ",(0,s.jsx)(n.code,{children:"Session"})," object."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myRow = Company(name: 'Serverpod corp.', employees: []);\nawait Company.insert(session, myRow);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["After the object has been inserted, it's ",(0,s.jsx)(n.code,{children:"id"})," field is set from its row in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"finding-a-single-row",children:"Finding a single row"}),"\n",(0,s.jsxs)(n.p,{children:["You can find a single row, either by its ",(0,s.jsx)(n.code,{children:"id"})," or using an expression. You need to pass a reference to the a session in the call. Tables are accessible through generated serializable classes."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findById(session, companyId);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If no matching row is found, ",(0,s.jsx)(n.code,{children:"null"})," is returned. You can also search for rows using expressions with the ",(0,s.jsx)(n.code,{children:"where"})," parameter. The ",(0,s.jsx)(n.code,{children:"where"})," parameter is a typed expression builder. The builder's parameter, ",(0,s.jsx)(n.code,{children:"t"}),", contains a description of the table which gives access to the table's columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findSingleRow(\n session,\n where: (t) => t.name.equals('My Company'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"finding-multiple-rows",children:"Finding multiple rows"}),"\n",(0,s.jsxs)(n.p,{children:["To find multiple rows, use the same principle as for finding a single row. Returned will be a ",(0,s.jsx)(n.code,{children:"List"})," of ",(0,s.jsx)(n.code,{children:"TableRow"}),"s."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var companies = await Company.find(\n tCompany,\n where: (t) => t.id < 100,\n limit: 50,\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"updating-a-row",children:"Updating a row"}),"\n",(0,s.jsxs)(n.p,{children:["To update a row, use the ",(0,s.jsx)(n.code,{children:"update"})," method. The object that you update must have its ",(0,s.jsx)(n.code,{children:"id"})," set to a non ",(0,s.jsx)(n.code,{children:"null"})," value."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await session.db.findById(tCompany, companyId) as Company?;\nmyCompany.name = 'New name';\nawait session.db.update(myCompany);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"deleting-rows",children:"Deleting rows"}),"\n",(0,s.jsxs)(n.p,{children:["Deleting a single row works similarly to the ",(0,s.jsx)(n.code,{children:"update"})," method, but you can also delete rows using the where parameter."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// Delete a single row\nawait Company.deleteRow(session, myCompany);\n\n// Delete all rows where the company name ends with 'Ltd'\nawait Company.delete(\n where: (t) => t.name.like('%Ltd'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"creating-expressions",children:"Creating expressions"}),"\n",(0,s.jsxs)(n.p,{children:["To find or delete specific rows, most often, expressions are needed. Serverpod makes it easy to build expressions that are statically type-checked. Columns are referenced using the global table descriptor objects. The table descriptors, ",(0,s.jsx)(n.code,{children:"t"})," are passed to the expression builder function. The ",(0,s.jsx)(n.code,{children:">"}),", ",(0,s.jsx)(n.code,{children:">="}),", ",(0,s.jsx)(n.code,{children:"<"}),", ",(0,s.jsx)(n.code,{children:"<="}),", ",(0,s.jsx)(n.code,{children:"&"}),", and ",(0,s.jsx)(n.code,{children:"|"})," operators are overridden to make it easier to work with column values. When using the operators, it's a good practice to place them within a set of parentheses as the precedence rules are not always what would be expected. These are some examples of expressions."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// The name column of the Company table equals 'My company')\nt.name.equals('My company')\n\n// Companies founded at or after 2020\nt.foundedDate >= DateTime.utc(2020)\n\n// Companies with number of employees between 10 and 100\n(t.numEmployees > 10) & (t.numEmployees <= 100)\n\n// Companies that has the founded date set\nt.foundedDate.notEquals(null)\n"})}),"\n",(0,s.jsx)(n.h3,{id:"transactions",children:"Transactions"}),"\n",(0,s.jsx)(n.p,{children:"Docs coming."}),"\n",(0,s.jsx)(n.h3,{id:"executing-raw-queries",children:"Executing raw queries"}),"\n",(0,s.jsxs)(n.p,{children:["Sometimes more advanced tasks need to be performed on the database. For those occasions, it's possible to run raw SQL queries on the database. Use the ",(0,s.jsx)(n.code,{children:"query"})," method. A ",(0,s.jsx)(n.code,{children:"List>"})," will be returned with rows and columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var result = await session.db.query('SELECT * FROM mytable WHERE ...');\n"})})]})}function h(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},11151:(e,n,a)=>{a.d(n,{Z:()=>d,a:()=>o});var s=a(67294);const i={},t=s.createContext(i);function o(e){const n=s.useContext(t);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/511f9951.bae60e3b.js b/docs/assets/js/511f9951.bae60e3b.js new file mode 100644 index 000000000..3e6a20db3 --- /dev/null +++ b/docs/assets/js/511f9951.bae60e3b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkserverpod_docs=self.webpackChunkserverpod_docs||[]).push([[399],{2726:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>i,metadata:()=>r,toc:()=>l});var s=a(85893),t=a(11151);const i={},o="Database communication",r={id:"concepts/database-communication",title:"Database communication",description:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files.",source:"@site/versioned_docs/version-0.9.21/04-concepts/03-database-communication.md",sourceDirName:"04-concepts",slug:"/concepts/database-communication",permalink:"/0.9.21/concepts/database-communication",draft:!1,unlisted:!1,editUrl:"https://github.com/serverpod/serverpod_docs/tree/main/versioned_docs/version-0.9.21/04-concepts/03-database-communication.md",tags:[],version:"0.9.21",sidebarPosition:3,frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Serialization",permalink:"/0.9.21/concepts/serialization"},next:{title:"Caching",permalink:"/0.9.21/concepts/caching"}},d={},l=[{value:"Database mappings",id:"database-mappings",level:2},{value:"Field scopes",id:"field-scopes",level:3},{value:"Database indexes",id:"database-indexes",level:3},{value:"Parent/child relationships",id:"parentchild-relationships",level:3},{value:"Storing objects or references",id:"storing-objects-or-references",level:3},{value:"Making queries",id:"making-queries",level:2},{value:"Inserting a table row",id:"inserting-a-table-row",level:3},{value:"Finding a single row",id:"finding-a-single-row",level:3},{value:"Finding multiple rows",id:"finding-multiple-rows",level:3},{value:"Updating a row",id:"updating-a-row",level:3},{value:"Deleting rows",id:"deleting-rows",level:3},{value:"Creating expressions",id:"creating-expressions",level:3},{value:"Joining tables and nesting objects",id:"joining-tables-and-nesting-objects",level:3},{value:"Transactions",id:"transactions",level:3},{value:"Executing raw queries",id:"executing-raw-queries",level:3}];function c(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,t.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"database-communication",children:"Database communication"}),"\n",(0,s.jsx)(n.p,{children:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files."}),"\n",(0,s.jsx)(n.h2,{id:"database-mappings",children:"Database mappings"}),"\n",(0,s.jsxs)(n.p,{children:["It's possible to map serializable classes straight to tables in your database. To do this, add the ",(0,s.jsx)(n.code,{children:"table"})," key to your yaml file:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n"})}),"\n",(0,s.jsxs)(n.p,{children:["When running ",(0,s.jsx)(n.code,{children:"serverpod generate"}),", the database schema will be saved in the ",(0,s.jsx)(n.code,{children:"generated/tables.pgsql"})," file. You can use this to create the corresponding database tables."]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["When you add a ",(0,s.jsx)(n.code,{children:"table"})," to a serializable class, Serverpod will automatically add an ",(0,s.jsx)(n.code,{children:"id"})," field of type ",(0,s.jsx)(n.code,{children:"int?"})," to the class. You should not define this field yourself. The ",(0,s.jsx)(n.code,{children:"id"})," is set when you insert or select a row from the database. The ",(0,s.jsx)(n.code,{children:"id"})," field allows you to do updates and reference the rows from other objects and tables."]})}),"\n",(0,s.jsx)(n.h3,{id:"field-scopes",children:"Field scopes"}),"\n",(0,s.jsxs)(n.p,{children:["In some cases, you want to save a field to the database, but it should never be sent to the server. You can exclude it from the protocol by adding the ",(0,s.jsx)(n.code,{children:"database"})," scope to the type."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: UserData\nfields:\n name: String\n password: String?, database\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Likewise, if you only want a field to be accessible in the protocol but not stored in the server, you can add the ",(0,s.jsx)(n.code,{children:"api"})," flag. By default, a field is accessible to both the API and the database."]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["If you use the ",(0,s.jsx)(n.code,{children:"database"})," or ",(0,s.jsx)(n.code,{children:"api"})," options the field must be nullable."]})}),"\n",(0,s.jsx)(n.h3,{id:"database-indexes",children:"Database indexes"}),"\n",(0,s.jsx)(n.p,{children:"For performance reasons, you may want to add indexes to your database tables. You add these in the yaml-files defining the serializable objects."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n employees: List?, api\nindexes:\n company_name_idx:\n fields: name\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"fields"})," key holds a comma-separated list of column names. In addition, it's possible to add a type key (default is ",(0,s.jsx)(n.code,{children:"btree"}),"), and a ",(0,s.jsx)(n.code,{children:"unique"})," key (default is ",(0,s.jsx)(n.code,{children:"false"}),")."]}),"\n",(0,s.jsx)(n.h3,{id:"parentchild-relationships",children:"Parent/child relationships"}),"\n",(0,s.jsx)(n.p,{children:"With a field's parent property, you can define a relationship with a table's parent table. This relationship ensures that the parent id is always valid and that if you delete the referenced parent, the referencing row will automatically be deleted."}),"\n",(0,s.jsxs)(n.p,{children:["The employee's ",(0,s.jsx)(n.code,{children:"parent"})," is set to the ",(0,s.jsx)(n.code,{children:"company"})," table in the example below. If you remove the company, all employees of the company will automatically be removed. When you insert the employee into the database, you must specify a valid ",(0,s.jsx)(n.code,{children:"companyId"})," that corresponds to the id field in the ",(0,s.jsx)(n.code,{children:"company"})," table."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Employee\ntable: employee\nfields:\n companyId: int, parent=company\n name: String\n birthday: DateTime\n"})}),"\n",(0,s.jsx)(n.h3,{id:"storing-objects-or-references",children:"Storing objects or references"}),"\n",(0,s.jsxs)(n.p,{children:["If you reference another serializable object in your yaml file, it will be stored as a JSON entry in the database. This creates a copy of that object. In many cases, this is not desirable. Instead, you may want to reference that object by an id from another table. See the section on ",(0,s.jsx)(n.a,{href:"#joining-tables-and-nesting-objects",children:"joining tables and nesting objects"})," below for more information."]}),"\n",(0,s.jsx)(n.p,{children:"In the example below, a list of employees is stored as a JSON structure for each company in the database. A better solution would be to create a database row for each employee and reference the company. However, there are cases where it is convenient to store whole JSON structures in each row."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n employees: List # Stored as JSON structure\n"})}),"\n",(0,s.jsx)(n.h2,{id:"making-queries",children:"Making queries"}),"\n",(0,s.jsxs)(n.p,{children:["For the communication to work, you need to have generated serializable classes with the ",(0,s.jsx)(n.code,{children:"table"})," key set, and the corresponding table must have been created in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"inserting-a-table-row",children:"Inserting a table row"}),"\n",(0,s.jsxs)(n.p,{children:["Insert a new row in the database by calling the insert method of the ",(0,s.jsx)(n.code,{children:"db"})," field in your ",(0,s.jsx)(n.code,{children:"Session"})," object."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myRow = Company(name: 'Serverpod corp.', employees: []);\nawait Company.insert(session, myRow);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["After the object has been inserted, it's ",(0,s.jsx)(n.code,{children:"id"})," field is set from its row in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"finding-a-single-row",children:"Finding a single row"}),"\n",(0,s.jsxs)(n.p,{children:["You can find a single row, either by its ",(0,s.jsx)(n.code,{children:"id"})," or using an expression. You need to pass a reference to the a session in the call. Tables are accessible through generated serializable classes."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findById(session, companyId);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If no matching row is found, ",(0,s.jsx)(n.code,{children:"null"})," is returned. You can also search for rows using expressions with the ",(0,s.jsx)(n.code,{children:"where"})," parameter. The ",(0,s.jsx)(n.code,{children:"where"})," parameter is a typed expression builder. The builder's parameter, ",(0,s.jsx)(n.code,{children:"t"}),", contains a description of the table which gives access to the table's columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findSingleRow(\n session,\n where: (t) => t.name.equals('My Company'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"finding-multiple-rows",children:"Finding multiple rows"}),"\n",(0,s.jsxs)(n.p,{children:["To find multiple rows, use the same principle as for finding a single row. Returned will be a ",(0,s.jsx)(n.code,{children:"List"})," of ",(0,s.jsx)(n.code,{children:"TableRow"}),"s."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var companies = await Company.find(\n tCompany,\n where: (t) => t.id < 100,\n limit: 50,\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"updating-a-row",children:"Updating a row"}),"\n",(0,s.jsxs)(n.p,{children:["To update a row, use the ",(0,s.jsx)(n.code,{children:"update"})," method. The object that you update must have its ",(0,s.jsx)(n.code,{children:"id"})," set to a non-",(0,s.jsx)(n.code,{children:"null"})," value."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await session.db.findById(tCompany, companyId) as Company?;\nmyCompany.name = 'New name';\nawait session.db.update(myCompany);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"deleting-rows",children:"Deleting rows"}),"\n",(0,s.jsxs)(n.p,{children:["Deleting a single row works similarly to the ",(0,s.jsx)(n.code,{children:"update"})," method, but you can also delete rows using the where parameter."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// Delete a single row\nawait Company.deleteRow(session, myCompany);\n\n// Delete all rows where the company name ends with 'Ltd'\nawait Company.delete(\n where: (t) => t.name.like('%Ltd'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"creating-expressions",children:"Creating expressions"}),"\n",(0,s.jsxs)(n.p,{children:["To find or delete specific rows, most often, expressions are needed. Serverpod makes it easy to build expressions that are statically type-checked. Columns are referenced using the global table descriptor objects. The table descriptors, ",(0,s.jsx)(n.code,{children:"t"})," are passed to the expression builder function. The ",(0,s.jsx)(n.code,{children:">"}),", ",(0,s.jsx)(n.code,{children:">="}),", ",(0,s.jsx)(n.code,{children:"<"}),", ",(0,s.jsx)(n.code,{children:"<="}),", ",(0,s.jsx)(n.code,{children:"&"}),", and ",(0,s.jsx)(n.code,{children:"|"})," operators are overridden to make it easier to work with column values. When using the operators, it's a good practice to place them within a set of parentheses as the precedence rules are not always what would be expected. These are some examples of expressions."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// The name column of the Company table equals 'My company')\nt.name.equals('My company')\n\n// Companies founded at or after 2020\nt.foundedDate >= DateTime.utc(2020)\n\n// Companies with number of employees between 10 and 100\n(t.numEmployees > 10) & (t.numEmployees <= 100)\n\n// Companies that has the founded date set\nt.foundedDate.notEquals(null)\n"})}),"\n",(0,s.jsx)(n.h3,{id:"joining-tables-and-nesting-objects",children:"Joining tables and nesting objects"}),"\n",(0,s.jsx)(n.p,{children:"Serverpod does not yet support joins automatically. However, you can easily create nested objects by performing two or more queries."}),"\n",(0,s.jsxs)(n.p,{children:["For instance, if you have a ",(0,s.jsx)(n.code,{children:"Company"})," object with a list of ",(0,s.jsx)(n.code,{children:"Employee"})," it can be declared like this:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"# company.yaml\nclass: Company\ntable: company\nfields:\n name: String\n employees: List?, api\n\n# employee.yaml\nclass: Employee\ntable: employee\nfields:\n companyId: int\n name: String\n birthday: DateTime\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This prevents the list of ",(0,s.jsx)(n.code,{children:"Employee"})," to be automatically fetched or stored in the database. After you fetch a ",(0,s.jsx)(n.code,{children:"Company"})," object from the database, format it by fetching the list of ",(0,s.jsx)(n.code,{children:"Employees"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var company = await Company.findById(session, id);\n\nvar employees = await Employee.find(\n session,\n where: (t) => t.companyId.equals(company.id),\n);\n\ncompany.employees = employees;\n"})}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsx)(n.p,{children:"Future versions of Serverpod will add support for automatic joins and database views."})}),"\n",(0,s.jsx)(n.h3,{id:"transactions",children:"Transactions"}),"\n",(0,s.jsx)(n.p,{children:"The essential point of a database transaction is that it bundles multiple steps into a single, all-or-nothing operation. The intermediate states between the steps are not visible to other concurrent transactions, and if some failure occurs that prevents the transaction from completing, then none of the steps affect the database at all."}),"\n",(0,s.jsxs)(n.p,{children:["Serverpod handles database transactions through the ",(0,s.jsx)(n.code,{children:"session.db.transaction"})," method. The transaction takes a method that performs any database queries or other operations and optionally returns a value."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var result = await session.db.transaction((transaction) async {\n // Do some database queries here.\n\n // Optionally return a value.\n return true;\n});\n"})}),"\n",(0,s.jsx)(n.h3,{id:"executing-raw-queries",children:"Executing raw queries"}),"\n",(0,s.jsxs)(n.p,{children:["Sometimes more advanced tasks need to be performed on the database. For those occasions, it's possible to run raw SQL queries on the database. Use the ",(0,s.jsx)(n.code,{children:"query"})," method. A ",(0,s.jsx)(n.code,{children:"List>"})," will be returned with rows and columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var result = await session.db.query('SELECT * FROM mytable WHERE ...');\n"})})]})}function h(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},11151:(e,n,a)=>{a.d(n,{Z:()=>r,a:()=>o});var s=a(67294);const t={},i=s.createContext(t);function o(e){const n=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),s.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/638e38ae.b24dcfbe.js b/docs/assets/js/638e38ae.b24dcfbe.js new file mode 100644 index 000000000..85f0f3782 --- /dev/null +++ b/docs/assets/js/638e38ae.b24dcfbe.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkserverpod_docs=self.webpackChunkserverpod_docs||[]).push([[7673],{74352:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>i,metadata:()=>r,toc:()=>l});var s=a(85893),t=a(11151);const i={},o="Database communication",r={id:"concepts/database-communication",title:"Database communication",description:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files.",source:"@site/versioned_docs/version-1.1.1/05-concepts/05-database-communication.md",sourceDirName:"05-concepts",slug:"/concepts/database-communication",permalink:"/1.1.1/concepts/database-communication",draft:!1,unlisted:!1,editUrl:"https://github.com/serverpod/serverpod_docs/tree/main/versioned_docs/version-1.1.1/05-concepts/05-database-communication.md",tags:[],version:"1.1.1",sidebarPosition:5,frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Error handling and exceptions",permalink:"/1.1.1/concepts/exceptions"},next:{title:"Caching",permalink:"/1.1.1/concepts/caching"}},d={},l=[{value:"Database mappings",id:"database-mappings",level:2},{value:"Field scopes",id:"field-scopes",level:3},{value:"Database indexes",id:"database-indexes",level:3},{value:"Parent/child relationships",id:"parentchild-relationships",level:3},{value:"Storing objects or references",id:"storing-objects-or-references",level:3},{value:"Making queries",id:"making-queries",level:2},{value:"Inserting a table row",id:"inserting-a-table-row",level:3},{value:"Finding a single row",id:"finding-a-single-row",level:3},{value:"Finding multiple rows",id:"finding-multiple-rows",level:3},{value:"Updating a row",id:"updating-a-row",level:3},{value:"Deleting rows",id:"deleting-rows",level:3},{value:"Creating expressions",id:"creating-expressions",level:3},{value:"Ordering rows",id:"ordering-rows",level:3},{value:"Joining tables and nesting objects",id:"joining-tables-and-nesting-objects",level:3},{value:"Transactions",id:"transactions",level:3},{value:"Executing raw queries",id:"executing-raw-queries",level:3}];function c(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,t.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"database-communication",children:"Database communication"}),"\n",(0,s.jsx)(n.p,{children:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files."}),"\n",(0,s.jsx)(n.h2,{id:"database-mappings",children:"Database mappings"}),"\n",(0,s.jsxs)(n.p,{children:["It's possible to map serializable classes straight to tables in your database. To do this, add the ",(0,s.jsx)(n.code,{children:"table"})," key to your yaml file:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n"})}),"\n",(0,s.jsxs)(n.p,{children:["When running ",(0,s.jsx)(n.code,{children:"serverpod generate"}),", the database schema will be saved in the ",(0,s.jsx)(n.code,{children:"generated/tables.pgsql"})," file. You can use this to create the corresponding database tables."]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["When you add a ",(0,s.jsx)(n.code,{children:"table"})," to a serializable class, Serverpod will automatically add an ",(0,s.jsx)(n.code,{children:"id"})," field of type ",(0,s.jsx)(n.code,{children:"int?"})," to the class. You should not define this field yourself. The ",(0,s.jsx)(n.code,{children:"id"})," is set when you insert or select a row from the database. The ",(0,s.jsx)(n.code,{children:"id"})," field allows you to do updates and reference the rows from other objects and tables."]})}),"\n",(0,s.jsx)(n.h3,{id:"field-scopes",children:"Field scopes"}),"\n",(0,s.jsxs)(n.p,{children:["In some cases, you want to save a field to the database, but it should never be sent to the server. You can exclude it from the protocol by adding the ",(0,s.jsx)(n.code,{children:"database"})," scope to the type."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: UserData\nfields:\n name: String\n password: String?, database\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Likewise, if you only want a field to be accessible in the protocol but not stored in the server, you can add the ",(0,s.jsx)(n.code,{children:"api"})," flag. By default, a field is accessible to both the API and the database."]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["If you use the ",(0,s.jsx)(n.code,{children:"database"})," or ",(0,s.jsx)(n.code,{children:"api"})," options the field must be nullable."]})}),"\n",(0,s.jsx)(n.h3,{id:"database-indexes",children:"Database indexes"}),"\n",(0,s.jsx)(n.p,{children:"For performance reasons, you may want to add indexes to your database tables. You add these in the yaml-files defining the serializable objects."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n employees: List?, api\nindexes:\n company_name_idx:\n fields: name\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"fields"})," key holds a comma-separated list of column names. In addition, it's possible to add a type key (default is ",(0,s.jsx)(n.code,{children:"btree"}),"), and a ",(0,s.jsx)(n.code,{children:"unique"})," key (default is ",(0,s.jsx)(n.code,{children:"false"}),")."]}),"\n",(0,s.jsx)(n.h3,{id:"parentchild-relationships",children:"Parent/child relationships"}),"\n",(0,s.jsx)(n.p,{children:"With a field's parent property, you can define a relationship with a table's parent table. This relationship ensures that the parent id is always valid and that if you delete the referenced parent, the referencing row will automatically be deleted."}),"\n",(0,s.jsxs)(n.p,{children:["The employee's ",(0,s.jsx)(n.code,{children:"parent"})," is set to the ",(0,s.jsx)(n.code,{children:"company"})," table in the example below. If you remove the company, all employees of the company will automatically be removed. When you insert the employee into the database, you must specify a valid ",(0,s.jsx)(n.code,{children:"companyId"})," that corresponds to the id field in the ",(0,s.jsx)(n.code,{children:"company"})," table."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Employee\ntable: employee\nfields:\n companyId: int, parent=company\n name: String\n birthday: DateTime\n"})}),"\n",(0,s.jsx)(n.h3,{id:"storing-objects-or-references",children:"Storing objects or references"}),"\n",(0,s.jsxs)(n.p,{children:["If you reference another serializable object in your yaml file, it will be stored as a JSON entry in the database. This creates a copy of that object. In many cases, this is not desirable. Instead, you may want to reference that object by an id from another table. See the section on ",(0,s.jsx)(n.a,{href:"#joining-tables-and-nesting-objects",children:"joining tables and nesting objects"})," below for more information."]}),"\n",(0,s.jsx)(n.p,{children:"In the example below, a list of employees is stored as a JSON structure for each company in the database. A better solution would be to create a database row for each employee and reference the company. However, there are cases where it is convenient to store whole JSON structures in each row."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n employees: List # Stored as JSON structure\n"})}),"\n",(0,s.jsx)(n.h2,{id:"making-queries",children:"Making queries"}),"\n",(0,s.jsxs)(n.p,{children:["For the communication to work, you need to have generated serializable classes with the ",(0,s.jsx)(n.code,{children:"table"})," key set, and the corresponding table must have been created in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"inserting-a-table-row",children:"Inserting a table row"}),"\n",(0,s.jsxs)(n.p,{children:["Insert a new row in the database by calling the insert method of the ",(0,s.jsx)(n.code,{children:"db"})," field in your ",(0,s.jsx)(n.code,{children:"Session"})," object."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myRow = Company(name: 'Serverpod corp.', employees: []);\nawait Company.insert(session, myRow);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["After the object has been inserted, its ",(0,s.jsx)(n.code,{children:"id"})," field is set from its row in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"finding-a-single-row",children:"Finding a single row"}),"\n",(0,s.jsxs)(n.p,{children:["You can find a single row, either by its ",(0,s.jsx)(n.code,{children:"id"})," or using an expression. You need to pass a reference to the session in the call. Tables are accessible through generated serializable classes."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findById(session, companyId);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If no matching row is found, ",(0,s.jsx)(n.code,{children:"null"})," is returned. You can also search for rows using expressions with the ",(0,s.jsx)(n.code,{children:"where"})," parameter. The ",(0,s.jsx)(n.code,{children:"where"})," parameter is a typed expression builder. The builder's parameter, ",(0,s.jsx)(n.code,{children:"t"}),", contains a description of the table which gives access to the table's columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findSingleRow(\n session,\n where: (t) => t.name.equals('My Company'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"finding-multiple-rows",children:"Finding multiple rows"}),"\n",(0,s.jsxs)(n.p,{children:["To find multiple rows, use the same principle as for finding a single row. Returned will be a ",(0,s.jsx)(n.code,{children:"List"})," of ",(0,s.jsx)(n.code,{children:"TableRow"}),"s."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var companies = await Company.find(\n session,\n where: (t) => t.id < 100,\n limit: 50,\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"updating-a-row",children:"Updating a row"}),"\n",(0,s.jsxs)(n.p,{children:["To update a row, use the ",(0,s.jsx)(n.code,{children:"update"})," method. The object that you update must have its ",(0,s.jsx)(n.code,{children:"id"})," set to a non-",(0,s.jsx)(n.code,{children:"null"})," value."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findById(session, companyId);\nmyCompany.name = 'New name';\nawait session.db.update(myCompany);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"deleting-rows",children:"Deleting rows"}),"\n",(0,s.jsxs)(n.p,{children:["Deleting a single row works similarly to the ",(0,s.jsx)(n.code,{children:"update"})," method, but you can also delete rows using the where parameter."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// Delete a single row\nawait Company.deleteRow(session, myCompany);\n\n// Delete all rows where the company name ends with 'Ltd'\nawait Company.delete(\n where: (t) => t.name.like('%Ltd'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"creating-expressions",children:"Creating expressions"}),"\n",(0,s.jsxs)(n.p,{children:["To find or delete specific rows, most often, expressions are needed. Serverpod makes it easy to build expressions that are statically type-checked. Columns are referenced using the global table descriptor objects. The table descriptors, ",(0,s.jsx)(n.code,{children:"t"})," are passed to the expression builder function. The ",(0,s.jsx)(n.code,{children:">"}),", ",(0,s.jsx)(n.code,{children:">="}),", ",(0,s.jsx)(n.code,{children:"<"}),", ",(0,s.jsx)(n.code,{children:"<="}),", ",(0,s.jsx)(n.code,{children:"&"}),", and ",(0,s.jsx)(n.code,{children:"|"})," operators are overridden to make it easier to work with column values. When using the operators, it's a good practice to place them within a set of parentheses as the precedence rules are not always what would be expected. These are some examples of expressions."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// The name column of the Company table equals 'My company')\nt.name.equals('My company')\n\n// Companies founded at or after 2020\nt.foundedDate >= DateTime.utc(2020)\n\n// Companies with number of employees between 10 and 100\n(t.numEmployees > 10) & (t.numEmployees <= 100)\n\n// Companies that has the founded date set\nt.foundedDate.notEquals(null)\n"})}),"\n",(0,s.jsx)(n.h3,{id:"ordering-rows",children:"Ordering rows"}),"\n",(0,s.jsxs)(n.p,{children:["It is often desirable to order the results of a database query. The ",(0,s.jsx)(n.code,{children:"find"})," method contains an ",(0,s.jsx)(n.code,{children:"orderBy"})," parameter, to which you can pass a column to order by. The static ",(0,s.jsx)(n.code,{children:"t"})," field on your serializable objects includes a reference to a representation of your table. It has a field for each column."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var companies = await Company.find(\n session,\n orderBy: Company.t.name,\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"joining-tables-and-nesting-objects",children:"Joining tables and nesting objects"}),"\n",(0,s.jsx)(n.p,{children:"Serverpod does not yet support joins automatically. However, you can easily create nested objects by performing two or more queries."}),"\n",(0,s.jsxs)(n.p,{children:["For instance, if you have a ",(0,s.jsx)(n.code,{children:"Company"})," object with a list of ",(0,s.jsx)(n.code,{children:"Employee"})," it can be declared like this:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"# company.yaml\nclass: Company\ntable: company\nfields:\n name: String\n employees: List?, api\n\n# employee.yaml\nclass: Employee\ntable: employee\nfields:\n companyId: int\n name: String\n birthday: DateTime\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This prevents the list of ",(0,s.jsx)(n.code,{children:"Employee"})," to be automatically fetched or stored in the database. After you fetch a ",(0,s.jsx)(n.code,{children:"Company"})," object from the database, format it by fetching the list of ",(0,s.jsx)(n.code,{children:"Employees"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var company = await Company.findById(session, id);\n\nvar employees = await Employee.find(\n session,\n where: (t) => t.companyId.equals(company.id),\n);\n\ncompany.employees = employees;\n"})}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsx)(n.p,{children:"Future versions of Serverpod will add support for automatic joins and database views."})}),"\n",(0,s.jsx)(n.h3,{id:"transactions",children:"Transactions"}),"\n",(0,s.jsx)(n.p,{children:"The essential point of a database transaction is that it bundles multiple steps into a single, all-or-nothing operation. The intermediate states between the steps are not visible to other concurrent transactions, and if some failure occurs that prevents the transaction from completing, then none of the steps affect the database at all."}),"\n",(0,s.jsxs)(n.p,{children:["Serverpod handles database transactions through the ",(0,s.jsx)(n.code,{children:"session.db.transaction"})," method. The transaction takes a method that performs any database queries or other operations and optionally returns a value."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var result = await session.db.transaction((transaction) async {\n // Do some database queries here.\n\n // Optionally return a value.\n return true;\n});\n"})}),"\n",(0,s.jsx)(n.h3,{id:"executing-raw-queries",children:"Executing raw queries"}),"\n",(0,s.jsxs)(n.p,{children:["Sometimes more advanced tasks need to be performed on the database. For those occasions, it's possible to run raw SQL queries on the database. Use the ",(0,s.jsx)(n.code,{children:"query"})," method. A ",(0,s.jsx)(n.code,{children:"List>"})," will be returned with rows and columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var result = await session.db.query('SELECT * FROM mytable WHERE ...');\n"})})]})}function h(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},11151:(e,n,a)=>{a.d(n,{Z:()=>r,a:()=>o});var s=a(67294);const t={},i=s.createContext(t);function o(e){const n=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),s.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/704545ab.c94cb47d.js b/docs/assets/js/704545ab.c94cb47d.js new file mode 100644 index 000000000..58f2e70dc --- /dev/null +++ b/docs/assets/js/704545ab.c94cb47d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkserverpod_docs=self.webpackChunkserverpod_docs||[]).push([[5724],{45828:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>i,metadata:()=>r,toc:()=>l});var s=a(85893),t=a(11151);const i={},o="Database communication",r={id:"concepts/database-communication",title:"Database communication",description:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files.",source:"@site/versioned_docs/version-0.9.20/04-concepts/03-database-communication.md",sourceDirName:"04-concepts",slug:"/concepts/database-communication",permalink:"/0.9.20/concepts/database-communication",draft:!1,unlisted:!1,editUrl:"https://github.com/serverpod/serverpod_docs/tree/main/versioned_docs/version-0.9.20/04-concepts/03-database-communication.md",tags:[],version:"0.9.20",sidebarPosition:3,frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Serialization",permalink:"/0.9.20/concepts/serialization"},next:{title:"Caching",permalink:"/0.9.20/concepts/caching"}},d={},l=[{value:"Database mappings",id:"database-mappings",level:2},{value:"Field scopes",id:"field-scopes",level:3},{value:"Database indexes",id:"database-indexes",level:3},{value:"Parent/child relationships",id:"parentchild-relationships",level:3},{value:"Storing objects or references",id:"storing-objects-or-references",level:3},{value:"Making queries",id:"making-queries",level:2},{value:"Inserting a table row",id:"inserting-a-table-row",level:3},{value:"Finding a single row",id:"finding-a-single-row",level:3},{value:"Finding multiple rows",id:"finding-multiple-rows",level:3},{value:"Updating a row",id:"updating-a-row",level:3},{value:"Deleting rows",id:"deleting-rows",level:3},{value:"Creating expressions",id:"creating-expressions",level:3},{value:"Joining tables and nesting objects",id:"joining-tables-and-nesting-objects",level:3},{value:"Transactions",id:"transactions",level:3},{value:"Executing raw queries",id:"executing-raw-queries",level:3}];function c(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,t.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"database-communication",children:"Database communication"}),"\n",(0,s.jsx)(n.p,{children:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files."}),"\n",(0,s.jsx)(n.h2,{id:"database-mappings",children:"Database mappings"}),"\n",(0,s.jsxs)(n.p,{children:["It's possible to map serializable classes straight to tables in your database. To do this, add the ",(0,s.jsx)(n.code,{children:"table"})," key to your yaml file:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n"})}),"\n",(0,s.jsxs)(n.p,{children:["When running ",(0,s.jsx)(n.code,{children:"serverpod generate"}),", the database schema will be saved in the ",(0,s.jsx)(n.code,{children:"generated/tables.pgsql"})," file. You can use this to create the corresponding database tables."]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["When you add a ",(0,s.jsx)(n.code,{children:"table"})," to a serializable class, Serverpod will automatically add an ",(0,s.jsx)(n.code,{children:"id"})," field of type ",(0,s.jsx)(n.code,{children:"int?"})," to the class. You should not define this field yourself. The ",(0,s.jsx)(n.code,{children:"id"})," is set when you insert or select a row from the database. The ",(0,s.jsx)(n.code,{children:"id"})," field allows you to do updates and reference the rows from other objects and tables."]})}),"\n",(0,s.jsx)(n.h3,{id:"field-scopes",children:"Field scopes"}),"\n",(0,s.jsxs)(n.p,{children:["In some cases, you want to save a field to the database, but it should never be sent to the server. You can exclude it from the protocol by adding the ",(0,s.jsx)(n.code,{children:"database"})," scope to the type."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: UserData\nfields:\n name: String\n password: String?, database\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Likewise, if you only want a field to be accessible in the protocol but not stored in the server, you can add the ",(0,s.jsx)(n.code,{children:"api"})," flag. By default, a field is accessible to both the API and the database."]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["If you use the ",(0,s.jsx)(n.code,{children:"database"})," or ",(0,s.jsx)(n.code,{children:"api"})," options the field must be nullable."]})}),"\n",(0,s.jsx)(n.h3,{id:"database-indexes",children:"Database indexes"}),"\n",(0,s.jsx)(n.p,{children:"For performance reasons, you may want to add indexes to your database tables. You add these in the yaml-files defining the serializable objects."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n employees: List?, api\nindexes:\n company_name_idx:\n fields: name\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"fields"})," key holds a comma-separated list of column names. In addition, it's possible to add a type key (default is ",(0,s.jsx)(n.code,{children:"btree"}),"), and a ",(0,s.jsx)(n.code,{children:"unique"})," key (default is ",(0,s.jsx)(n.code,{children:"false"}),")."]}),"\n",(0,s.jsx)(n.h3,{id:"parentchild-relationships",children:"Parent/child relationships"}),"\n",(0,s.jsx)(n.p,{children:"With a field's parent property, you can define a relationship with a table's parent table. This relationship ensures that the parent id is always valid and that if you delete the referenced parent, the referencing row will automatically be deleted."}),"\n",(0,s.jsxs)(n.p,{children:["The employee's ",(0,s.jsx)(n.code,{children:"parent"})," is set to the ",(0,s.jsx)(n.code,{children:"company"})," table in the example below. If you remove the company, all employees of the company will automatically be removed. When you insert the employee into the database, you must specify a valid ",(0,s.jsx)(n.code,{children:"companyId"})," that corresponds to the id field in the ",(0,s.jsx)(n.code,{children:"company"})," table."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Employee\ntable: employee\nfields:\n companyId: int, parent=company\n name: String\n birthday: DateTime\n"})}),"\n",(0,s.jsx)(n.h3,{id:"storing-objects-or-references",children:"Storing objects or references"}),"\n",(0,s.jsxs)(n.p,{children:["If you reference another serializable object in your yaml file, it will be stored as a JSON entry in the database. This creates a copy of that object. In many cases, this is not desirable. Instead, you may want to reference that object by an id from another table. See the section on ",(0,s.jsx)(n.a,{href:"#joining-tables-and-nesting-objects",children:"joining tables and nesting objects"})," below for more information."]}),"\n",(0,s.jsx)(n.p,{children:"In the example below, a list of employees is stored as a JSON structure for each company in the database. A better solution would be to create a database row for each employee and reference the company. However, there are cases where it is convenient to store whole JSON structures in each row."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n employees: List # Stored as JSON structure\n"})}),"\n",(0,s.jsx)(n.h2,{id:"making-queries",children:"Making queries"}),"\n",(0,s.jsxs)(n.p,{children:["For the communication to work, you need to have generated serializable classes with the ",(0,s.jsx)(n.code,{children:"table"})," key set, and the corresponding table must have been created in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"inserting-a-table-row",children:"Inserting a table row"}),"\n",(0,s.jsxs)(n.p,{children:["Insert a new row in the database by calling the insert method of the ",(0,s.jsx)(n.code,{children:"db"})," field in your ",(0,s.jsx)(n.code,{children:"Session"})," object."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myRow = Company(name: 'Serverpod corp.', employees: []);\nawait Company.insert(session, myRow);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["After the object has been inserted, it's ",(0,s.jsx)(n.code,{children:"id"})," field is set from its row in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"finding-a-single-row",children:"Finding a single row"}),"\n",(0,s.jsxs)(n.p,{children:["You can find a single row, either by its ",(0,s.jsx)(n.code,{children:"id"})," or using an expression. You need to pass a reference to the a session in the call. Tables are accessible through generated serializable classes."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findById(session, companyId);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If no matching row is found, ",(0,s.jsx)(n.code,{children:"null"})," is returned. You can also search for rows using expressions with the ",(0,s.jsx)(n.code,{children:"where"})," parameter. The ",(0,s.jsx)(n.code,{children:"where"})," parameter is a typed expression builder. The builder's parameter, ",(0,s.jsx)(n.code,{children:"t"}),", contains a description of the table which gives access to the table's columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findSingleRow(\n session,\n where: (t) => t.name.equals('My Company'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"finding-multiple-rows",children:"Finding multiple rows"}),"\n",(0,s.jsxs)(n.p,{children:["To find multiple rows, use the same principle as for finding a single row. Returned will be a ",(0,s.jsx)(n.code,{children:"List"})," of ",(0,s.jsx)(n.code,{children:"TableRow"}),"s."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var companies = await Company.find(\n tCompany,\n where: (t) => t.id < 100,\n limit: 50,\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"updating-a-row",children:"Updating a row"}),"\n",(0,s.jsxs)(n.p,{children:["To update a row, use the ",(0,s.jsx)(n.code,{children:"update"})," method. The object that you update must have its ",(0,s.jsx)(n.code,{children:"id"})," set to a non-",(0,s.jsx)(n.code,{children:"null"})," value."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await session.db.findById(tCompany, companyId) as Company?;\nmyCompany.name = 'New name';\nawait session.db.update(myCompany);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"deleting-rows",children:"Deleting rows"}),"\n",(0,s.jsxs)(n.p,{children:["Deleting a single row works similarly to the ",(0,s.jsx)(n.code,{children:"update"})," method, but you can also delete rows using the where parameter."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// Delete a single row\nawait Company.deleteRow(session, myCompany);\n\n// Delete all rows where the company name ends with 'Ltd'\nawait Company.delete(\n where: (t) => t.name.like('%Ltd'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"creating-expressions",children:"Creating expressions"}),"\n",(0,s.jsxs)(n.p,{children:["To find or delete specific rows, most often, expressions are needed. Serverpod makes it easy to build expressions that are statically type-checked. Columns are referenced using the global table descriptor objects. The table descriptors, ",(0,s.jsx)(n.code,{children:"t"})," are passed to the expression builder function. The ",(0,s.jsx)(n.code,{children:">"}),", ",(0,s.jsx)(n.code,{children:">="}),", ",(0,s.jsx)(n.code,{children:"<"}),", ",(0,s.jsx)(n.code,{children:"<="}),", ",(0,s.jsx)(n.code,{children:"&"}),", and ",(0,s.jsx)(n.code,{children:"|"})," operators are overridden to make it easier to work with column values. When using the operators, it's a good practice to place them within a set of parentheses as the precedence rules are not always what would be expected. These are some examples of expressions."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// The name column of the Company table equals 'My company')\nt.name.equals('My company')\n\n// Companies founded at or after 2020\nt.foundedDate >= DateTime.utc(2020)\n\n// Companies with number of employees between 10 and 100\n(t.numEmployees > 10) & (t.numEmployees <= 100)\n\n// Companies that has the founded date set\nt.foundedDate.notEquals(null)\n"})}),"\n",(0,s.jsx)(n.h3,{id:"joining-tables-and-nesting-objects",children:"Joining tables and nesting objects"}),"\n",(0,s.jsx)(n.p,{children:"Serverpod does not yet support joins automatically. However, you can easily create nested objects by performing two or more queries."}),"\n",(0,s.jsxs)(n.p,{children:["For instance, if you have a ",(0,s.jsx)(n.code,{children:"Company"})," object with a list of ",(0,s.jsx)(n.code,{children:"Employee"})," it can be declared like this:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"# company.yaml\nclass: Company\ntable: company\nfields:\n name: String\n employees: List?, api\n\n# employee.yaml\nclass: Employee\ntable: employee\nfields:\n companyId: int\n name: String\n birthday: DateTime\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This prevents the list of ",(0,s.jsx)(n.code,{children:"Employee"})," to be automatically fetched or stored in the database. After you fetch a ",(0,s.jsx)(n.code,{children:"Company"})," object from the database, format it by fetching the list of ",(0,s.jsx)(n.code,{children:"Employees"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var company = await Company.findById(session, id);\n\nvar employees = await Employee.find(\n session,\n where: (t) => t.companyId.equals(company.id),\n);\n\ncompany.employees = employees;\n"})}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsx)(n.p,{children:"Future versions of Serverpod will add support for automatic joins and database views."})}),"\n",(0,s.jsx)(n.h3,{id:"transactions",children:"Transactions"}),"\n",(0,s.jsx)(n.p,{children:"The essential point of a database transaction is that it bundles multiple steps into a single, all-or-nothing operation. The intermediate states between the steps are not visible to other concurrent transactions, and if some failure occurs that prevents the transaction from completing, then none of the steps affect the database at all."}),"\n",(0,s.jsxs)(n.p,{children:["Serverpod handles database transactions through the ",(0,s.jsx)(n.code,{children:"session.db.transaction"})," method. The transaction takes a method that performs any database queries or other operations and optionally returns a value."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var result = await session.db.transaction((transaction) async {\n // Do some database queries here.\n\n // Optionally return a value.\n return true;\n});\n"})}),"\n",(0,s.jsx)(n.h3,{id:"executing-raw-queries",children:"Executing raw queries"}),"\n",(0,s.jsxs)(n.p,{children:["Sometimes more advanced tasks need to be performed on the database. For those occasions, it's possible to run raw SQL queries on the database. Use the ",(0,s.jsx)(n.code,{children:"query"})," method. A ",(0,s.jsx)(n.code,{children:"List>"})," will be returned with rows and columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var result = await session.db.query('SELECT * FROM mytable WHERE ...');\n"})})]})}function h(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},11151:(e,n,a)=>{a.d(n,{Z:()=>r,a:()=>o});var s=a(67294);const t={},i=s.createContext(t);function o(e){const n=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),s.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/8dfd8953.b1a2272b.js b/docs/assets/js/8dfd8953.b1a2272b.js new file mode 100644 index 000000000..a2d4f3d23 --- /dev/null +++ b/docs/assets/js/8dfd8953.b1a2272b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkserverpod_docs=self.webpackChunkserverpod_docs||[]).push([[7065],{77088:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>t,metadata:()=>r,toc:()=>l});var s=a(85893),i=a(11151);const t={},o="Database communication",r={id:"concepts/database-communication",title:"Database communication",description:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files.",source:"@site/versioned_docs/version-0.9.5/02-concepts/03-database-communication.md",sourceDirName:"02-concepts",slug:"/concepts/database-communication",permalink:"/0.9.5/concepts/database-communication",draft:!1,unlisted:!1,editUrl:"https://github.com/serverpod/serverpod_docs/tree/main/versioned_docs/version-0.9.5/02-concepts/03-database-communication.md",tags:[],version:"0.9.5",sidebarPosition:3,frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Serialization",permalink:"/0.9.5/concepts/serialization"},next:{title:"Caching",permalink:"/0.9.5/concepts/caching"}},d={},l=[{value:"Database mappings",id:"database-mappings",level:2},{value:"Database indexes",id:"database-indexes",level:3},{value:"Making queries",id:"making-queries",level:2},{value:"Inserting a table row",id:"inserting-a-table-row",level:3},{value:"Finding a single row",id:"finding-a-single-row",level:3},{value:"Finding multiple rows",id:"finding-multiple-rows",level:3},{value:"Updating a row",id:"updating-a-row",level:3},{value:"Deleting rows",id:"deleting-rows",level:3},{value:"Creating expressions",id:"creating-expressions",level:3},{value:"Transactions",id:"transactions",level:3},{value:"Executing raw queries",id:"executing-raw-queries",level:3}];function c(e){const n={code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,i.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"database-communication",children:"Database communication"}),"\n",(0,s.jsx)(n.p,{children:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files."}),"\n",(0,s.jsx)(n.h2,{id:"database-mappings",children:"Database mappings"}),"\n",(0,s.jsxs)(n.p,{children:["It's possible to map serializable classes straight to tables in your database. To do this, add the ",(0,s.jsx)(n.code,{children:"table"})," key to your yaml file:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n employees: List\n"})}),"\n",(0,s.jsxs)(n.p,{children:["When running ",(0,s.jsx)(n.code,{children:"serverpod generate"}),", the database schema will be saved in the ",(0,s.jsx)(n.code,{children:"generated/tables.pgsql"})," file. You can use this to create the corresponding database tables."]}),"\n",(0,s.jsxs)(n.p,{children:["In some cases, you want to save a field to the database, but it should never be sent to the server. You can exclude it from the protocol by adding the ",(0,s.jsx)(n.code,{children:"database"})," flag to the type."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: UserData\nfields:\n name: String\n password: String, database\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Likewise, if you only want a field to be accessible in the protocol but not stored in the server, you can add the ",(0,s.jsx)(n.code,{children:"api"})," flag. By default, a field is accessible to both the API and the database."]}),"\n",(0,s.jsx)(n.h3,{id:"database-indexes",children:"Database indexes"}),"\n",(0,s.jsx)(n.p,{children:"For performance reasons, you may want to add indexes to your database tables. You add these in the yaml-files defining the serializable objects."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n employees: List\nindexes:\n company_name_idx:\n fields: name\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"fields"})," key holds a comma-separated list of column names. In addition, it's possible to add a type key (default is ",(0,s.jsx)(n.code,{children:"btree"}),"), and a ",(0,s.jsx)(n.code,{children:"unique"})," key (default is ",(0,s.jsx)(n.code,{children:"false"}),")."]}),"\n",(0,s.jsx)(n.h2,{id:"making-queries",children:"Making queries"}),"\n",(0,s.jsxs)(n.p,{children:["For the communication to work, you need to have generated serializable classes with the ",(0,s.jsx)(n.code,{children:"table"})," key set, and the corresponding table must have been created in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"inserting-a-table-row",children:"Inserting a table row"}),"\n",(0,s.jsxs)(n.p,{children:["Insert a new row in the database by calling the insert method of the ",(0,s.jsx)(n.code,{children:"db"})," field in your ",(0,s.jsx)(n.code,{children:"Session"})," object."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myRow = Company(name: 'Serverpod corp.', employees: []);\nawait Company.insert(session, myRow);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["After the object has been inserted, it's ",(0,s.jsx)(n.code,{children:"id"})," field is set from its row in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"finding-a-single-row",children:"Finding a single row"}),"\n",(0,s.jsxs)(n.p,{children:["You can find a single row, either by its ",(0,s.jsx)(n.code,{children:"id"})," or using an expression. You need to pass a reference to the a session in the call. Tables are accessible through generated serializable classes."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findById(session, companyId);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If no matching row is found, ",(0,s.jsx)(n.code,{children:"null"})," is returned. You can also search for rows using expressions with the ",(0,s.jsx)(n.code,{children:"where"})," parameter. The ",(0,s.jsx)(n.code,{children:"where"})," parameter is a typed expression builder. The builder's parameter, ",(0,s.jsx)(n.code,{children:"t"}),", contains a description of the table which gives access to the table's columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findSingleRow(\n session,\n where: (t) => t.name.equals('My Company'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"finding-multiple-rows",children:"Finding multiple rows"}),"\n",(0,s.jsxs)(n.p,{children:["To find multiple rows, use the same principle as for finding a single row. Returned will be a ",(0,s.jsx)(n.code,{children:"List"})," of ",(0,s.jsx)(n.code,{children:"TableRow"}),"s."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var companies = await Company.find(\n tCompany,\n where: (t) => t.id < 100,\n limit: 50,\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"updating-a-row",children:"Updating a row"}),"\n",(0,s.jsxs)(n.p,{children:["To update a row, use the ",(0,s.jsx)(n.code,{children:"update"})," method. The object that you update must have its ",(0,s.jsx)(n.code,{children:"id"})," set to a non ",(0,s.jsx)(n.code,{children:"null"})," value."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await session.db.findById(tCompany, companyId) as Company?;\nmyCompany.name = 'New name';\nawait session.db.update(myCompany);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"deleting-rows",children:"Deleting rows"}),"\n",(0,s.jsxs)(n.p,{children:["Deleting a single row works similarly to the ",(0,s.jsx)(n.code,{children:"update"})," method, but you can also delete rows using the where parameter."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// Delete a single row\nawait Company.deleteRow(session, myCompany);\n\n// Delete all rows where the company name ends with 'Ltd'\nawait Company.delete(\n where: (t) => t.name.like('%Ltd'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"creating-expressions",children:"Creating expressions"}),"\n",(0,s.jsxs)(n.p,{children:["To find or delete specific rows, most often, expressions are needed. Serverpod makes it easy to build expressions that are statically type-checked. Columns are referenced using the global table descriptor objects. The table descriptors, ",(0,s.jsx)(n.code,{children:"t"})," are passed to the expression builder function. The ",(0,s.jsx)(n.code,{children:">"}),", ",(0,s.jsx)(n.code,{children:">="}),", ",(0,s.jsx)(n.code,{children:"<"}),", ",(0,s.jsx)(n.code,{children:"<="}),", ",(0,s.jsx)(n.code,{children:"&"}),", and ",(0,s.jsx)(n.code,{children:"|"})," operators are overridden to make it easier to work with column values. When using the operators, it's a good practice to place them within a set of parentheses as the precedence rules are not always what would be expected. These are some examples of expressions."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// The name column of the Company table equals 'My company')\nt.name.equals('My company')\n\n// Companies founded at or after 2020\nt.foundedDate >= DateTime.utc(2020)\n\n// Companies with number of employees between 10 and 100\n(t.numEmployees > 10) & (t.numEmployees <= 100)\n\n// Companies that has the founded date set\nt.foundedDate.notEquals(null)\n"})}),"\n",(0,s.jsx)(n.h3,{id:"transactions",children:"Transactions"}),"\n",(0,s.jsx)(n.p,{children:"Docs coming."}),"\n",(0,s.jsx)(n.h3,{id:"executing-raw-queries",children:"Executing raw queries"}),"\n",(0,s.jsxs)(n.p,{children:["Sometimes more advanced tasks need to be performed on the database. For those occasions, it's possible to run raw SQL queries on the database. Use the ",(0,s.jsx)(n.code,{children:"query"})," method. A ",(0,s.jsx)(n.code,{children:"List>"})," will be returned with rows and columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var result = await session.db.query('SELECT * FROM mytable WHERE ...');\n"})})]})}function h(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},11151:(e,n,a)=>{a.d(n,{Z:()=>r,a:()=>o});var s=a(67294);const i={},t=s.createContext(i);function o(e){const n=s.useContext(t);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/98c94590.2a56ce4c.js b/docs/assets/js/98c94590.2a56ce4c.js new file mode 100644 index 000000000..f40b2bd4b --- /dev/null +++ b/docs/assets/js/98c94590.2a56ce4c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkserverpod_docs=self.webpackChunkserverpod_docs||[]).push([[8213],{45894:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>o,contentTitle:()=>d,default:()=>h,frontMatter:()=>a,metadata:()=>r,toc:()=>l});var s=i(85893),t=i(11151);const a={},d="CRUD",r={id:"concepts/database/crud",title:"CRUD",description:"To interact with the database you need a Session object as this object holds the connection to the database. All CRUD operations are accessible via the session object and the generated models. The methods can be found under the static db field in your generated models.",source:"@site/versioned_docs/version-1.2.0/05-concepts/06-database/05-crud.md",sourceDirName:"05-concepts/06-database",slug:"/concepts/database/crud",permalink:"/concepts/database/crud",draft:!1,unlisted:!1,editUrl:"https://github.com/serverpod/serverpod_docs/tree/main/versioned_docs/version-1.2.0/05-concepts/06-database/05-crud.md",tags:[],version:"1.2.0",sidebarPosition:5,frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Indexing",permalink:"/concepts/database/indexing"},next:{title:"Filter",permalink:"/concepts/database/filter"}},o={},l=[{value:"Create",id:"create",level:2},{value:"Inserting a single row",id:"inserting-a-single-row",level:3},{value:"Inserting several rows",id:"inserting-several-rows",level:3},{value:"Read",id:"read",level:2},{value:"Finding by id",id:"finding-by-id",level:3},{value:"Finding a single row",id:"finding-a-single-row",level:3},{value:"Finding multiple rows",id:"finding-multiple-rows",level:3},{value:"Update",id:"update",level:2},{value:"Update a single row",id:"update-a-single-row",level:3},{value:"Update several rows",id:"update-several-rows",level:3},{value:"Delete",id:"delete",level:2},{value:"Delete a single row",id:"delete-a-single-row",level:3},{value:"Delete several rows",id:"delete-several-rows",level:3},{value:"Delete by filter",id:"delete-by-filter",level:3},{value:"Count",id:"count",level:2}];function c(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,t.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"crud",children:"CRUD"}),"\n",(0,s.jsxs)(n.p,{children:["To interact with the database you need a ",(0,s.jsx)(n.a,{href:"../sessions",children:(0,s.jsx)(n.code,{children:"Session"})})," object as this object holds the connection to the database. All CRUD operations are accessible via the session object and the generated models. The methods can be found under the static ",(0,s.jsx)(n.code,{children:"db"})," field in your generated models."]}),"\n",(0,s.jsx)(n.p,{children:"For the following examples we will use this model:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n"})}),"\n",(0,s.jsx)(n.admonition,{type:"note",children:(0,s.jsxs)(n.p,{children:["You can also access the database methods through the session object under the field ",(0,s.jsx)(n.code,{children:"dbNext"}),". However, this is typically only recommended if you want to do custom queries where you explicitly type out your SQL queries. The ",(0,s.jsx)(n.code,{children:"db"})," field on ",(0,s.jsx)(n.code,{children:"Session"})," contains legacy methods that are included for compatibility. In version 2 of Serverpod, the old legacy methods will be removed and ",(0,s.jsx)(n.code,{children:"db"})," will be replaced by ",(0,s.jsx)(n.code,{children:"dbNext"}),"."]})}),"\n",(0,s.jsx)(n.h2,{id:"create",children:"Create"}),"\n",(0,s.jsx)(n.p,{children:"There are two ways to create a new row in the database."}),"\n",(0,s.jsx)(n.h3,{id:"inserting-a-single-row",children:"Inserting a single row"}),"\n",(0,s.jsxs)(n.p,{children:["Inserting a single row to the database is done by calling the ",(0,s.jsx)(n.code,{children:"insertRow"})," method on your generated model. The method will return the entire company object with the ",(0,s.jsx)(n.code,{children:"id"})," field set."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var row = Company(name: 'Serverpod');\nvar company = await Company.db.insertRow(session, row);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"inserting-several-rows",children:"Inserting several rows"}),"\n",(0,s.jsxs)(n.p,{children:["Inserting several rows in a batch operation is done by calling the ",(0,s.jsx)(n.code,{children:"insert"})," method. This is an atomic operation, meaning no entries will be created if any entry fails to be created."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var rows = [Company(name: 'Serverpod'), Company(name: 'Google')];\nvar companies = await Company.db.insert(session, rows);\n"})}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["In previous versions of Serverpod the ",(0,s.jsx)(n.code,{children:"insert"})," method mutated the input object by setting the ",(0,s.jsx)(n.code,{children:"id"})," field. In the example above the input variable remains unmodified after the ",(0,s.jsx)(n.code,{children:"insert"}),"/",(0,s.jsx)(n.code,{children:"insertRow"})," call."]})}),"\n",(0,s.jsx)(n.h2,{id:"read",children:"Read"}),"\n",(0,s.jsx)(n.p,{children:"There are three different read operations available."}),"\n",(0,s.jsx)(n.h3,{id:"finding-by-id",children:"Finding by id"}),"\n",(0,s.jsxs)(n.p,{children:["You can retrieve a single row by its ",(0,s.jsx)(n.code,{children:"id"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var company = await Company.db.findById(session, companyId);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This operation either returns the model or ",(0,s.jsx)(n.code,{children:"null"}),"."]}),"\n",(0,s.jsx)(n.h3,{id:"finding-a-single-row",children:"Finding a single row"}),"\n",(0,s.jsx)(n.p,{children:"You can find a single row using an expression."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var company = await Company.db.findRow(\n session,\n where: (t) => t.name.equals('Serverpod'),\n);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This operation returns the first model matching the filtering criteria or ",(0,s.jsx)(n.code,{children:"null"}),". See ",(0,s.jsx)(n.a,{href:"filter",children:"filter"})," and ",(0,s.jsx)(n.a,{href:"sort",children:"sort"})," for all filter operations."]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsx)(n.p,{children:"Note that ordering of the entries is important here as it will return the fist row returned by the database query."})}),"\n",(0,s.jsx)(n.h3,{id:"finding-multiple-rows",children:"Finding multiple rows"}),"\n",(0,s.jsx)(n.p,{children:"To find multiple rows, use the same principle as for finding a single row."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var companies = await Company.db.find(\n session,\n where: (t) => t.id < 100,\n limit: 50,\n);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This operation returns a ",(0,s.jsx)(n.code,{children:"List"})," of your models matching the filtering criteria."]}),"\n",(0,s.jsxs)(n.p,{children:["See ",(0,s.jsx)(n.a,{href:"filter",children:"filter"})," and ",(0,s.jsx)(n.a,{href:"sort",children:"sort"})," for all filter and sorting operations and ",(0,s.jsx)(n.a,{href:"pagination",children:"pagination"})," for how to paginate the result."]}),"\n",(0,s.jsx)(n.h2,{id:"update",children:"Update"}),"\n",(0,s.jsx)(n.p,{children:"There are two update operations available."}),"\n",(0,s.jsx)(n.h3,{id:"update-a-single-row",children:"Update a single row"}),"\n",(0,s.jsxs)(n.p,{children:["To update a single row, use the ",(0,s.jsx)(n.code,{children:"updateRow"})," method."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var company = await Company.db.findById(session, companyId); // Fetched company has its id set \ncompany.name = 'New name';\nvar updatedCompany = await Company.db.updateRow(session, company);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The object that you update must have its ",(0,s.jsx)(n.code,{children:"id"})," set to a non-",(0,s.jsx)(n.code,{children:"null"})," value and the id needs to exist on a row in the database. The ",(0,s.jsx)(n.code,{children:"updateRow"})," method returns the updated object."]}),"\n",(0,s.jsx)(n.h3,{id:"update-several-rows",children:"Update several rows"}),"\n",(0,s.jsxs)(n.p,{children:["To batch update several rows use the ",(0,s.jsx)(n.code,{children:"update"})," method."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var companies = await Company.db.find(session);\ncompanies = companies.map((c) => c.copyWith(name: 'New name')).toList();\nvar updatedCompanies = await Company.db.update(session, companies);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This is an atomic operation, meaning no entries will be updated if any entry fails to be updated. The ",(0,s.jsx)(n.code,{children:"update"})," method returns a ",(0,s.jsx)(n.code,{children:"List"})," of the updated objects."]}),"\n",(0,s.jsx)(n.h2,{id:"delete",children:"Delete"}),"\n",(0,s.jsx)(n.p,{children:"Deleting rows from the database is done in a similar way to updating rows. However, there are three delete operations available."}),"\n",(0,s.jsx)(n.h3,{id:"delete-a-single-row",children:"Delete a single row"}),"\n",(0,s.jsxs)(n.p,{children:["To delete a single row, use the ",(0,s.jsx)(n.code,{children:"deleteRow"})," method."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var company = await Company.db.findById(session, companyId); // Fetched company has its id set \nvar id = await Company.db.deleteRow(session, company);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The input object needs to have the ",(0,s.jsx)(n.code,{children:"id"})," field set. The ",(0,s.jsx)(n.code,{children:"deleteRow"})," method returns the ",(0,s.jsx)(n.code,{children:"id"})," of the deleted row."]}),"\n",(0,s.jsx)(n.h3,{id:"delete-several-rows",children:"Delete several rows"}),"\n",(0,s.jsxs)(n.p,{children:["To batch delete several rows, use the ",(0,s.jsx)(n.code,{children:"delete"})," method."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var ids = await Company.db.delete(session, companies);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This is an atomic operation, meaning no entries will be deleted if any entry fails to be deleted. The ",(0,s.jsx)(n.code,{children:"delete"})," method returns a ",(0,s.jsx)(n.code,{children:"List"})," of the ",(0,s.jsx)(n.code,{children:"id"}),"s of the deleted row(s)."]}),"\n",(0,s.jsx)(n.h3,{id:"delete-by-filter",children:"Delete by filter"}),"\n",(0,s.jsxs)(n.p,{children:["You can also do a ",(0,s.jsx)(n.a,{href:"filter",children:"filtered"})," delete and delete all entries matching a ",(0,s.jsx)(n.code,{children:"where"})," query, by using the ",(0,s.jsx)(n.code,{children:"deleteWhere"})," method."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var ids = await Company.db.deleteWhere(\n session,\n where: (t) => t.name.like('%Ltd'),\n);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The above example will delete any row that ends in ",(0,s.jsx)(n.em,{children:"Ltd"}),". The ",(0,s.jsx)(n.code,{children:"deleteWhere"})," method returns a ",(0,s.jsx)(n.code,{children:"List"})," of the ",(0,s.jsx)(n.code,{children:"id"}),"s of the deleted row(s)."]}),"\n",(0,s.jsx)(n.h2,{id:"count",children:"Count"}),"\n",(0,s.jsxs)(n.p,{children:["Count is a special type of query that helps counting the number of rows in the database that matches a specific ",(0,s.jsx)(n.a,{href:"filter",children:"filter"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var count = await Company.db.count(\n session, \n where: (t) => t.name.like('s%'),\n);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The return value is an ",(0,s.jsx)(n.code,{children:"int"})," for the number of rows matching the filter."]})]})}function h(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},11151:(e,n,i)=>{i.d(n,{Z:()=>r,a:()=>d});var s=i(67294);const t={},a=s.createContext(t);function d(e){const n=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:d(e.components),s.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/afde3230.988b02ff.js b/docs/assets/js/afde3230.988b02ff.js new file mode 100644 index 000000000..1754c8093 --- /dev/null +++ b/docs/assets/js/afde3230.988b02ff.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkserverpod_docs=self.webpackChunkserverpod_docs||[]).push([[8856],{3410:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>t,metadata:()=>r,toc:()=>l});var s=a(85893),i=a(11151);const t={},o="Database communication",r={id:"concepts/database-communication",title:"Database communication",description:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files.",source:"@site/versioned_docs/version-0.9.10/03-concepts/03-database-communication.md",sourceDirName:"03-concepts",slug:"/concepts/database-communication",permalink:"/0.9.10/concepts/database-communication",draft:!1,unlisted:!1,editUrl:"https://github.com/serverpod/serverpod_docs/tree/main/versioned_docs/version-0.9.10/03-concepts/03-database-communication.md",tags:[],version:"0.9.10",sidebarPosition:3,frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Serialization",permalink:"/0.9.10/concepts/serialization"},next:{title:"Caching",permalink:"/0.9.10/concepts/caching"}},d={},l=[{value:"Database mappings",id:"database-mappings",level:2},{value:"Database indexes",id:"database-indexes",level:3},{value:"Making queries",id:"making-queries",level:2},{value:"Inserting a table row",id:"inserting-a-table-row",level:3},{value:"Finding a single row",id:"finding-a-single-row",level:3},{value:"Finding multiple rows",id:"finding-multiple-rows",level:3},{value:"Updating a row",id:"updating-a-row",level:3},{value:"Deleting rows",id:"deleting-rows",level:3},{value:"Creating expressions",id:"creating-expressions",level:3},{value:"Transactions",id:"transactions",level:3},{value:"Executing raw queries",id:"executing-raw-queries",level:3}];function c(e){const n={code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,i.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"database-communication",children:"Database communication"}),"\n",(0,s.jsx)(n.p,{children:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files."}),"\n",(0,s.jsx)(n.h2,{id:"database-mappings",children:"Database mappings"}),"\n",(0,s.jsxs)(n.p,{children:["It's possible to map serializable classes straight to tables in your database. To do this, add the ",(0,s.jsx)(n.code,{children:"table"})," key to your yaml file:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n employees: List\n"})}),"\n",(0,s.jsxs)(n.p,{children:["When running ",(0,s.jsx)(n.code,{children:"serverpod generate"}),", the database schema will be saved in the ",(0,s.jsx)(n.code,{children:"generated/tables.pgsql"})," file. You can use this to create the corresponding database tables."]}),"\n",(0,s.jsxs)(n.p,{children:["In some cases, you want to save a field to the database, but it should never be sent to the server. You can exclude it from the protocol by adding the ",(0,s.jsx)(n.code,{children:"database"})," flag to the type."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: UserData\nfields:\n name: String\n password: String, database\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Likewise, if you only want a field to be accessible in the protocol but not stored in the server, you can add the ",(0,s.jsx)(n.code,{children:"api"})," flag. By default, a field is accessible to both the API and the database."]}),"\n",(0,s.jsx)(n.h3,{id:"database-indexes",children:"Database indexes"}),"\n",(0,s.jsx)(n.p,{children:"For performance reasons, you may want to add indexes to your database tables. You add these in the yaml-files defining the serializable objects."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n employees: List\nindexes:\n company_name_idx:\n fields: name\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"fields"})," key holds a comma-separated list of column names. In addition, it's possible to add a type key (default is ",(0,s.jsx)(n.code,{children:"btree"}),"), and a ",(0,s.jsx)(n.code,{children:"unique"})," key (default is ",(0,s.jsx)(n.code,{children:"false"}),")."]}),"\n",(0,s.jsx)(n.h2,{id:"making-queries",children:"Making queries"}),"\n",(0,s.jsxs)(n.p,{children:["For the communication to work, you need to have generated serializable classes with the ",(0,s.jsx)(n.code,{children:"table"})," key set, and the corresponding table must have been created in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"inserting-a-table-row",children:"Inserting a table row"}),"\n",(0,s.jsxs)(n.p,{children:["Insert a new row in the database by calling the insert method of the ",(0,s.jsx)(n.code,{children:"db"})," field in your ",(0,s.jsx)(n.code,{children:"Session"})," object."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myRow = Company(name: 'Serverpod corp.', employees: []);\nawait Company.insert(session, myRow);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["After the object has been inserted, it's ",(0,s.jsx)(n.code,{children:"id"})," field is set from its row in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"finding-a-single-row",children:"Finding a single row"}),"\n",(0,s.jsxs)(n.p,{children:["You can find a single row, either by its ",(0,s.jsx)(n.code,{children:"id"})," or using an expression. You need to pass a reference to the a session in the call. Tables are accessible through generated serializable classes."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findById(session, companyId);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If no matching row is found, ",(0,s.jsx)(n.code,{children:"null"})," is returned. You can also search for rows using expressions with the ",(0,s.jsx)(n.code,{children:"where"})," parameter. The ",(0,s.jsx)(n.code,{children:"where"})," parameter is a typed expression builder. The builder's parameter, ",(0,s.jsx)(n.code,{children:"t"}),", contains a description of the table which gives access to the table's columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findSingleRow(\n session,\n where: (t) => t.name.equals('My Company'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"finding-multiple-rows",children:"Finding multiple rows"}),"\n",(0,s.jsxs)(n.p,{children:["To find multiple rows, use the same principle as for finding a single row. Returned will be a ",(0,s.jsx)(n.code,{children:"List"})," of ",(0,s.jsx)(n.code,{children:"TableRow"}),"s."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var companies = await Company.find(\n tCompany,\n where: (t) => t.id < 100,\n limit: 50,\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"updating-a-row",children:"Updating a row"}),"\n",(0,s.jsxs)(n.p,{children:["To update a row, use the ",(0,s.jsx)(n.code,{children:"update"})," method. The object that you update must have its ",(0,s.jsx)(n.code,{children:"id"})," set to a non ",(0,s.jsx)(n.code,{children:"null"})," value."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await session.db.findById(tCompany, companyId) as Company?;\nmyCompany.name = 'New name';\nawait session.db.update(myCompany);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"deleting-rows",children:"Deleting rows"}),"\n",(0,s.jsxs)(n.p,{children:["Deleting a single row works similarly to the ",(0,s.jsx)(n.code,{children:"update"})," method, but you can also delete rows using the where parameter."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// Delete a single row\nawait Company.deleteRow(session, myCompany);\n\n// Delete all rows where the company name ends with 'Ltd'\nawait Company.delete(\n where: (t) => t.name.like('%Ltd'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"creating-expressions",children:"Creating expressions"}),"\n",(0,s.jsxs)(n.p,{children:["To find or delete specific rows, most often, expressions are needed. Serverpod makes it easy to build expressions that are statically type-checked. Columns are referenced using the global table descriptor objects. The table descriptors, ",(0,s.jsx)(n.code,{children:"t"})," are passed to the expression builder function. The ",(0,s.jsx)(n.code,{children:">"}),", ",(0,s.jsx)(n.code,{children:">="}),", ",(0,s.jsx)(n.code,{children:"<"}),", ",(0,s.jsx)(n.code,{children:"<="}),", ",(0,s.jsx)(n.code,{children:"&"}),", and ",(0,s.jsx)(n.code,{children:"|"})," operators are overridden to make it easier to work with column values. When using the operators, it's a good practice to place them within a set of parentheses as the precedence rules are not always what would be expected. These are some examples of expressions."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// The name column of the Company table equals 'My company')\nt.name.equals('My company')\n\n// Companies founded at or after 2020\nt.foundedDate >= DateTime.utc(2020)\n\n// Companies with number of employees between 10 and 100\n(t.numEmployees > 10) & (t.numEmployees <= 100)\n\n// Companies that has the founded date set\nt.foundedDate.notEquals(null)\n"})}),"\n",(0,s.jsx)(n.h3,{id:"transactions",children:"Transactions"}),"\n",(0,s.jsx)(n.p,{children:"Docs coming."}),"\n",(0,s.jsx)(n.h3,{id:"executing-raw-queries",children:"Executing raw queries"}),"\n",(0,s.jsxs)(n.p,{children:["Sometimes more advanced tasks need to be performed on the database. For those occasions, it's possible to run raw SQL queries on the database. Use the ",(0,s.jsx)(n.code,{children:"query"})," method. A ",(0,s.jsx)(n.code,{children:"List>"})," will be returned with rows and columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var result = await session.db.query('SELECT * FROM mytable WHERE ...');\n"})})]})}function h(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},11151:(e,n,a)=>{a.d(n,{Z:()=>r,a:()=>o});var s=a(67294);const i={},t=s.createContext(i);function o(e){const n=s.useContext(t);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/b79774cd.86948f6d.js b/docs/assets/js/b79774cd.86948f6d.js new file mode 100644 index 000000000..572e42bff --- /dev/null +++ b/docs/assets/js/b79774cd.86948f6d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkserverpod_docs=self.webpackChunkserverpod_docs||[]).push([[2284],{28250:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>o,contentTitle:()=>d,default:()=>h,frontMatter:()=>a,metadata:()=>r,toc:()=>l});var s=i(85893),t=i(11151);const a={},d="CRUD",r={id:"concepts/database/crud",title:"CRUD",description:"To interact with the database you need a Session object as this object holds the connection to the database. All CRUD operations are accessible via the session object and the generated models. The methods can be found under the static db field in your generated models.",source:"@site/docs/05-concepts/06-database/05-crud.md",sourceDirName:"05-concepts/06-database",slug:"/concepts/database/crud",permalink:"/next/concepts/database/crud",draft:!1,unlisted:!1,editUrl:"https://github.com/serverpod/serverpod_docs/tree/main/docs/05-concepts/06-database/05-crud.md",tags:[],version:"current",sidebarPosition:5,frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Indexing",permalink:"/next/concepts/database/indexing"},next:{title:"Filter",permalink:"/next/concepts/database/filter"}},o={},l=[{value:"Create",id:"create",level:2},{value:"Inserting a single row",id:"inserting-a-single-row",level:3},{value:"Inserting several rows",id:"inserting-several-rows",level:3},{value:"Read",id:"read",level:2},{value:"Finding by id",id:"finding-by-id",level:3},{value:"Finding a single row",id:"finding-a-single-row",level:3},{value:"Finding multiple rows",id:"finding-multiple-rows",level:3},{value:"Update",id:"update",level:2},{value:"Update a single row",id:"update-a-single-row",level:3},{value:"Update several rows",id:"update-several-rows",level:3},{value:"Delete",id:"delete",level:2},{value:"Delete a single row",id:"delete-a-single-row",level:3},{value:"Delete several rows",id:"delete-several-rows",level:3},{value:"Delete by filter",id:"delete-by-filter",level:3},{value:"Count",id:"count",level:2}];function c(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,t.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"crud",children:"CRUD"}),"\n",(0,s.jsxs)(n.p,{children:["To interact with the database you need a ",(0,s.jsx)(n.a,{href:"../sessions",children:(0,s.jsx)(n.code,{children:"Session"})})," object as this object holds the connection to the database. All CRUD operations are accessible via the session object and the generated models. The methods can be found under the static ",(0,s.jsx)(n.code,{children:"db"})," field in your generated models."]}),"\n",(0,s.jsx)(n.p,{children:"For the following examples we will use this model:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n"})}),"\n",(0,s.jsx)(n.admonition,{type:"note",children:(0,s.jsxs)(n.p,{children:["You can also access the database methods through the session object under the field ",(0,s.jsx)(n.code,{children:"db"}),". However, this is typically only recommended if you want to do custom queries where you explicitly type out your SQL queries."]})}),"\n",(0,s.jsx)(n.h2,{id:"create",children:"Create"}),"\n",(0,s.jsx)(n.p,{children:"There are two ways to create a new row in the database."}),"\n",(0,s.jsx)(n.h3,{id:"inserting-a-single-row",children:"Inserting a single row"}),"\n",(0,s.jsxs)(n.p,{children:["Inserting a single row to the database is done by calling the ",(0,s.jsx)(n.code,{children:"insertRow"})," method on your generated model. The method will return the entire company object with the ",(0,s.jsx)(n.code,{children:"id"})," field set."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var row = Company(name: 'Serverpod');\nvar company = await Company.db.insertRow(session, row);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"inserting-several-rows",children:"Inserting several rows"}),"\n",(0,s.jsxs)(n.p,{children:["Inserting several rows in a batch operation is done by calling the ",(0,s.jsx)(n.code,{children:"insert"})," method. This is an atomic operation, meaning no entries will be created if any entry fails to be created."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var rows = [Company(name: 'Serverpod'), Company(name: 'Google')];\nvar companies = await Company.db.insert(session, rows);\n"})}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["In previous versions of Serverpod the ",(0,s.jsx)(n.code,{children:"insert"})," method mutated the input object by setting the ",(0,s.jsx)(n.code,{children:"id"})," field. In the example above the input variable remains unmodified after the ",(0,s.jsx)(n.code,{children:"insert"}),"/",(0,s.jsx)(n.code,{children:"insertRow"})," call."]})}),"\n",(0,s.jsx)(n.h2,{id:"read",children:"Read"}),"\n",(0,s.jsx)(n.p,{children:"There are three different read operations available."}),"\n",(0,s.jsx)(n.h3,{id:"finding-by-id",children:"Finding by id"}),"\n",(0,s.jsxs)(n.p,{children:["You can retrieve a single row by its ",(0,s.jsx)(n.code,{children:"id"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var company = await Company.db.findById(session, companyId);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This operation either returns the model or ",(0,s.jsx)(n.code,{children:"null"}),"."]}),"\n",(0,s.jsx)(n.h3,{id:"finding-a-single-row",children:"Finding a single row"}),"\n",(0,s.jsx)(n.p,{children:"You can find a single row using an expression."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var company = await Company.db.findRow(\n session,\n where: (t) => t.name.equals('Serverpod'),\n);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This operation returns the first model matching the filtering criteria or ",(0,s.jsx)(n.code,{children:"null"}),". See ",(0,s.jsx)(n.a,{href:"filter",children:"filter"})," and ",(0,s.jsx)(n.a,{href:"sort",children:"sort"})," for all filter operations."]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsx)(n.p,{children:"Note that ordering of the entries is important here as it will return the fist row returned by the database query."})}),"\n",(0,s.jsx)(n.h3,{id:"finding-multiple-rows",children:"Finding multiple rows"}),"\n",(0,s.jsx)(n.p,{children:"To find multiple rows, use the same principle as for finding a single row."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var companies = await Company.db.find(\n session,\n where: (t) => t.id < 100,\n limit: 50,\n);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This operation returns a ",(0,s.jsx)(n.code,{children:"List"})," of your models matching the filtering criteria."]}),"\n",(0,s.jsxs)(n.p,{children:["See ",(0,s.jsx)(n.a,{href:"filter",children:"filter"})," and ",(0,s.jsx)(n.a,{href:"sort",children:"sort"})," for all filter and sorting operations and ",(0,s.jsx)(n.a,{href:"pagination",children:"pagination"})," for how to paginate the result."]}),"\n",(0,s.jsx)(n.h2,{id:"update",children:"Update"}),"\n",(0,s.jsx)(n.p,{children:"There are two update operations available."}),"\n",(0,s.jsx)(n.h3,{id:"update-a-single-row",children:"Update a single row"}),"\n",(0,s.jsxs)(n.p,{children:["To update a single row, use the ",(0,s.jsx)(n.code,{children:"updateRow"})," method."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var company = await Company.db.findById(session, companyId); // Fetched company has its id set \ncompany.name = 'New name';\nvar updatedCompany = await Company.db.updateRow(session, company);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The object that you update must have its ",(0,s.jsx)(n.code,{children:"id"})," set to a non-",(0,s.jsx)(n.code,{children:"null"})," value and the id needs to exist on a row in the database. The ",(0,s.jsx)(n.code,{children:"updateRow"})," method returns the updated object."]}),"\n",(0,s.jsx)(n.h3,{id:"update-several-rows",children:"Update several rows"}),"\n",(0,s.jsxs)(n.p,{children:["To batch update several rows use the ",(0,s.jsx)(n.code,{children:"update"})," method."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var companies = await Company.db.find(session);\ncompanies = companies.map((c) => c.copyWith(name: 'New name')).toList();\nvar updatedCompanies = await Company.db.update(session, companies);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This is an atomic operation, meaning no entries will be updated if any entry fails to be updated. The ",(0,s.jsx)(n.code,{children:"update"})," method returns a ",(0,s.jsx)(n.code,{children:"List"})," of the updated objects."]}),"\n",(0,s.jsx)(n.h2,{id:"delete",children:"Delete"}),"\n",(0,s.jsx)(n.p,{children:"Deleting rows from the database is done in a similar way to updating rows. However, there are three delete operations available."}),"\n",(0,s.jsx)(n.h3,{id:"delete-a-single-row",children:"Delete a single row"}),"\n",(0,s.jsxs)(n.p,{children:["To delete a single row, use the ",(0,s.jsx)(n.code,{children:"deleteRow"})," method."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var company = await Company.db.findById(session, companyId); // Fetched company has its id set \nvar companyDeleted = await Company.db.deleteRow(session, company);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The input object needs to have the ",(0,s.jsx)(n.code,{children:"id"})," field set. The ",(0,s.jsx)(n.code,{children:"deleteRow"})," method returns the deleted model."]}),"\n",(0,s.jsx)(n.h3,{id:"delete-several-rows",children:"Delete several rows"}),"\n",(0,s.jsxs)(n.p,{children:["To batch delete several rows, use the ",(0,s.jsx)(n.code,{children:"delete"})," method."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var companiesDeleted = await Company.db.delete(session, companies);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This is an atomic operation, meaning no entries will be deleted if any entry fails to be deleted. The ",(0,s.jsx)(n.code,{children:"delete"})," method returns a ",(0,s.jsx)(n.code,{children:"List"})," of the models deleted."]}),"\n",(0,s.jsx)(n.h3,{id:"delete-by-filter",children:"Delete by filter"}),"\n",(0,s.jsxs)(n.p,{children:["You can also do a ",(0,s.jsx)(n.a,{href:"filter",children:"filtered"})," delete and delete all entries matching a ",(0,s.jsx)(n.code,{children:"where"})," query, by using the ",(0,s.jsx)(n.code,{children:"deleteWhere"})," method."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var companiesDeleted = await Company.db.deleteWhere(\n session,\n where: (t) => t.name.like('%Ltd'),\n);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The above example will delete any row that ends in ",(0,s.jsx)(n.em,{children:"Ltd"}),". The ",(0,s.jsx)(n.code,{children:"deleteWhere"})," method returns a ",(0,s.jsx)(n.code,{children:"List"})," of the models deleted."]}),"\n",(0,s.jsx)(n.h2,{id:"count",children:"Count"}),"\n",(0,s.jsxs)(n.p,{children:["Count is a special type of query that helps counting the number of rows in the database that matches a specific ",(0,s.jsx)(n.a,{href:"filter",children:"filter"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var count = await Company.db.count(\n session, \n where: (t) => t.name.like('s%'),\n);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The return value is an ",(0,s.jsx)(n.code,{children:"int"})," for the number of rows matching the filter."]})]})}function h(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},11151:(e,n,i)=>{i.d(n,{Z:()=>r,a:()=>d});var s=i(67294);const t={},a=s.createContext(t);function d(e){const n=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:d(e.components),s.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/b9ec56c8.42068d6e.js b/docs/assets/js/b9ec56c8.42068d6e.js new file mode 100644 index 000000000..6801b6f35 --- /dev/null +++ b/docs/assets/js/b9ec56c8.42068d6e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkserverpod_docs=self.webpackChunkserverpod_docs||[]).push([[3029],{56271:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>i,metadata:()=>r,toc:()=>l});var s=a(85893),t=a(11151);const i={},o="Database communication",r={id:"concepts/database-communication",title:"Database communication",description:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files.",source:"@site/versioned_docs/version-0.9.22/04-concepts/03-database-communication.md",sourceDirName:"04-concepts",slug:"/concepts/database-communication",permalink:"/0.9.22/concepts/database-communication",draft:!1,unlisted:!1,editUrl:"https://github.com/serverpod/serverpod_docs/tree/main/versioned_docs/version-0.9.22/04-concepts/03-database-communication.md",tags:[],version:"0.9.22",sidebarPosition:3,frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Serialization",permalink:"/0.9.22/concepts/serialization"},next:{title:"Caching",permalink:"/0.9.22/concepts/caching"}},d={},l=[{value:"Database mappings",id:"database-mappings",level:2},{value:"Field scopes",id:"field-scopes",level:3},{value:"Database indexes",id:"database-indexes",level:3},{value:"Parent/child relationships",id:"parentchild-relationships",level:3},{value:"Storing objects or references",id:"storing-objects-or-references",level:3},{value:"Making queries",id:"making-queries",level:2},{value:"Inserting a table row",id:"inserting-a-table-row",level:3},{value:"Finding a single row",id:"finding-a-single-row",level:3},{value:"Finding multiple rows",id:"finding-multiple-rows",level:3},{value:"Updating a row",id:"updating-a-row",level:3},{value:"Deleting rows",id:"deleting-rows",level:3},{value:"Creating expressions",id:"creating-expressions",level:3},{value:"Joining tables and nesting objects",id:"joining-tables-and-nesting-objects",level:3},{value:"Transactions",id:"transactions",level:3},{value:"Executing raw queries",id:"executing-raw-queries",level:3}];function c(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,t.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"database-communication",children:"Database communication"}),"\n",(0,s.jsx)(n.p,{children:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files."}),"\n",(0,s.jsx)(n.h2,{id:"database-mappings",children:"Database mappings"}),"\n",(0,s.jsxs)(n.p,{children:["It's possible to map serializable classes straight to tables in your database. To do this, add the ",(0,s.jsx)(n.code,{children:"table"})," key to your yaml file:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n"})}),"\n",(0,s.jsxs)(n.p,{children:["When running ",(0,s.jsx)(n.code,{children:"serverpod generate"}),", the database schema will be saved in the ",(0,s.jsx)(n.code,{children:"generated/tables.pgsql"})," file. You can use this to create the corresponding database tables."]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["When you add a ",(0,s.jsx)(n.code,{children:"table"})," to a serializable class, Serverpod will automatically add an ",(0,s.jsx)(n.code,{children:"id"})," field of type ",(0,s.jsx)(n.code,{children:"int?"})," to the class. You should not define this field yourself. The ",(0,s.jsx)(n.code,{children:"id"})," is set when you insert or select a row from the database. The ",(0,s.jsx)(n.code,{children:"id"})," field allows you to do updates and reference the rows from other objects and tables."]})}),"\n",(0,s.jsx)(n.h3,{id:"field-scopes",children:"Field scopes"}),"\n",(0,s.jsxs)(n.p,{children:["In some cases, you want to save a field to the database, but it should never be sent to the server. You can exclude it from the protocol by adding the ",(0,s.jsx)(n.code,{children:"database"})," scope to the type."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: UserData\nfields:\n name: String\n password: String?, database\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Likewise, if you only want a field to be accessible in the protocol but not stored in the server, you can add the ",(0,s.jsx)(n.code,{children:"api"})," flag. By default, a field is accessible to both the API and the database."]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["If you use the ",(0,s.jsx)(n.code,{children:"database"})," or ",(0,s.jsx)(n.code,{children:"api"})," options the field must be nullable."]})}),"\n",(0,s.jsx)(n.h3,{id:"database-indexes",children:"Database indexes"}),"\n",(0,s.jsx)(n.p,{children:"For performance reasons, you may want to add indexes to your database tables. You add these in the yaml-files defining the serializable objects."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n employees: List?, api\nindexes:\n company_name_idx:\n fields: name\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"fields"})," key holds a comma-separated list of column names. In addition, it's possible to add a type key (default is ",(0,s.jsx)(n.code,{children:"btree"}),"), and a ",(0,s.jsx)(n.code,{children:"unique"})," key (default is ",(0,s.jsx)(n.code,{children:"false"}),")."]}),"\n",(0,s.jsx)(n.h3,{id:"parentchild-relationships",children:"Parent/child relationships"}),"\n",(0,s.jsx)(n.p,{children:"With a field's parent property, you can define a relationship with a table's parent table. This relationship ensures that the parent id is always valid and that if you delete the referenced parent, the referencing row will automatically be deleted."}),"\n",(0,s.jsxs)(n.p,{children:["The employee's ",(0,s.jsx)(n.code,{children:"parent"})," is set to the ",(0,s.jsx)(n.code,{children:"company"})," table in the example below. If you remove the company, all employees of the company will automatically be removed. When you insert the employee into the database, you must specify a valid ",(0,s.jsx)(n.code,{children:"companyId"})," that corresponds to the id field in the ",(0,s.jsx)(n.code,{children:"company"})," table."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Employee\ntable: employee\nfields:\n companyId: int, parent=company\n name: String\n birthday: DateTime\n"})}),"\n",(0,s.jsx)(n.h3,{id:"storing-objects-or-references",children:"Storing objects or references"}),"\n",(0,s.jsxs)(n.p,{children:["If you reference another serializable object in your yaml file, it will be stored as a JSON entry in the database. This creates a copy of that object. In many cases, this is not desirable. Instead, you may want to reference that object by an id from another table. See the section on ",(0,s.jsx)(n.a,{href:"#joining-tables-and-nesting-objects",children:"joining tables and nesting objects"})," below for more information."]}),"\n",(0,s.jsx)(n.p,{children:"In the example below, a list of employees is stored as a JSON structure for each company in the database. A better solution would be to create a database row for each employee and reference the company. However, there are cases where it is convenient to store whole JSON structures in each row."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n employees: List # Stored as JSON structure\n"})}),"\n",(0,s.jsx)(n.h2,{id:"making-queries",children:"Making queries"}),"\n",(0,s.jsxs)(n.p,{children:["For the communication to work, you need to have generated serializable classes with the ",(0,s.jsx)(n.code,{children:"table"})," key set, and the corresponding table must have been created in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"inserting-a-table-row",children:"Inserting a table row"}),"\n",(0,s.jsxs)(n.p,{children:["Insert a new row in the database by calling the insert method of the ",(0,s.jsx)(n.code,{children:"db"})," field in your ",(0,s.jsx)(n.code,{children:"Session"})," object."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myRow = Company(name: 'Serverpod corp.', employees: []);\nawait Company.insert(session, myRow);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["After the object has been inserted, it's ",(0,s.jsx)(n.code,{children:"id"})," field is set from its row in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"finding-a-single-row",children:"Finding a single row"}),"\n",(0,s.jsxs)(n.p,{children:["You can find a single row, either by its ",(0,s.jsx)(n.code,{children:"id"})," or using an expression. You need to pass a reference to the a session in the call. Tables are accessible through generated serializable classes."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findById(session, companyId);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If no matching row is found, ",(0,s.jsx)(n.code,{children:"null"})," is returned. You can also search for rows using expressions with the ",(0,s.jsx)(n.code,{children:"where"})," parameter. The ",(0,s.jsx)(n.code,{children:"where"})," parameter is a typed expression builder. The builder's parameter, ",(0,s.jsx)(n.code,{children:"t"}),", contains a description of the table which gives access to the table's columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findSingleRow(\n session,\n where: (t) => t.name.equals('My Company'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"finding-multiple-rows",children:"Finding multiple rows"}),"\n",(0,s.jsxs)(n.p,{children:["To find multiple rows, use the same principle as for finding a single row. Returned will be a ",(0,s.jsx)(n.code,{children:"List"})," of ",(0,s.jsx)(n.code,{children:"TableRow"}),"s."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var companies = await Company.find(\n tCompany,\n where: (t) => t.id < 100,\n limit: 50,\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"updating-a-row",children:"Updating a row"}),"\n",(0,s.jsxs)(n.p,{children:["To update a row, use the ",(0,s.jsx)(n.code,{children:"update"})," method. The object that you update must have its ",(0,s.jsx)(n.code,{children:"id"})," set to a non-",(0,s.jsx)(n.code,{children:"null"})," value."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await session.db.findById(tCompany, companyId) as Company?;\nmyCompany.name = 'New name';\nawait session.db.update(myCompany);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"deleting-rows",children:"Deleting rows"}),"\n",(0,s.jsxs)(n.p,{children:["Deleting a single row works similarly to the ",(0,s.jsx)(n.code,{children:"update"})," method, but you can also delete rows using the where parameter."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// Delete a single row\nawait Company.deleteRow(session, myCompany);\n\n// Delete all rows where the company name ends with 'Ltd'\nawait Company.delete(\n where: (t) => t.name.like('%Ltd'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"creating-expressions",children:"Creating expressions"}),"\n",(0,s.jsxs)(n.p,{children:["To find or delete specific rows, most often, expressions are needed. Serverpod makes it easy to build expressions that are statically type-checked. Columns are referenced using the global table descriptor objects. The table descriptors, ",(0,s.jsx)(n.code,{children:"t"})," are passed to the expression builder function. The ",(0,s.jsx)(n.code,{children:">"}),", ",(0,s.jsx)(n.code,{children:">="}),", ",(0,s.jsx)(n.code,{children:"<"}),", ",(0,s.jsx)(n.code,{children:"<="}),", ",(0,s.jsx)(n.code,{children:"&"}),", and ",(0,s.jsx)(n.code,{children:"|"})," operators are overridden to make it easier to work with column values. When using the operators, it's a good practice to place them within a set of parentheses as the precedence rules are not always what would be expected. These are some examples of expressions."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// The name column of the Company table equals 'My company')\nt.name.equals('My company')\n\n// Companies founded at or after 2020\nt.foundedDate >= DateTime.utc(2020)\n\n// Companies with number of employees between 10 and 100\n(t.numEmployees > 10) & (t.numEmployees <= 100)\n\n// Companies that has the founded date set\nt.foundedDate.notEquals(null)\n"})}),"\n",(0,s.jsx)(n.h3,{id:"joining-tables-and-nesting-objects",children:"Joining tables and nesting objects"}),"\n",(0,s.jsx)(n.p,{children:"Serverpod does not yet support joins automatically. However, you can easily create nested objects by performing two or more queries."}),"\n",(0,s.jsxs)(n.p,{children:["For instance, if you have a ",(0,s.jsx)(n.code,{children:"Company"})," object with a list of ",(0,s.jsx)(n.code,{children:"Employee"})," it can be declared like this:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"# company.yaml\nclass: Company\ntable: company\nfields:\n name: String\n employees: List?, api\n\n# employee.yaml\nclass: Employee\ntable: employee\nfields:\n companyId: int\n name: String\n birthday: DateTime\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This prevents the list of ",(0,s.jsx)(n.code,{children:"Employee"})," to be automatically fetched or stored in the database. After you fetch a ",(0,s.jsx)(n.code,{children:"Company"})," object from the database, format it by fetching the list of ",(0,s.jsx)(n.code,{children:"Employees"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var company = await Company.findById(session, id);\n\nvar employees = await Employee.find(\n session,\n where: (t) => t.companyId.equals(company.id),\n);\n\ncompany.employees = employees;\n"})}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsx)(n.p,{children:"Future versions of Serverpod will add support for automatic joins and database views."})}),"\n",(0,s.jsx)(n.h3,{id:"transactions",children:"Transactions"}),"\n",(0,s.jsx)(n.p,{children:"The essential point of a database transaction is that it bundles multiple steps into a single, all-or-nothing operation. The intermediate states between the steps are not visible to other concurrent transactions, and if some failure occurs that prevents the transaction from completing, then none of the steps affect the database at all."}),"\n",(0,s.jsxs)(n.p,{children:["Serverpod handles database transactions through the ",(0,s.jsx)(n.code,{children:"session.db.transaction"})," method. The transaction takes a method that performs any database queries or other operations and optionally returns a value."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var result = await session.db.transaction((transaction) async {\n // Do some database queries here.\n\n // Optionally return a value.\n return true;\n});\n"})}),"\n",(0,s.jsx)(n.h3,{id:"executing-raw-queries",children:"Executing raw queries"}),"\n",(0,s.jsxs)(n.p,{children:["Sometimes more advanced tasks need to be performed on the database. For those occasions, it's possible to run raw SQL queries on the database. Use the ",(0,s.jsx)(n.code,{children:"query"})," method. A ",(0,s.jsx)(n.code,{children:"List>"})," will be returned with rows and columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var result = await session.db.query('SELECT * FROM mytable WHERE ...');\n"})})]})}function h(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},11151:(e,n,a)=>{a.d(n,{Z:()=>r,a:()=>o});var s=a(67294);const t={},i=s.createContext(t);function o(e){const n=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),s.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/e3443ce0.5d1e4720.js b/docs/assets/js/e3443ce0.5d1e4720.js new file mode 100644 index 000000000..a2891175b --- /dev/null +++ b/docs/assets/js/e3443ce0.5d1e4720.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkserverpod_docs=self.webpackChunkserverpod_docs||[]).push([[7427],{71494:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>t,metadata:()=>r,toc:()=>l});var s=a(85893),i=a(11151);const t={},o="Database communication",r={id:"concepts/database-communication",title:"Database communication",description:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files.",source:"@site/versioned_docs/version-0.9.9/03-concepts/03-database-communication.md",sourceDirName:"03-concepts",slug:"/concepts/database-communication",permalink:"/0.9.9/concepts/database-communication",draft:!1,unlisted:!1,editUrl:"https://github.com/serverpod/serverpod_docs/tree/main/versioned_docs/version-0.9.9/03-concepts/03-database-communication.md",tags:[],version:"0.9.9",sidebarPosition:3,frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Serialization",permalink:"/0.9.9/concepts/serialization"},next:{title:"Caching",permalink:"/0.9.9/concepts/caching"}},d={},l=[{value:"Database mappings",id:"database-mappings",level:2},{value:"Database indexes",id:"database-indexes",level:3},{value:"Making queries",id:"making-queries",level:2},{value:"Inserting a table row",id:"inserting-a-table-row",level:3},{value:"Finding a single row",id:"finding-a-single-row",level:3},{value:"Finding multiple rows",id:"finding-multiple-rows",level:3},{value:"Updating a row",id:"updating-a-row",level:3},{value:"Deleting rows",id:"deleting-rows",level:3},{value:"Creating expressions",id:"creating-expressions",level:3},{value:"Transactions",id:"transactions",level:3},{value:"Executing raw queries",id:"executing-raw-queries",level:3}];function c(e){const n={code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,i.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"database-communication",children:"Database communication"}),"\n",(0,s.jsx)(n.p,{children:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files."}),"\n",(0,s.jsx)(n.h2,{id:"database-mappings",children:"Database mappings"}),"\n",(0,s.jsxs)(n.p,{children:["It's possible to map serializable classes straight to tables in your database. To do this, add the ",(0,s.jsx)(n.code,{children:"table"})," key to your yaml file:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n employees: List\n"})}),"\n",(0,s.jsxs)(n.p,{children:["When running ",(0,s.jsx)(n.code,{children:"serverpod generate"}),", the database schema will be saved in the ",(0,s.jsx)(n.code,{children:"generated/tables.pgsql"})," file. You can use this to create the corresponding database tables."]}),"\n",(0,s.jsxs)(n.p,{children:["In some cases, you want to save a field to the database, but it should never be sent to the server. You can exclude it from the protocol by adding the ",(0,s.jsx)(n.code,{children:"database"})," flag to the type."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: UserData\nfields:\n name: String\n password: String, database\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Likewise, if you only want a field to be accessible in the protocol but not stored in the server, you can add the ",(0,s.jsx)(n.code,{children:"api"})," flag. By default, a field is accessible to both the API and the database."]}),"\n",(0,s.jsx)(n.h3,{id:"database-indexes",children:"Database indexes"}),"\n",(0,s.jsx)(n.p,{children:"For performance reasons, you may want to add indexes to your database tables. You add these in the yaml-files defining the serializable objects."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n employees: List\nindexes:\n company_name_idx:\n fields: name\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"fields"})," key holds a comma-separated list of column names. In addition, it's possible to add a type key (default is ",(0,s.jsx)(n.code,{children:"btree"}),"), and a ",(0,s.jsx)(n.code,{children:"unique"})," key (default is ",(0,s.jsx)(n.code,{children:"false"}),")."]}),"\n",(0,s.jsx)(n.h2,{id:"making-queries",children:"Making queries"}),"\n",(0,s.jsxs)(n.p,{children:["For the communication to work, you need to have generated serializable classes with the ",(0,s.jsx)(n.code,{children:"table"})," key set, and the corresponding table must have been created in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"inserting-a-table-row",children:"Inserting a table row"}),"\n",(0,s.jsxs)(n.p,{children:["Insert a new row in the database by calling the insert method of the ",(0,s.jsx)(n.code,{children:"db"})," field in your ",(0,s.jsx)(n.code,{children:"Session"})," object."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myRow = Company(name: 'Serverpod corp.', employees: []);\nawait Company.insert(session, myRow);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["After the object has been inserted, it's ",(0,s.jsx)(n.code,{children:"id"})," field is set from its row in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"finding-a-single-row",children:"Finding a single row"}),"\n",(0,s.jsxs)(n.p,{children:["You can find a single row, either by its ",(0,s.jsx)(n.code,{children:"id"})," or using an expression. You need to pass a reference to the a session in the call. Tables are accessible through generated serializable classes."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findById(session, companyId);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If no matching row is found, ",(0,s.jsx)(n.code,{children:"null"})," is returned. You can also search for rows using expressions with the ",(0,s.jsx)(n.code,{children:"where"})," parameter. The ",(0,s.jsx)(n.code,{children:"where"})," parameter is a typed expression builder. The builder's parameter, ",(0,s.jsx)(n.code,{children:"t"}),", contains a description of the table which gives access to the table's columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findSingleRow(\n session,\n where: (t) => t.name.equals('My Company'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"finding-multiple-rows",children:"Finding multiple rows"}),"\n",(0,s.jsxs)(n.p,{children:["To find multiple rows, use the same principle as for finding a single row. Returned will be a ",(0,s.jsx)(n.code,{children:"List"})," of ",(0,s.jsx)(n.code,{children:"TableRow"}),"s."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var companies = await Company.find(\n tCompany,\n where: (t) => t.id < 100,\n limit: 50,\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"updating-a-row",children:"Updating a row"}),"\n",(0,s.jsxs)(n.p,{children:["To update a row, use the ",(0,s.jsx)(n.code,{children:"update"})," method. The object that you update must have its ",(0,s.jsx)(n.code,{children:"id"})," set to a non ",(0,s.jsx)(n.code,{children:"null"})," value."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await session.db.findById(tCompany, companyId) as Company?;\nmyCompany.name = 'New name';\nawait session.db.update(myCompany);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"deleting-rows",children:"Deleting rows"}),"\n",(0,s.jsxs)(n.p,{children:["Deleting a single row works similarly to the ",(0,s.jsx)(n.code,{children:"update"})," method, but you can also delete rows using the where parameter."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// Delete a single row\nawait Company.deleteRow(session, myCompany);\n\n// Delete all rows where the company name ends with 'Ltd'\nawait Company.delete(\n where: (t) => t.name.like('%Ltd'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"creating-expressions",children:"Creating expressions"}),"\n",(0,s.jsxs)(n.p,{children:["To find or delete specific rows, most often, expressions are needed. Serverpod makes it easy to build expressions that are statically type-checked. Columns are referenced using the global table descriptor objects. The table descriptors, ",(0,s.jsx)(n.code,{children:"t"})," are passed to the expression builder function. The ",(0,s.jsx)(n.code,{children:">"}),", ",(0,s.jsx)(n.code,{children:">="}),", ",(0,s.jsx)(n.code,{children:"<"}),", ",(0,s.jsx)(n.code,{children:"<="}),", ",(0,s.jsx)(n.code,{children:"&"}),", and ",(0,s.jsx)(n.code,{children:"|"})," operators are overridden to make it easier to work with column values. When using the operators, it's a good practice to place them within a set of parentheses as the precedence rules are not always what would be expected. These are some examples of expressions."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// The name column of the Company table equals 'My company')\nt.name.equals('My company')\n\n// Companies founded at or after 2020\nt.foundedDate >= DateTime.utc(2020)\n\n// Companies with number of employees between 10 and 100\n(t.numEmployees > 10) & (t.numEmployees <= 100)\n\n// Companies that has the founded date set\nt.foundedDate.notEquals(null)\n"})}),"\n",(0,s.jsx)(n.h3,{id:"transactions",children:"Transactions"}),"\n",(0,s.jsx)(n.p,{children:"Docs coming."}),"\n",(0,s.jsx)(n.h3,{id:"executing-raw-queries",children:"Executing raw queries"}),"\n",(0,s.jsxs)(n.p,{children:["Sometimes more advanced tasks need to be performed on the database. For those occasions, it's possible to run raw SQL queries on the database. Use the ",(0,s.jsx)(n.code,{children:"query"})," method. A ",(0,s.jsx)(n.code,{children:"List>"})," will be returned with rows and columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var result = await session.db.query('SELECT * FROM mytable WHERE ...');\n"})})]})}function h(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},11151:(e,n,a)=>{a.d(n,{Z:()=>r,a:()=>o});var s=a(67294);const i={},t=s.createContext(i);function o(e){const n=s.useContext(t);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/eecc43ff.a7c864af.js b/docs/assets/js/eecc43ff.a7c864af.js new file mode 100644 index 000000000..04ba2639d --- /dev/null +++ b/docs/assets/js/eecc43ff.a7c864af.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkserverpod_docs=self.webpackChunkserverpod_docs||[]).push([[845],{64050:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>i,metadata:()=>r,toc:()=>l});var s=a(85893),t=a(11151);const i={},o="Database communication",r={id:"concepts/database-communication",title:"Database communication",description:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files.",source:"@site/versioned_docs/version-1.1.0/04-concepts/05-database-communication.md",sourceDirName:"04-concepts",slug:"/concepts/database-communication",permalink:"/1.1.0/concepts/database-communication",draft:!1,unlisted:!1,editUrl:"https://github.com/serverpod/serverpod_docs/tree/main/versioned_docs/version-1.1.0/04-concepts/05-database-communication.md",tags:[],version:"1.1.0",sidebarPosition:5,frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Error handling and exceptions",permalink:"/1.1.0/concepts/exceptions"},next:{title:"Caching",permalink:"/1.1.0/concepts/caching"}},d={},l=[{value:"Database mappings",id:"database-mappings",level:2},{value:"Field scopes",id:"field-scopes",level:3},{value:"Database indexes",id:"database-indexes",level:3},{value:"Parent/child relationships",id:"parentchild-relationships",level:3},{value:"Storing objects or references",id:"storing-objects-or-references",level:3},{value:"Making queries",id:"making-queries",level:2},{value:"Inserting a table row",id:"inserting-a-table-row",level:3},{value:"Finding a single row",id:"finding-a-single-row",level:3},{value:"Finding multiple rows",id:"finding-multiple-rows",level:3},{value:"Updating a row",id:"updating-a-row",level:3},{value:"Deleting rows",id:"deleting-rows",level:3},{value:"Creating expressions",id:"creating-expressions",level:3},{value:"Ordering rows",id:"ordering-rows",level:3},{value:"Joining tables and nesting objects",id:"joining-tables-and-nesting-objects",level:3},{value:"Transactions",id:"transactions",level:3},{value:"Executing raw queries",id:"executing-raw-queries",level:3}];function c(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,t.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"database-communication",children:"Database communication"}),"\n",(0,s.jsx)(n.p,{children:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files."}),"\n",(0,s.jsx)(n.h2,{id:"database-mappings",children:"Database mappings"}),"\n",(0,s.jsxs)(n.p,{children:["It's possible to map serializable classes straight to tables in your database. To do this, add the ",(0,s.jsx)(n.code,{children:"table"})," key to your yaml file:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n"})}),"\n",(0,s.jsxs)(n.p,{children:["When running ",(0,s.jsx)(n.code,{children:"serverpod generate"}),", the database schema will be saved in the ",(0,s.jsx)(n.code,{children:"generated/tables.pgsql"})," file. You can use this to create the corresponding database tables."]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["When you add a ",(0,s.jsx)(n.code,{children:"table"})," to a serializable class, Serverpod will automatically add an ",(0,s.jsx)(n.code,{children:"id"})," field of type ",(0,s.jsx)(n.code,{children:"int?"})," to the class. You should not define this field yourself. The ",(0,s.jsx)(n.code,{children:"id"})," is set when you insert or select a row from the database. The ",(0,s.jsx)(n.code,{children:"id"})," field allows you to do updates and reference the rows from other objects and tables."]})}),"\n",(0,s.jsx)(n.h3,{id:"field-scopes",children:"Field scopes"}),"\n",(0,s.jsxs)(n.p,{children:["In some cases, you want to save a field to the database, but it should never be sent to the server. You can exclude it from the protocol by adding the ",(0,s.jsx)(n.code,{children:"database"})," scope to the type."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: UserData\nfields:\n name: String\n password: String?, database\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Likewise, if you only want a field to be accessible in the protocol but not stored in the server, you can add the ",(0,s.jsx)(n.code,{children:"api"})," flag. By default, a field is accessible to both the API and the database."]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["If you use the ",(0,s.jsx)(n.code,{children:"database"})," or ",(0,s.jsx)(n.code,{children:"api"})," options the field must be nullable."]})}),"\n",(0,s.jsx)(n.h3,{id:"database-indexes",children:"Database indexes"}),"\n",(0,s.jsx)(n.p,{children:"For performance reasons, you may want to add indexes to your database tables. You add these in the yaml-files defining the serializable objects."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n employees: List?, api\nindexes:\n company_name_idx:\n fields: name\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"fields"})," key holds a comma-separated list of column names. In addition, it's possible to add a type key (default is ",(0,s.jsx)(n.code,{children:"btree"}),"), and a ",(0,s.jsx)(n.code,{children:"unique"})," key (default is ",(0,s.jsx)(n.code,{children:"false"}),")."]}),"\n",(0,s.jsx)(n.h3,{id:"parentchild-relationships",children:"Parent/child relationships"}),"\n",(0,s.jsx)(n.p,{children:"With a field's parent property, you can define a relationship with a table's parent table. This relationship ensures that the parent id is always valid and that if you delete the referenced parent, the referencing row will automatically be deleted."}),"\n",(0,s.jsxs)(n.p,{children:["The employee's ",(0,s.jsx)(n.code,{children:"parent"})," is set to the ",(0,s.jsx)(n.code,{children:"company"})," table in the example below. If you remove the company, all employees of the company will automatically be removed. When you insert the employee into the database, you must specify a valid ",(0,s.jsx)(n.code,{children:"companyId"})," that corresponds to the id field in the ",(0,s.jsx)(n.code,{children:"company"})," table."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Employee\ntable: employee\nfields:\n companyId: int, parent=company\n name: String\n birthday: DateTime\n"})}),"\n",(0,s.jsx)(n.h3,{id:"storing-objects-or-references",children:"Storing objects or references"}),"\n",(0,s.jsxs)(n.p,{children:["If you reference another serializable object in your yaml file, it will be stored as a JSON entry in the database. This creates a copy of that object. In many cases, this is not desirable. Instead, you may want to reference that object by an id from another table. See the section on ",(0,s.jsx)(n.a,{href:"#joining-tables-and-nesting-objects",children:"joining tables and nesting objects"})," below for more information."]}),"\n",(0,s.jsx)(n.p,{children:"In the example below, a list of employees is stored as a JSON structure for each company in the database. A better solution would be to create a database row for each employee and reference the company. However, there are cases where it is convenient to store whole JSON structures in each row."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n employees: List # Stored as JSON structure\n"})}),"\n",(0,s.jsx)(n.h2,{id:"making-queries",children:"Making queries"}),"\n",(0,s.jsxs)(n.p,{children:["For the communication to work, you need to have generated serializable classes with the ",(0,s.jsx)(n.code,{children:"table"})," key set, and the corresponding table must have been created in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"inserting-a-table-row",children:"Inserting a table row"}),"\n",(0,s.jsxs)(n.p,{children:["Insert a new row in the database by calling the insert method of the ",(0,s.jsx)(n.code,{children:"db"})," field in your ",(0,s.jsx)(n.code,{children:"Session"})," object."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myRow = Company(name: 'Serverpod corp.', employees: []);\nawait Company.insert(session, myRow);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["After the object has been inserted, it's ",(0,s.jsx)(n.code,{children:"id"})," field is set from its row in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"finding-a-single-row",children:"Finding a single row"}),"\n",(0,s.jsxs)(n.p,{children:["You can find a single row, either by its ",(0,s.jsx)(n.code,{children:"id"})," or using an expression. You need to pass a reference to the a session in the call. Tables are accessible through generated serializable classes."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findById(session, companyId);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If no matching row is found, ",(0,s.jsx)(n.code,{children:"null"})," is returned. You can also search for rows using expressions with the ",(0,s.jsx)(n.code,{children:"where"})," parameter. The ",(0,s.jsx)(n.code,{children:"where"})," parameter is a typed expression builder. The builder's parameter, ",(0,s.jsx)(n.code,{children:"t"}),", contains a description of the table which gives access to the table's columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findSingleRow(\n session,\n where: (t) => t.name.equals('My Company'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"finding-multiple-rows",children:"Finding multiple rows"}),"\n",(0,s.jsxs)(n.p,{children:["To find multiple rows, use the same principle as for finding a single row. Returned will be a ",(0,s.jsx)(n.code,{children:"List"})," of ",(0,s.jsx)(n.code,{children:"TableRow"}),"s."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var companies = await Company.find(\n tCompany,\n where: (t) => t.id < 100,\n limit: 50,\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"updating-a-row",children:"Updating a row"}),"\n",(0,s.jsxs)(n.p,{children:["To update a row, use the ",(0,s.jsx)(n.code,{children:"update"})," method. The object that you update must have its ",(0,s.jsx)(n.code,{children:"id"})," set to a non-",(0,s.jsx)(n.code,{children:"null"})," value."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await session.db.findById(tCompany, companyId) as Company?;\nmyCompany.name = 'New name';\nawait session.db.update(myCompany);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"deleting-rows",children:"Deleting rows"}),"\n",(0,s.jsxs)(n.p,{children:["Deleting a single row works similarly to the ",(0,s.jsx)(n.code,{children:"update"})," method, but you can also delete rows using the where parameter."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// Delete a single row\nawait Company.deleteRow(session, myCompany);\n\n// Delete all rows where the company name ends with 'Ltd'\nawait Company.delete(\n where: (t) => t.name.like('%Ltd'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"creating-expressions",children:"Creating expressions"}),"\n",(0,s.jsxs)(n.p,{children:["To find or delete specific rows, most often, expressions are needed. Serverpod makes it easy to build expressions that are statically type-checked. Columns are referenced using the global table descriptor objects. The table descriptors, ",(0,s.jsx)(n.code,{children:"t"})," are passed to the expression builder function. The ",(0,s.jsx)(n.code,{children:">"}),", ",(0,s.jsx)(n.code,{children:">="}),", ",(0,s.jsx)(n.code,{children:"<"}),", ",(0,s.jsx)(n.code,{children:"<="}),", ",(0,s.jsx)(n.code,{children:"&"}),", and ",(0,s.jsx)(n.code,{children:"|"})," operators are overridden to make it easier to work with column values. When using the operators, it's a good practice to place them within a set of parentheses as the precedence rules are not always what would be expected. These are some examples of expressions."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// The name column of the Company table equals 'My company')\nt.name.equals('My company')\n\n// Companies founded at or after 2020\nt.foundedDate >= DateTime.utc(2020)\n\n// Companies with number of employees between 10 and 100\n(t.numEmployees > 10) & (t.numEmployees <= 100)\n\n// Companies that has the founded date set\nt.foundedDate.notEquals(null)\n"})}),"\n",(0,s.jsx)(n.h3,{id:"ordering-rows",children:"Ordering rows"}),"\n",(0,s.jsxs)(n.p,{children:["It is often desirable to order the results of a database query. The ",(0,s.jsx)(n.code,{children:"find"})," method contains an ",(0,s.jsx)(n.code,{children:"orderBy"})," parameter, to which you can pass a column to order by. The static ",(0,s.jsx)(n.code,{children:"t"})," field on your serializable objects includes a reference to a representation of your table. It has a field for each column."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var companies = await Company.find(\n session,\n orderBy: Company.t.name,\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"joining-tables-and-nesting-objects",children:"Joining tables and nesting objects"}),"\n",(0,s.jsx)(n.p,{children:"Serverpod does not yet support joins automatically. However, you can easily create nested objects by performing two or more queries."}),"\n",(0,s.jsxs)(n.p,{children:["For instance, if you have a ",(0,s.jsx)(n.code,{children:"Company"})," object with a list of ",(0,s.jsx)(n.code,{children:"Employee"})," it can be declared like this:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"# company.yaml\nclass: Company\ntable: company\nfields:\n name: String\n employees: List?, api\n\n# employee.yaml\nclass: Employee\ntable: employee\nfields:\n companyId: int\n name: String\n birthday: DateTime\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This prevents the list of ",(0,s.jsx)(n.code,{children:"Employee"})," to be automatically fetched or stored in the database. After you fetch a ",(0,s.jsx)(n.code,{children:"Company"})," object from the database, format it by fetching the list of ",(0,s.jsx)(n.code,{children:"Employees"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var company = await Company.findById(session, id);\n\nvar employees = await Employee.find(\n session,\n where: (t) => t.companyId.equals(company.id),\n);\n\ncompany.employees = employees;\n"})}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsx)(n.p,{children:"Future versions of Serverpod will add support for automatic joins and database views."})}),"\n",(0,s.jsx)(n.h3,{id:"transactions",children:"Transactions"}),"\n",(0,s.jsx)(n.p,{children:"The essential point of a database transaction is that it bundles multiple steps into a single, all-or-nothing operation. The intermediate states between the steps are not visible to other concurrent transactions, and if some failure occurs that prevents the transaction from completing, then none of the steps affect the database at all."}),"\n",(0,s.jsxs)(n.p,{children:["Serverpod handles database transactions through the ",(0,s.jsx)(n.code,{children:"session.db.transaction"})," method. The transaction takes a method that performs any database queries or other operations and optionally returns a value."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var result = await session.db.transaction((transaction) async {\n // Do some database queries here.\n\n // Optionally return a value.\n return true;\n});\n"})}),"\n",(0,s.jsx)(n.h3,{id:"executing-raw-queries",children:"Executing raw queries"}),"\n",(0,s.jsxs)(n.p,{children:["Sometimes more advanced tasks need to be performed on the database. For those occasions, it's possible to run raw SQL queries on the database. Use the ",(0,s.jsx)(n.code,{children:"query"})," method. A ",(0,s.jsx)(n.code,{children:"List>"})," will be returned with rows and columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var result = await session.db.query('SELECT * FROM mytable WHERE ...');\n"})})]})}function h(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},11151:(e,n,a)=>{a.d(n,{Z:()=>r,a:()=>o});var s=a(67294);const t={},i=s.createContext(t);function o(e){const n=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),s.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/ef4456b5.d6afbb0a.js b/docs/assets/js/ef4456b5.d6afbb0a.js new file mode 100644 index 000000000..8f2b33531 --- /dev/null +++ b/docs/assets/js/ef4456b5.d6afbb0a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkserverpod_docs=self.webpackChunkserverpod_docs||[]).push([[3283],{88655:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>t,metadata:()=>r,toc:()=>l});var s=a(85893),i=a(11151);const t={},o="Database communication",r={id:"concepts/database-communication",title:"Database communication",description:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files.",source:"@site/versioned_docs/version-0.9.6/02-concepts/03-database-communication.md",sourceDirName:"02-concepts",slug:"/concepts/database-communication",permalink:"/0.9.6/concepts/database-communication",draft:!1,unlisted:!1,editUrl:"https://github.com/serverpod/serverpod_docs/tree/main/versioned_docs/version-0.9.6/02-concepts/03-database-communication.md",tags:[],version:"0.9.6",sidebarPosition:3,frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Serialization",permalink:"/0.9.6/concepts/serialization"},next:{title:"Caching",permalink:"/0.9.6/concepts/caching"}},d={},l=[{value:"Database mappings",id:"database-mappings",level:2},{value:"Database indexes",id:"database-indexes",level:3},{value:"Making queries",id:"making-queries",level:2},{value:"Inserting a table row",id:"inserting-a-table-row",level:3},{value:"Finding a single row",id:"finding-a-single-row",level:3},{value:"Finding multiple rows",id:"finding-multiple-rows",level:3},{value:"Updating a row",id:"updating-a-row",level:3},{value:"Deleting rows",id:"deleting-rows",level:3},{value:"Creating expressions",id:"creating-expressions",level:3},{value:"Transactions",id:"transactions",level:3},{value:"Executing raw queries",id:"executing-raw-queries",level:3}];function c(e){const n={code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,i.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"database-communication",children:"Database communication"}),"\n",(0,s.jsx)(n.p,{children:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files."}),"\n",(0,s.jsx)(n.h2,{id:"database-mappings",children:"Database mappings"}),"\n",(0,s.jsxs)(n.p,{children:["It's possible to map serializable classes straight to tables in your database. To do this, add the ",(0,s.jsx)(n.code,{children:"table"})," key to your yaml file:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n employees: List\n"})}),"\n",(0,s.jsxs)(n.p,{children:["When running ",(0,s.jsx)(n.code,{children:"serverpod generate"}),", the database schema will be saved in the ",(0,s.jsx)(n.code,{children:"generated/tables.pgsql"})," file. You can use this to create the corresponding database tables."]}),"\n",(0,s.jsxs)(n.p,{children:["In some cases, you want to save a field to the database, but it should never be sent to the server. You can exclude it from the protocol by adding the ",(0,s.jsx)(n.code,{children:"database"})," flag to the type."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: UserData\nfields:\n name: String\n password: String, database\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Likewise, if you only want a field to be accessible in the protocol but not stored in the server, you can add the ",(0,s.jsx)(n.code,{children:"api"})," flag. By default, a field is accessible to both the API and the database."]}),"\n",(0,s.jsx)(n.h3,{id:"database-indexes",children:"Database indexes"}),"\n",(0,s.jsx)(n.p,{children:"For performance reasons, you may want to add indexes to your database tables. You add these in the yaml-files defining the serializable objects."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n employees: List\nindexes:\n company_name_idx:\n fields: name\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"fields"})," key holds a comma-separated list of column names. In addition, it's possible to add a type key (default is ",(0,s.jsx)(n.code,{children:"btree"}),"), and a ",(0,s.jsx)(n.code,{children:"unique"})," key (default is ",(0,s.jsx)(n.code,{children:"false"}),")."]}),"\n",(0,s.jsx)(n.h2,{id:"making-queries",children:"Making queries"}),"\n",(0,s.jsxs)(n.p,{children:["For the communication to work, you need to have generated serializable classes with the ",(0,s.jsx)(n.code,{children:"table"})," key set, and the corresponding table must have been created in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"inserting-a-table-row",children:"Inserting a table row"}),"\n",(0,s.jsxs)(n.p,{children:["Insert a new row in the database by calling the insert method of the ",(0,s.jsx)(n.code,{children:"db"})," field in your ",(0,s.jsx)(n.code,{children:"Session"})," object."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myRow = Company(name: 'Serverpod corp.', employees: []);\nawait Company.insert(session, myRow);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["After the object has been inserted, it's ",(0,s.jsx)(n.code,{children:"id"})," field is set from its row in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"finding-a-single-row",children:"Finding a single row"}),"\n",(0,s.jsxs)(n.p,{children:["You can find a single row, either by its ",(0,s.jsx)(n.code,{children:"id"})," or using an expression. You need to pass a reference to the a session in the call. Tables are accessible through generated serializable classes."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findById(session, companyId);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If no matching row is found, ",(0,s.jsx)(n.code,{children:"null"})," is returned. You can also search for rows using expressions with the ",(0,s.jsx)(n.code,{children:"where"})," parameter. The ",(0,s.jsx)(n.code,{children:"where"})," parameter is a typed expression builder. The builder's parameter, ",(0,s.jsx)(n.code,{children:"t"}),", contains a description of the table which gives access to the table's columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findSingleRow(\n session,\n where: (t) => t.name.equals('My Company'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"finding-multiple-rows",children:"Finding multiple rows"}),"\n",(0,s.jsxs)(n.p,{children:["To find multiple rows, use the same principle as for finding a single row. Returned will be a ",(0,s.jsx)(n.code,{children:"List"})," of ",(0,s.jsx)(n.code,{children:"TableRow"}),"s."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var companies = await Company.find(\n tCompany,\n where: (t) => t.id < 100,\n limit: 50,\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"updating-a-row",children:"Updating a row"}),"\n",(0,s.jsxs)(n.p,{children:["To update a row, use the ",(0,s.jsx)(n.code,{children:"update"})," method. The object that you update must have its ",(0,s.jsx)(n.code,{children:"id"})," set to a non ",(0,s.jsx)(n.code,{children:"null"})," value."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await session.db.findById(tCompany, companyId) as Company?;\nmyCompany.name = 'New name';\nawait session.db.update(myCompany);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"deleting-rows",children:"Deleting rows"}),"\n",(0,s.jsxs)(n.p,{children:["Deleting a single row works similarly to the ",(0,s.jsx)(n.code,{children:"update"})," method, but you can also delete rows using the where parameter."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// Delete a single row\nawait Company.deleteRow(session, myCompany);\n\n// Delete all rows where the company name ends with 'Ltd'\nawait Company.delete(\n where: (t) => t.name.like('%Ltd'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"creating-expressions",children:"Creating expressions"}),"\n",(0,s.jsxs)(n.p,{children:["To find or delete specific rows, most often, expressions are needed. Serverpod makes it easy to build expressions that are statically type-checked. Columns are referenced using the global table descriptor objects. The table descriptors, ",(0,s.jsx)(n.code,{children:"t"})," are passed to the expression builder function. The ",(0,s.jsx)(n.code,{children:">"}),", ",(0,s.jsx)(n.code,{children:">="}),", ",(0,s.jsx)(n.code,{children:"<"}),", ",(0,s.jsx)(n.code,{children:"<="}),", ",(0,s.jsx)(n.code,{children:"&"}),", and ",(0,s.jsx)(n.code,{children:"|"})," operators are overridden to make it easier to work with column values. When using the operators, it's a good practice to place them within a set of parentheses as the precedence rules are not always what would be expected. These are some examples of expressions."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// The name column of the Company table equals 'My company')\nt.name.equals('My company')\n\n// Companies founded at or after 2020\nt.foundedDate >= DateTime.utc(2020)\n\n// Companies with number of employees between 10 and 100\n(t.numEmployees > 10) & (t.numEmployees <= 100)\n\n// Companies that has the founded date set\nt.foundedDate.notEquals(null)\n"})}),"\n",(0,s.jsx)(n.h3,{id:"transactions",children:"Transactions"}),"\n",(0,s.jsx)(n.p,{children:"Docs coming."}),"\n",(0,s.jsx)(n.h3,{id:"executing-raw-queries",children:"Executing raw queries"}),"\n",(0,s.jsxs)(n.p,{children:["Sometimes more advanced tasks need to be performed on the database. For those occasions, it's possible to run raw SQL queries on the database. Use the ",(0,s.jsx)(n.code,{children:"query"})," method. A ",(0,s.jsx)(n.code,{children:"List>"})," will be returned with rows and columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var result = await session.db.query('SELECT * FROM mytable WHERE ...');\n"})})]})}function h(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},11151:(e,n,a)=>{a.d(n,{Z:()=>r,a:()=>o});var s=a(67294);const i={},t=s.createContext(i);function o(e){const n=s.useContext(t);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/efe5610c.73ada662.js b/docs/assets/js/efe5610c.73ada662.js new file mode 100644 index 000000000..794aada14 --- /dev/null +++ b/docs/assets/js/efe5610c.73ada662.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkserverpod_docs=self.webpackChunkserverpod_docs||[]).push([[5738],{47810:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>i,metadata:()=>r,toc:()=>l});var s=a(85893),t=a(11151);const i={},o="Database communication",r={id:"concepts/database-communication",title:"Database communication",description:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files.",source:"@site/versioned_docs/version-1.0.0/04-concepts/03-database-communication.md",sourceDirName:"04-concepts",slug:"/concepts/database-communication",permalink:"/1.0.0/concepts/database-communication",draft:!1,unlisted:!1,editUrl:"https://github.com/serverpod/serverpod_docs/tree/main/versioned_docs/version-1.0.0/04-concepts/03-database-communication.md",tags:[],version:"1.0.0",sidebarPosition:3,frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Serialization",permalink:"/1.0.0/concepts/serialization"},next:{title:"Caching",permalink:"/1.0.0/concepts/caching"}},d={},l=[{value:"Database mappings",id:"database-mappings",level:2},{value:"Field scopes",id:"field-scopes",level:3},{value:"Database indexes",id:"database-indexes",level:3},{value:"Parent/child relationships",id:"parentchild-relationships",level:3},{value:"Storing objects or references",id:"storing-objects-or-references",level:3},{value:"Making queries",id:"making-queries",level:2},{value:"Inserting a table row",id:"inserting-a-table-row",level:3},{value:"Finding a single row",id:"finding-a-single-row",level:3},{value:"Finding multiple rows",id:"finding-multiple-rows",level:3},{value:"Updating a row",id:"updating-a-row",level:3},{value:"Deleting rows",id:"deleting-rows",level:3},{value:"Creating expressions",id:"creating-expressions",level:3},{value:"Joining tables and nesting objects",id:"joining-tables-and-nesting-objects",level:3},{value:"Transactions",id:"transactions",level:3},{value:"Executing raw queries",id:"executing-raw-queries",level:3}];function c(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,t.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"database-communication",children:"Database communication"}),"\n",(0,s.jsx)(n.p,{children:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files."}),"\n",(0,s.jsx)(n.h2,{id:"database-mappings",children:"Database mappings"}),"\n",(0,s.jsxs)(n.p,{children:["It's possible to map serializable classes straight to tables in your database. To do this, add the ",(0,s.jsx)(n.code,{children:"table"})," key to your yaml file:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n"})}),"\n",(0,s.jsxs)(n.p,{children:["When running ",(0,s.jsx)(n.code,{children:"serverpod generate"}),", the database schema will be saved in the ",(0,s.jsx)(n.code,{children:"generated/tables.pgsql"})," file. You can use this to create the corresponding database tables."]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["When you add a ",(0,s.jsx)(n.code,{children:"table"})," to a serializable class, Serverpod will automatically add an ",(0,s.jsx)(n.code,{children:"id"})," field of type ",(0,s.jsx)(n.code,{children:"int?"})," to the class. You should not define this field yourself. The ",(0,s.jsx)(n.code,{children:"id"})," is set when you insert or select a row from the database. The ",(0,s.jsx)(n.code,{children:"id"})," field allows you to do updates and reference the rows from other objects and tables."]})}),"\n",(0,s.jsx)(n.h3,{id:"field-scopes",children:"Field scopes"}),"\n",(0,s.jsxs)(n.p,{children:["In some cases, you want to save a field to the database, but it should never be sent to the server. You can exclude it from the protocol by adding the ",(0,s.jsx)(n.code,{children:"database"})," scope to the type."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: UserData\nfields:\n name: String\n password: String?, database\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Likewise, if you only want a field to be accessible in the protocol but not stored in the server, you can add the ",(0,s.jsx)(n.code,{children:"api"})," flag. By default, a field is accessible to both the API and the database."]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["If you use the ",(0,s.jsx)(n.code,{children:"database"})," or ",(0,s.jsx)(n.code,{children:"api"})," options the field must be nullable."]})}),"\n",(0,s.jsx)(n.h3,{id:"database-indexes",children:"Database indexes"}),"\n",(0,s.jsx)(n.p,{children:"For performance reasons, you may want to add indexes to your database tables. You add these in the yaml-files defining the serializable objects."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n employees: List?, api\nindexes:\n company_name_idx:\n fields: name\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"fields"})," key holds a comma-separated list of column names. In addition, it's possible to add a type key (default is ",(0,s.jsx)(n.code,{children:"btree"}),"), and a ",(0,s.jsx)(n.code,{children:"unique"})," key (default is ",(0,s.jsx)(n.code,{children:"false"}),")."]}),"\n",(0,s.jsx)(n.h3,{id:"parentchild-relationships",children:"Parent/child relationships"}),"\n",(0,s.jsx)(n.p,{children:"With a field's parent property, you can define a relationship with a table's parent table. This relationship ensures that the parent id is always valid and that if you delete the referenced parent, the referencing row will automatically be deleted."}),"\n",(0,s.jsxs)(n.p,{children:["The employee's ",(0,s.jsx)(n.code,{children:"parent"})," is set to the ",(0,s.jsx)(n.code,{children:"company"})," table in the example below. If you remove the company, all employees of the company will automatically be removed. When you insert the employee into the database, you must specify a valid ",(0,s.jsx)(n.code,{children:"companyId"})," that corresponds to the id field in the ",(0,s.jsx)(n.code,{children:"company"})," table."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Employee\ntable: employee\nfields:\n companyId: int, parent=company\n name: String\n birthday: DateTime\n"})}),"\n",(0,s.jsx)(n.h3,{id:"storing-objects-or-references",children:"Storing objects or references"}),"\n",(0,s.jsxs)(n.p,{children:["If you reference another serializable object in your yaml file, it will be stored as a JSON entry in the database. This creates a copy of that object. In many cases, this is not desirable. Instead, you may want to reference that object by an id from another table. See the section on ",(0,s.jsx)(n.a,{href:"#joining-tables-and-nesting-objects",children:"joining tables and nesting objects"})," below for more information."]}),"\n",(0,s.jsx)(n.p,{children:"In the example below, a list of employees is stored as a JSON structure for each company in the database. A better solution would be to create a database row for each employee and reference the company. However, there are cases where it is convenient to store whole JSON structures in each row."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n employees: List # Stored as JSON structure\n"})}),"\n",(0,s.jsx)(n.h2,{id:"making-queries",children:"Making queries"}),"\n",(0,s.jsxs)(n.p,{children:["For the communication to work, you need to have generated serializable classes with the ",(0,s.jsx)(n.code,{children:"table"})," key set, and the corresponding table must have been created in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"inserting-a-table-row",children:"Inserting a table row"}),"\n",(0,s.jsxs)(n.p,{children:["Insert a new row in the database by calling the insert method of the ",(0,s.jsx)(n.code,{children:"db"})," field in your ",(0,s.jsx)(n.code,{children:"Session"})," object."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myRow = Company(name: 'Serverpod corp.', employees: []);\nawait Company.insert(session, myRow);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["After the object has been inserted, it's ",(0,s.jsx)(n.code,{children:"id"})," field is set from its row in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"finding-a-single-row",children:"Finding a single row"}),"\n",(0,s.jsxs)(n.p,{children:["You can find a single row, either by its ",(0,s.jsx)(n.code,{children:"id"})," or using an expression. You need to pass a reference to the a session in the call. Tables are accessible through generated serializable classes."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findById(session, companyId);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If no matching row is found, ",(0,s.jsx)(n.code,{children:"null"})," is returned. You can also search for rows using expressions with the ",(0,s.jsx)(n.code,{children:"where"})," parameter. The ",(0,s.jsx)(n.code,{children:"where"})," parameter is a typed expression builder. The builder's parameter, ",(0,s.jsx)(n.code,{children:"t"}),", contains a description of the table which gives access to the table's columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findSingleRow(\n session,\n where: (t) => t.name.equals('My Company'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"finding-multiple-rows",children:"Finding multiple rows"}),"\n",(0,s.jsxs)(n.p,{children:["To find multiple rows, use the same principle as for finding a single row. Returned will be a ",(0,s.jsx)(n.code,{children:"List"})," of ",(0,s.jsx)(n.code,{children:"TableRow"}),"s."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var companies = await Company.find(\n tCompany,\n where: (t) => t.id < 100,\n limit: 50,\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"updating-a-row",children:"Updating a row"}),"\n",(0,s.jsxs)(n.p,{children:["To update a row, use the ",(0,s.jsx)(n.code,{children:"update"})," method. The object that you update must have its ",(0,s.jsx)(n.code,{children:"id"})," set to a non-",(0,s.jsx)(n.code,{children:"null"})," value."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await session.db.findById(tCompany, companyId) as Company?;\nmyCompany.name = 'New name';\nawait session.db.update(myCompany);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"deleting-rows",children:"Deleting rows"}),"\n",(0,s.jsxs)(n.p,{children:["Deleting a single row works similarly to the ",(0,s.jsx)(n.code,{children:"update"})," method, but you can also delete rows using the where parameter."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// Delete a single row\nawait Company.deleteRow(session, myCompany);\n\n// Delete all rows where the company name ends with 'Ltd'\nawait Company.delete(\n where: (t) => t.name.like('%Ltd'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"creating-expressions",children:"Creating expressions"}),"\n",(0,s.jsxs)(n.p,{children:["To find or delete specific rows, most often, expressions are needed. Serverpod makes it easy to build expressions that are statically type-checked. Columns are referenced using the global table descriptor objects. The table descriptors, ",(0,s.jsx)(n.code,{children:"t"})," are passed to the expression builder function. The ",(0,s.jsx)(n.code,{children:">"}),", ",(0,s.jsx)(n.code,{children:">="}),", ",(0,s.jsx)(n.code,{children:"<"}),", ",(0,s.jsx)(n.code,{children:"<="}),", ",(0,s.jsx)(n.code,{children:"&"}),", and ",(0,s.jsx)(n.code,{children:"|"})," operators are overridden to make it easier to work with column values. When using the operators, it's a good practice to place them within a set of parentheses as the precedence rules are not always what would be expected. These are some examples of expressions."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// The name column of the Company table equals 'My company')\nt.name.equals('My company')\n\n// Companies founded at or after 2020\nt.foundedDate >= DateTime.utc(2020)\n\n// Companies with number of employees between 10 and 100\n(t.numEmployees > 10) & (t.numEmployees <= 100)\n\n// Companies that has the founded date set\nt.foundedDate.notEquals(null)\n"})}),"\n",(0,s.jsx)(n.h3,{id:"joining-tables-and-nesting-objects",children:"Joining tables and nesting objects"}),"\n",(0,s.jsx)(n.p,{children:"Serverpod does not yet support joins automatically. However, you can easily create nested objects by performing two or more queries."}),"\n",(0,s.jsxs)(n.p,{children:["For instance, if you have a ",(0,s.jsx)(n.code,{children:"Company"})," object with a list of ",(0,s.jsx)(n.code,{children:"Employee"})," it can be declared like this:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"# company.yaml\nclass: Company\ntable: company\nfields:\n name: String\n employees: List?, api\n\n# employee.yaml\nclass: Employee\ntable: employee\nfields:\n companyId: int\n name: String\n birthday: DateTime\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This prevents the list of ",(0,s.jsx)(n.code,{children:"Employee"})," to be automatically fetched or stored in the database. After you fetch a ",(0,s.jsx)(n.code,{children:"Company"})," object from the database, format it by fetching the list of ",(0,s.jsx)(n.code,{children:"Employees"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var company = await Company.findById(session, id);\n\nvar employees = await Employee.find(\n session,\n where: (t) => t.companyId.equals(company.id),\n);\n\ncompany.employees = employees;\n"})}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsx)(n.p,{children:"Future versions of Serverpod will add support for automatic joins and database views."})}),"\n",(0,s.jsx)(n.h3,{id:"transactions",children:"Transactions"}),"\n",(0,s.jsx)(n.p,{children:"The essential point of a database transaction is that it bundles multiple steps into a single, all-or-nothing operation. The intermediate states between the steps are not visible to other concurrent transactions, and if some failure occurs that prevents the transaction from completing, then none of the steps affect the database at all."}),"\n",(0,s.jsxs)(n.p,{children:["Serverpod handles database transactions through the ",(0,s.jsx)(n.code,{children:"session.db.transaction"})," method. The transaction takes a method that performs any database queries or other operations and optionally returns a value."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var result = await session.db.transaction((transaction) async {\n // Do some database queries here.\n\n // Optionally return a value.\n return true;\n});\n"})}),"\n",(0,s.jsx)(n.h3,{id:"executing-raw-queries",children:"Executing raw queries"}),"\n",(0,s.jsxs)(n.p,{children:["Sometimes more advanced tasks need to be performed on the database. For those occasions, it's possible to run raw SQL queries on the database. Use the ",(0,s.jsx)(n.code,{children:"query"})," method. A ",(0,s.jsx)(n.code,{children:"List>"})," will be returned with rows and columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var result = await session.db.query('SELECT * FROM mytable WHERE ...');\n"})})]})}function h(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},11151:(e,n,a)=>{a.d(n,{Z:()=>r,a:()=>o});var s=a(67294);const t={},i=s.createContext(t);function o(e){const n=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),s.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/fc8b5a5d.8155e1ca.js b/docs/assets/js/fc8b5a5d.8155e1ca.js new file mode 100644 index 000000000..a1e6729d5 --- /dev/null +++ b/docs/assets/js/fc8b5a5d.8155e1ca.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkserverpod_docs=self.webpackChunkserverpod_docs||[]).push([[4135],{26347:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>t,metadata:()=>r,toc:()=>l});var s=a(85893),i=a(11151);const t={},o="Database communication",r={id:"concepts/database-communication",title:"Database communication",description:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files.",source:"@site/versioned_docs/version-0.9.8/03-concepts/03-database-communication.md",sourceDirName:"03-concepts",slug:"/concepts/database-communication",permalink:"/0.9.8/concepts/database-communication",draft:!1,unlisted:!1,editUrl:"https://github.com/serverpod/serverpod_docs/tree/main/versioned_docs/version-0.9.8/03-concepts/03-database-communication.md",tags:[],version:"0.9.8",sidebarPosition:3,frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Serialization",permalink:"/0.9.8/concepts/serialization"},next:{title:"Caching",permalink:"/0.9.8/concepts/caching"}},d={},l=[{value:"Database mappings",id:"database-mappings",level:2},{value:"Database indexes",id:"database-indexes",level:3},{value:"Making queries",id:"making-queries",level:2},{value:"Inserting a table row",id:"inserting-a-table-row",level:3},{value:"Finding a single row",id:"finding-a-single-row",level:3},{value:"Finding multiple rows",id:"finding-multiple-rows",level:3},{value:"Updating a row",id:"updating-a-row",level:3},{value:"Deleting rows",id:"deleting-rows",level:3},{value:"Creating expressions",id:"creating-expressions",level:3},{value:"Transactions",id:"transactions",level:3},{value:"Executing raw queries",id:"executing-raw-queries",level:3}];function c(e){const n={code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,i.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"database-communication",children:"Database communication"}),"\n",(0,s.jsx)(n.p,{children:"Serverpod makes it easy to communicate with your database using strictly typed objects without a single SQL line. But, if you need to do more complex tasks, you can always do direct SQL calls. You define your database mappings right in the protocol yaml files."}),"\n",(0,s.jsx)(n.h2,{id:"database-mappings",children:"Database mappings"}),"\n",(0,s.jsxs)(n.p,{children:["It's possible to map serializable classes straight to tables in your database. To do this, add the ",(0,s.jsx)(n.code,{children:"table"})," key to your yaml file:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n employees: List\n"})}),"\n",(0,s.jsxs)(n.p,{children:["When running ",(0,s.jsx)(n.code,{children:"serverpod generate"}),", the database schema will be saved in the ",(0,s.jsx)(n.code,{children:"generated/tables.pgsql"})," file. You can use this to create the corresponding database tables."]}),"\n",(0,s.jsxs)(n.p,{children:["In some cases, you want to save a field to the database, but it should never be sent to the server. You can exclude it from the protocol by adding the ",(0,s.jsx)(n.code,{children:"database"})," flag to the type."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: UserData\nfields:\n name: String\n password: String, database\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Likewise, if you only want a field to be accessible in the protocol but not stored in the server, you can add the ",(0,s.jsx)(n.code,{children:"api"})," flag. By default, a field is accessible to both the API and the database."]}),"\n",(0,s.jsx)(n.h3,{id:"database-indexes",children:"Database indexes"}),"\n",(0,s.jsx)(n.p,{children:"For performance reasons, you may want to add indexes to your database tables. You add these in the yaml-files defining the serializable objects."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"class: Company\ntable: company\nfields:\n name: String\n foundedDate: DateTime?\n employees: List\nindexes:\n company_name_idx:\n fields: name\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"fields"})," key holds a comma-separated list of column names. In addition, it's possible to add a type key (default is ",(0,s.jsx)(n.code,{children:"btree"}),"), and a ",(0,s.jsx)(n.code,{children:"unique"})," key (default is ",(0,s.jsx)(n.code,{children:"false"}),")."]}),"\n",(0,s.jsx)(n.h2,{id:"making-queries",children:"Making queries"}),"\n",(0,s.jsxs)(n.p,{children:["For the communication to work, you need to have generated serializable classes with the ",(0,s.jsx)(n.code,{children:"table"})," key set, and the corresponding table must have been created in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"inserting-a-table-row",children:"Inserting a table row"}),"\n",(0,s.jsxs)(n.p,{children:["Insert a new row in the database by calling the insert method of the ",(0,s.jsx)(n.code,{children:"db"})," field in your ",(0,s.jsx)(n.code,{children:"Session"})," object."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myRow = Company(name: 'Serverpod corp.', employees: []);\nawait Company.insert(session, myRow);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["After the object has been inserted, it's ",(0,s.jsx)(n.code,{children:"id"})," field is set from its row in the database."]}),"\n",(0,s.jsx)(n.h3,{id:"finding-a-single-row",children:"Finding a single row"}),"\n",(0,s.jsxs)(n.p,{children:["You can find a single row, either by its ",(0,s.jsx)(n.code,{children:"id"})," or using an expression. You need to pass a reference to the a session in the call. Tables are accessible through generated serializable classes."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findById(session, companyId);\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If no matching row is found, ",(0,s.jsx)(n.code,{children:"null"})," is returned. You can also search for rows using expressions with the ",(0,s.jsx)(n.code,{children:"where"})," parameter. The ",(0,s.jsx)(n.code,{children:"where"})," parameter is a typed expression builder. The builder's parameter, ",(0,s.jsx)(n.code,{children:"t"}),", contains a description of the table which gives access to the table's columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await Company.findSingleRow(\n session,\n where: (t) => t.name.equals('My Company'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"finding-multiple-rows",children:"Finding multiple rows"}),"\n",(0,s.jsxs)(n.p,{children:["To find multiple rows, use the same principle as for finding a single row. Returned will be a ",(0,s.jsx)(n.code,{children:"List"})," of ",(0,s.jsx)(n.code,{children:"TableRow"}),"s."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var companies = await Company.find(\n tCompany,\n where: (t) => t.id < 100,\n limit: 50,\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"updating-a-row",children:"Updating a row"}),"\n",(0,s.jsxs)(n.p,{children:["To update a row, use the ",(0,s.jsx)(n.code,{children:"update"})," method. The object that you update must have its ",(0,s.jsx)(n.code,{children:"id"})," set to a non ",(0,s.jsx)(n.code,{children:"null"})," value."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var myCompany = await session.db.findById(tCompany, companyId) as Company?;\nmyCompany.name = 'New name';\nawait session.db.update(myCompany);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"deleting-rows",children:"Deleting rows"}),"\n",(0,s.jsxs)(n.p,{children:["Deleting a single row works similarly to the ",(0,s.jsx)(n.code,{children:"update"})," method, but you can also delete rows using the where parameter."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// Delete a single row\nawait Company.deleteRow(session, myCompany);\n\n// Delete all rows where the company name ends with 'Ltd'\nawait Company.delete(\n where: (t) => t.name.like('%Ltd'),\n);\n"})}),"\n",(0,s.jsx)(n.h3,{id:"creating-expressions",children:"Creating expressions"}),"\n",(0,s.jsxs)(n.p,{children:["To find or delete specific rows, most often, expressions are needed. Serverpod makes it easy to build expressions that are statically type-checked. Columns are referenced using the global table descriptor objects. The table descriptors, ",(0,s.jsx)(n.code,{children:"t"})," are passed to the expression builder function. The ",(0,s.jsx)(n.code,{children:">"}),", ",(0,s.jsx)(n.code,{children:">="}),", ",(0,s.jsx)(n.code,{children:"<"}),", ",(0,s.jsx)(n.code,{children:"<="}),", ",(0,s.jsx)(n.code,{children:"&"}),", and ",(0,s.jsx)(n.code,{children:"|"})," operators are overridden to make it easier to work with column values. When using the operators, it's a good practice to place them within a set of parentheses as the precedence rules are not always what would be expected. These are some examples of expressions."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"// The name column of the Company table equals 'My company')\nt.name.equals('My company')\n\n// Companies founded at or after 2020\nt.foundedDate >= DateTime.utc(2020)\n\n// Companies with number of employees between 10 and 100\n(t.numEmployees > 10) & (t.numEmployees <= 100)\n\n// Companies that has the founded date set\nt.foundedDate.notEquals(null)\n"})}),"\n",(0,s.jsx)(n.h3,{id:"transactions",children:"Transactions"}),"\n",(0,s.jsx)(n.p,{children:"Docs coming."}),"\n",(0,s.jsx)(n.h3,{id:"executing-raw-queries",children:"Executing raw queries"}),"\n",(0,s.jsxs)(n.p,{children:["Sometimes more advanced tasks need to be performed on the database. For those occasions, it's possible to run raw SQL queries on the database. Use the ",(0,s.jsx)(n.code,{children:"query"})," method. A ",(0,s.jsx)(n.code,{children:"List>"})," will be returned with rows and columns."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-dart",children:"var result = await session.db.query('SELECT * FROM mytable WHERE ...');\n"})})]})}function h(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},11151:(e,n,a)=>{a.d(n,{Z:()=>r,a:()=>o});var s=a(67294);const i={},t=s.createContext(i);function o(e){const n=s.useContext(t);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/runtime~main.1ae0fba7.js b/docs/assets/js/runtime~main.1ae0fba7.js new file mode 100644 index 000000000..97c9c3c55 --- /dev/null +++ b/docs/assets/js/runtime~main.1ae0fba7.js @@ -0,0 +1 @@ +(()=>{"use strict";var e,d,a,c,f,b={},r={};function t(e){var d=r[e];if(void 0!==d)return d.exports;var a=r[e]={exports:{}};return b[e].call(a.exports,a,a.exports,t),a.exports}t.m=b,e=[],t.O=(d,a,c,f)=>{if(!a){var b=1/0;for(i=0;i=f)&&Object.keys(t.O).every((e=>t.O[e](a[o])))?a.splice(o--,1):(r=!1,f0&&e[i-1][2]>f;i--)e[i]=e[i-1];e[i]=[a,c,f]},t.n=e=>{var d=e&&e.__esModule?()=>e.default:()=>e;return t.d(d,{a:d}),d},a=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,t.t=function(e,c){if(1&c&&(e=this(e)),8&c)return e;if("object"==typeof e&&e){if(4&c&&e.__esModule)return e;if(16&c&&"function"==typeof e.then)return e}var f=Object.create(null);t.r(f);var b={};d=d||[null,a({}),a([]),a(a)];for(var r=2&c&&e;"object"==typeof r&&!~d.indexOf(r);r=a(r))Object.getOwnPropertyNames(r).forEach((d=>b[d]=()=>e[d]));return b.default=()=>e,t.d(f,b),f},t.d=(e,d)=>{for(var a in d)t.o(d,a)&&!t.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:d[a]})},t.f={},t.e=e=>Promise.all(Object.keys(t.f).reduce(((d,a)=>(t.f[a](e,d),d)),[])),t.u=e=>"assets/js/"+({45:"984d6493",53:"935f2afb",58:"313c9eb1",99:"b1394c86",102:"7d63aba8",114:"c10a0985",131:"986f0f98",187:"a2a1c245",281:"566f49fb",282:"072aa2d8",334:"f28f059c",372:"2d11a680",397:"b809d820",399:"511f9951",420:"da071cb8",550:"6ba85e75",578:"4f0519c7",599:"83c6f999",669:"bd568e77",770:"94b2bc9a",832:"719163ad",845:"eecc43ff",847:"1b6591f7",860:"1a84c7fd",870:"85d514f3",887:"71ba2dc1",967:"51ddac88",969:"45939ed5",979:"8b75b47c",1017:"0d76317c",1027:"f6adf820",1086:"17dc776d",1103:"a1154d73",1129:"a4adf53f",1131:"bd118f84",1162:"dc4059b2",1251:"1323771c",1308:"fc6f07d2",1315:"6feb7661",1332:"6e29a506",1362:"8e0e42ad",1370:"2bbc2deb",1372:"8552f549",1400:"5143312c",1414:"9c9052d1",1419:"9d779d8b",1444:"dec2bd4a",1453:"c3373259",1458:"e3d58533",1481:"3d277f18",1483:"9f8e6d57",1485:"da19ecb4",1499:"87ab7385",1567:"4f83adf9",1569:"805a59dc",1577:"897331c0",1582:"4519f039",1616:"25c6d77a",1651:"ea237062",1656:"1d39c85d",1681:"44a83f6a",1697:"9639af7c",1703:"9906d6d9",1733:"61ff6850",1754:"61aeda71",1816:"3817c387",1826:"7de3e81f",1827:"669968f9",1834:"419cd6b8",1843:"ce4dbf6d",1876:"3aa0ab0a",1898:"801276a1",1938:"afb7a97b",1978:"812cd700",1982:"ecb3c634",1996:"be37811c",2001:"e7977816",2020:"444a6d4e",2029:"f2c30f0a",2040:"54cab4d4",2058:"93dcedec",2068:"819b642a",2105:"cdc118a8",2128:"4aa94ec1",2151:"7570de64",2154:"2b67eda4",2165:"956829f8",2181:"c8139b75",2265:"0893faed",2284:"b79774cd",2330:"6d2a4d3f",2372:"33c1d41a",2394:"9b4ab8cd",2400:"15f7c149",2428:"fe76eed8",2475:"869ae8a7",2500:"ae0eacdd",2544:"5f6b1733",2559:"4a197f0b",2631:"071f33a8",2696:"1921e4ca",2733:"1457ddcd",2743:"c3094240",2768:"676f1bdb",2784:"3e87058f",2793:"2955939d",2890:"ad61550a",2917:"44463284",2924:"95a5d2b2",2935:"467a9f36",2981:"526e379a",2989:"6a2e0576",3012:"710ac1c1",3029:"b9ec56c8",3036:"4cbee5e0",3057:"4e689a0b",3083:"2590f46b",3095:"d2aa311d",3109:"d8d6d57b",3172:"7479a3f8",3174:"4a49065b",3238:"dc8c27bd",3243:"997397e3",3283:"ef4456b5",3310:"30bd0f5b",3314:"d2f6d210",3357:"49849746",3377:"7f0714d1",3380:"13798859",3414:"ec91ff36",3446:"96e80ddd",3457:"068743c8",3525:"227d1fc4",3537:"c342bcae",3624:"a6311318",3642:"d84f251f",3768:"5d707891",3770:"6da448d1",3786:"4867e743",3866:"0c695afe",3889:"b0f19176",3905:"f7ae65ac",3929:"4ab30eec",3949:"82ea7079",3954:"2db99065",3962:"af754a1f",3978:"cce58fe7",3983:"2db5c390",3988:"d4067975",4013:"9e0c2c37",4039:"24557dbc",4055:"272aa200",4056:"27b43779",4081:"5c6f6ba9",4086:"b5dcbe95",4102:"98f4e1ec",4135:"fc8b5a5d",4161:"da698f4c",4169:"e4a796aa",4201:"dd31e7e9",4235:"abd13aa2",4302:"999788b8",4325:"9fbfaf6d",4331:"8e7261c9",4351:"bdc5a52e",4368:"a94703ab",4378:"daec0d60",4384:"bafd283f",4426:"8b6141b3",4453:"afa99621",4477:"070c8c93",4531:"50f02128",4571:"51e50f95",4613:"dd059c51",4641:"a32c313f",4650:"c090764b",4652:"ebd05845",4665:"327b0a57",4786:"52f87500",4799:"d6dc384d",4801:"378935ce",4807:"099a3596",4842:"813cfb2f",4939:"d8020439",4955:"646cbece",4969:"fac0eceb",5002:"ee65edec",5069:"9107c65f",5080:"a6397568",5085:"59c6c1db",5109:"3c9432f0",5151:"e2d6ba1f",5172:"b26210db",5182:"945c4294",5183:"21b7a589",5190:"6458864c",5217:"3cc71396",5227:"522ca66b",5239:"89b55a09",5261:"18910d94",5265:"62dc82db",5267:"9ed3f7e3",5285:"45dd886d",5293:"5839343c",5321:"c0650537",5329:"62e81aa6",5367:"9e09f891",5413:"06393fc1",5478:"d58f1ee2",5482:"90239e6e",5515:"726a6c22",5532:"26398b18",5630:"79d28454",5664:"504d78e0",5666:"2ace8790",5688:"2e1ee4ed",5710:"cd461806",5724:"704545ab",5730:"f5fed352",5738:"efe5610c",5754:"05552792",5767:"2d16d24d",5801:"a81cb65f",5805:"42abcd4d",5836:"92f483f2",5838:"4a209014",5873:"564db590",5900:"616631fd",5935:"03b3cfd2",5955:"e84b4e80",5963:"69cda322",5969:"5c1eff22",6031:"4aec9039",6055:"cb867d98",6086:"5887a6b3",6092:"b28bd8b1",6099:"e8f4756d",6107:"9f1829f0",6183:"adce8179",6199:"1dda0a07",6223:"bd6f2233",6265:"3fe65583",6279:"055b225f",6288:"a4c89d62",6297:"45926b62",6302:"1a30ce1a",6401:"0a5c01b2",6490:"62037464",6495:"e4eafb12",6506:"03b2528f",6508:"d95655b8",6527:"07e708e9",6536:"65c67349",6553:"4bfca71d",6570:"79840965",6582:"3113b236",6611:"33f4c6a9",6640:"3f80bb14",6714:"92466816",6719:"5bc657fa",6738:"5112ebe3",6740:"53e9dd7a",6777:"d802bb56",6789:"9f85e773",6837:"0ae57e5e",6845:"141135bb",6863:"c7156cf2",6864:"08aab21d",6895:"5f5da5ff",6971:"c377a04b",6974:"954e932f",7001:"82444e58",7051:"c2b45dbb",7065:"8dfd8953",7071:"8a5390a0",7112:"10e37c04",7123:"fd4b36bb",7129:"23975af2",7136:"098f2604",7139:"926056c1",7250:"8e374c01",7251:"b32c213b",7262:"9a594c98",7265:"9d36f238",7273:"cdd4a9c6",7311:"8bed5a26",7395:"7af31c45",7425:"44145933",7427:"e3443ce0",7485:"b7ea99f7",7486:"67e77328",7489:"3e4a4cb2",7492:"81e4ed6a",7503:"16116660",7512:"07006f9e",7539:"616bfcf6",7566:"063d75bd",7613:"2e18ba50",7670:"49145cdf",7673:"638e38ae",7677:"c75d145e",7708:"b744c57f",7718:"ed64c12e",7800:"59df87e8",7819:"3141060a",7847:"c6e65aef",7858:"7ca2e59a",7918:"17896441",7927:"68401255",7932:"5af30237",7955:"b8787c81",7980:"db7d4591",8018:"65399378",8044:"e64edb60",8047:"3d150a24",8076:"169f3d24",8110:"26a0dea9",8143:"0773e78b",8172:"4934de22",8202:"9644aa4e",8213:"98c94590",8232:"2596363d",8278:"fe3f3783",8287:"d4fc3158",8299:"7974de6c",8317:"d26a73b8",8326:"e15bcb33",8341:"bd1cffff",8344:"e66f2658",8349:"eac16e1d",8369:"be895d61",8378:"38e32826",8413:"ac6e050c",8438:"aee9697b",8456:"f584139f",8457:"ac3101e9",8486:"a0aa5253",8492:"eb4c176e",8518:"a7bd4aaa",8524:"9d7352c0",8539:"5d8361b1",8548:"96331245",8560:"6a734661",8571:"056b386b",8573:"1d3ec39f",8618:"00d14154",8658:"2c2832e4",8675:"28967b3e",8686:"02e41de2",8746:"8af032d3",8752:"d44e0d1c",8757:"73ca4188",8778:"5e7d099e",8818:"d636c09f",8849:"5e253f2f",8853:"c05c66f0",8856:"afde3230",8864:"4eee9c87",8919:"8a14b359",8961:"ed942358",9006:"0f4a5c74",9048:"640696ee",9055:"10ad1fa6",9073:"a64b2578",9120:"e0bec135",9231:"31b73615",9241:"092bf57d",9261:"d86e4bec",9297:"f9bde383",9298:"6aee17c2",9434:"8ee9837e",9450:"3874f1bf",9523:"05fa9a60",9533:"8baf194b",9570:"f149b10e",9610:"f4f85478",9627:"f3467f26",9639:"4c781063",9652:"bb9c591b",9654:"5589c54d",9661:"5e95c892",9667:"cbf3c4ec",9670:"86a8bb6c",9705:"a7edc2bd",9726:"10ea0b82",9735:"b1218054",9773:"12407b36",9783:"4b6eee9a",9792:"7c4a294c",9835:"4ac2e930",9953:"2020ed93"}[e]||e)+"."+{45:"c54b64d6",53:"ff1143a6",58:"d89ace65",99:"6a2d6998",102:"1c17e5b1",114:"0c4ea37c",131:"55708207",187:"42fe0537",281:"af1ae895",282:"f7c0f822",334:"4c3b9833",372:"230bf69c",397:"54385e57",399:"bae60e3b",420:"d9ed7f78",550:"9d6fb543",578:"4d633456",599:"77b90007",669:"c3580291",770:"4922872a",832:"193c9e25",845:"a7c864af",847:"bde924af",860:"38706e3a",870:"c87ba2ef",887:"f51ccc1a",967:"e2c345f0",969:"9c52f9ab",979:"c1de2063",1017:"b66f5e13",1027:"f7f0795d",1086:"a3f719ee",1103:"c09ce126",1129:"78038a9d",1131:"ab9fe841",1162:"6667aebc",1251:"787da051",1308:"e2e6925a",1315:"1483bd71",1332:"217033db",1362:"d31998cd",1370:"3f4afda9",1372:"8aee3440",1400:"377a145f",1414:"a0350e3a",1419:"19b8929d",1444:"d728e633",1453:"749459a2",1458:"3afb2ac0",1481:"3343378a",1483:"85dd220e",1485:"1872039d",1499:"4956c5c3",1567:"50e4fdd2",1569:"4a8ac4a6",1577:"370ebae2",1582:"b3fa3a9d",1616:"85c668b2",1651:"fcf9ba2a",1656:"304e016d",1681:"c78ff86d",1697:"da290aeb",1703:"44f77352",1733:"e41fb7e5",1754:"6283ac47",1772:"01952d7f",1816:"dfa36167",1826:"bb65e083",1827:"87fa8eaf",1834:"43d07b6d",1843:"ba8ab343",1876:"4613dd75",1898:"041ddb38",1938:"ae6ae937",1978:"e42b66eb",1982:"746e5951",1996:"3c8f0e12",2001:"ead0e063",2020:"30dadc3e",2029:"e69a3948",2040:"bd5e4216",2058:"8a8990a5",2068:"006ffbde",2105:"873f2e59",2128:"f516246e",2151:"be6a0f20",2154:"5647de9d",2165:"64797f5a",2181:"37af1b0e",2265:"c36d4f81",2284:"86948f6d",2330:"f025d616",2372:"61bb1689",2394:"c024db12",2400:"feac5b56",2428:"ff3954a9",2475:"9760a622",2500:"1e360109",2544:"5373e235",2559:"997922fe",2631:"93ef3132",2696:"12f764d0",2733:"f456f2f5",2743:"ac06da09",2768:"bc82fe13",2784:"b4d7a119",2793:"edaf9023",2890:"24f987c6",2917:"06852bb5",2924:"b090940e",2935:"81f9e7b4",2981:"6d448690",2989:"85d60160",3012:"b8ba5e6c",3029:"42068d6e",3036:"1b43d381",3057:"8f32e8a2",3083:"3d8e21e6",3095:"e7b9482c",3109:"731a7f6c",3172:"e776ece7",3174:"fb1114c0",3238:"dc1f576e",3243:"d9b61b81",3283:"d6afbb0a",3310:"c886f148",3314:"9ec183be",3357:"75dabc99",3377:"5cd42774",3380:"704dfbfe",3414:"a7cf5a79",3446:"937cb941",3457:"055a7f2a",3525:"9bec2fd9",3537:"149674a7",3624:"ae0e4c0a",3642:"c4122d0d",3768:"489f4310",3770:"fff87b90",3786:"c2e541db",3866:"9727968b",3889:"8e409948",3905:"8e67668e",3929:"f83db984",3949:"f22912aa",3954:"eaa22abc",3962:"dbe57387",3978:"718dbe81",3983:"3046099d",3988:"a92167ee",4013:"e2de6367",4039:"543c1f00",4055:"c1899d2a",4056:"2af60df2",4081:"cd1980fd",4086:"dae878b5",4102:"754347e6",4135:"8155e1ca",4161:"e740c3d5",4169:"b0db8952",4201:"0399337f",4235:"c586f2ed",4302:"01525b26",4325:"ebb1785b",4331:"6ceaaa70",4351:"f23facd2",4368:"dff6e541",4378:"c513dd81",4384:"b0805a9b",4426:"560123aa",4453:"12fa8609",4477:"0a776bbd",4531:"541f8c6a",4571:"46619d04",4613:"a8efbb4d",4641:"98d78771",4650:"7353206f",4652:"56162133",4665:"8dbd41d3",4685:"beef0944",4786:"e94dbb4d",4799:"98ee6b33",4801:"dc5f0917",4807:"0bc222da",4842:"d700fd99",4939:"2d9dcfca",4955:"460626b9",4969:"ca4b19a5",5002:"b8f165c3",5069:"f4e41127",5080:"6689c9bf",5085:"f253cde2",5109:"6ed8240d",5151:"197e48f7",5172:"064cdaef",5182:"c323acc5",5183:"99e4c592",5190:"4f8db539",5217:"2911c07c",5227:"f0b9524b",5239:"6882fa8f",5261:"3ddebced",5265:"d8b485bf",5267:"93487111",5285:"0b9c0d74",5293:"e8cd6002",5321:"d3664bb2",5329:"966140c0",5367:"b76f3ef6",5413:"e4527c12",5478:"262d2fb2",5482:"6a44426e",5515:"fe945ea1",5532:"cebf9440",5630:"5cd3f743",5664:"8f8f19b3",5666:"ce449cb5",5688:"25bbed3a",5710:"6d70d6d1",5724:"c94cb47d",5730:"08d3bc06",5738:"73ada662",5754:"303186d9",5767:"e154d86c",5801:"b38076ff",5805:"53aba75e",5836:"5856e918",5838:"cebb9ea9",5873:"4fbd2ed1",5900:"0636d6ad",5935:"04020a32",5955:"ad223fc0",5963:"5c54719b",5969:"49486dcf",6031:"cadd7b19",6055:"f0fa2fea",6086:"0f061d88",6092:"d33b6b35",6099:"0e0c2707",6107:"66e73b2c",6183:"eb7fc255",6199:"fe4410d8",6223:"0a001c13",6265:"51332d25",6279:"7a3b2cec",6288:"2465dab0",6297:"6108586e",6302:"9ed912ac",6401:"9521ffe5",6490:"19d8f177",6495:"89edcc0e",6506:"0b416d39",6508:"f7d1e636",6527:"609f8145",6536:"c6372736",6553:"194c28d3",6570:"e394c678",6582:"3661920f",6611:"8cdf2270",6640:"444a798d",6714:"c9b32a43",6719:"9e88c14c",6738:"fc90b218",6740:"4f36427c",6777:"37b6b447",6789:"183f8ad7",6837:"3d3ccb71",6845:"cbfe9736",6863:"928fee2d",6864:"7cbda3a4",6895:"8cbc8c9e",6971:"73a4560a",6974:"74faaa9e",7001:"719e1ce4",7051:"8031deb4",7065:"b1a2272b",7071:"d3e90e55",7112:"f13123ad",7123:"3ef91cf3",7129:"22db06a7",7136:"d0594551",7139:"8955b52b",7250:"7c48ade1",7251:"e9398645",7262:"35dd374e",7265:"a86b3249",7273:"b21514d1",7311:"d09612ab",7395:"9df7e1e0",7425:"9e8f1d22",7427:"5d1e4720",7485:"e02d32f8",7486:"3549e7b3",7489:"2cdbbca1",7492:"d657d713",7503:"17ae88e5",7512:"d52a8537",7539:"29514747",7566:"3cfb01c6",7613:"d67b2dd2",7670:"c09c3c18",7673:"b24dcfbe",7677:"43598d7b",7708:"dfacc186",7718:"0cf2c286",7800:"470f25e4",7819:"590ce699",7847:"cb4b1fd3",7858:"a36b4059",7918:"d5edfc9d",7927:"7be27921",7932:"9510ae52",7955:"19000061",7980:"7e864817",8018:"bba26f76",8044:"80155196",8047:"30350cec",8076:"487d22fe",8110:"33dd7dbf",8143:"4aee0994",8172:"20d8130b",8202:"7af08790",8213:"2a56ce4c",8232:"ebdfdca5",8278:"3dcf1976",8287:"b796bd72",8299:"3e4308c9",8317:"a3fdd3d1",8326:"f7b1837e",8341:"70598be9",8344:"229b1fbd",8349:"c90ba1a8",8369:"27ad13f1",8378:"44e9afa2",8413:"c038c348",8438:"e517f740",8456:"0cc743de",8457:"4d9b6209",8486:"c9141254",8492:"77b55e1c",8518:"b47ce817",8524:"c2020712",8539:"b1e0c316",8548:"0aac657c",8560:"725dbabc",8571:"3eb1996f",8573:"5c64e67c",8618:"deaf4687",8658:"915e8c20",8675:"9798f4d9",8686:"64d5bca2",8746:"8a11dd40",8752:"99de598e",8757:"31f39ca8",8778:"5677aa36",8818:"8a533cd9",8849:"bf911669",8853:"a9080be1",8856:"988b02ff",8864:"6e99380a",8919:"643fc552",8961:"c98fc885",9006:"e2b039a7",9048:"953ebb91",9055:"be624869",9073:"0a342404",9120:"cc4ee629",9231:"87b00d7f",9241:"121f8efa",9261:"d75ca43a",9297:"f777844d",9298:"70354ce4",9434:"177d3556",9450:"866e1a94",9523:"390b1e27",9533:"9e9f1577",9570:"ebdf0d03",9610:"9c6acb63",9627:"d2cd1008",9639:"f02dc04a",9652:"5e59f0b7",9654:"cd620f12",9661:"697f2be4",9667:"4d91b24c",9670:"7572de5c",9705:"c796222e",9726:"b5b58d3f",9735:"c4c22c4f",9773:"b78f4d98",9783:"afea5b69",9792:"a61a2dc6",9835:"a4405588",9953:"cd6ce099"}[e]+".js",t.miniCssF=e=>{},t.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),t.o=(e,d)=>Object.prototype.hasOwnProperty.call(e,d),c={},f="serverpod-docs:",t.l=(e,d,a,b)=>{if(c[e])c[e].push(d);else{var r,o;if(void 0!==a)for(var n=document.getElementsByTagName("script"),i=0;i{r.onerror=r.onload=null,clearTimeout(s);var f=c[e];if(delete c[e],r.parentNode&&r.parentNode.removeChild(r),f&&f.forEach((e=>e(a))),d)return d(a)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:r}),12e4);r.onerror=l.bind(null,r.onerror),r.onload=l.bind(null,r.onload),o&&document.head.appendChild(r)}},t.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.p="/",t.gca=function(e){return e={13798859:"3380",16116660:"7503",17896441:"7918",44145933:"7425",44463284:"2917",49849746:"3357",62037464:"6490",65399378:"8018",68401255:"7927",79840965:"6570",92466816:"6714",96331245:"8548","984d6493":"45","935f2afb":"53","313c9eb1":"58",b1394c86:"99","7d63aba8":"102",c10a0985:"114","986f0f98":"131",a2a1c245:"187","566f49fb":"281","072aa2d8":"282",f28f059c:"334","2d11a680":"372",b809d820:"397","511f9951":"399",da071cb8:"420","6ba85e75":"550","4f0519c7":"578","83c6f999":"599",bd568e77:"669","94b2bc9a":"770","719163ad":"832",eecc43ff:"845","1b6591f7":"847","1a84c7fd":"860","85d514f3":"870","71ba2dc1":"887","51ddac88":"967","45939ed5":"969","8b75b47c":"979","0d76317c":"1017",f6adf820:"1027","17dc776d":"1086",a1154d73:"1103",a4adf53f:"1129",bd118f84:"1131",dc4059b2:"1162","1323771c":"1251",fc6f07d2:"1308","6feb7661":"1315","6e29a506":"1332","8e0e42ad":"1362","2bbc2deb":"1370","8552f549":"1372","5143312c":"1400","9c9052d1":"1414","9d779d8b":"1419",dec2bd4a:"1444",c3373259:"1453",e3d58533:"1458","3d277f18":"1481","9f8e6d57":"1483",da19ecb4:"1485","87ab7385":"1499","4f83adf9":"1567","805a59dc":"1569","897331c0":"1577","4519f039":"1582","25c6d77a":"1616",ea237062:"1651","1d39c85d":"1656","44a83f6a":"1681","9639af7c":"1697","9906d6d9":"1703","61ff6850":"1733","61aeda71":"1754","3817c387":"1816","7de3e81f":"1826","669968f9":"1827","419cd6b8":"1834",ce4dbf6d:"1843","3aa0ab0a":"1876","801276a1":"1898",afb7a97b:"1938","812cd700":"1978",ecb3c634:"1982",be37811c:"1996",e7977816:"2001","444a6d4e":"2020",f2c30f0a:"2029","54cab4d4":"2040","93dcedec":"2058","819b642a":"2068",cdc118a8:"2105","4aa94ec1":"2128","7570de64":"2151","2b67eda4":"2154","956829f8":"2165",c8139b75:"2181","0893faed":"2265",b79774cd:"2284","6d2a4d3f":"2330","33c1d41a":"2372","9b4ab8cd":"2394","15f7c149":"2400",fe76eed8:"2428","869ae8a7":"2475",ae0eacdd:"2500","5f6b1733":"2544","4a197f0b":"2559","071f33a8":"2631","1921e4ca":"2696","1457ddcd":"2733",c3094240:"2743","676f1bdb":"2768","3e87058f":"2784","2955939d":"2793",ad61550a:"2890","95a5d2b2":"2924","467a9f36":"2935","526e379a":"2981","6a2e0576":"2989","710ac1c1":"3012",b9ec56c8:"3029","4cbee5e0":"3036","4e689a0b":"3057","2590f46b":"3083",d2aa311d:"3095",d8d6d57b:"3109","7479a3f8":"3172","4a49065b":"3174",dc8c27bd:"3238","997397e3":"3243",ef4456b5:"3283","30bd0f5b":"3310",d2f6d210:"3314","7f0714d1":"3377",ec91ff36:"3414","96e80ddd":"3446","068743c8":"3457","227d1fc4":"3525",c342bcae:"3537",a6311318:"3624",d84f251f:"3642","5d707891":"3768","6da448d1":"3770","4867e743":"3786","0c695afe":"3866",b0f19176:"3889",f7ae65ac:"3905","4ab30eec":"3929","82ea7079":"3949","2db99065":"3954",af754a1f:"3962",cce58fe7:"3978","2db5c390":"3983",d4067975:"3988","9e0c2c37":"4013","24557dbc":"4039","272aa200":"4055","27b43779":"4056","5c6f6ba9":"4081",b5dcbe95:"4086","98f4e1ec":"4102",fc8b5a5d:"4135",da698f4c:"4161",e4a796aa:"4169",dd31e7e9:"4201",abd13aa2:"4235","999788b8":"4302","9fbfaf6d":"4325","8e7261c9":"4331",bdc5a52e:"4351",a94703ab:"4368",daec0d60:"4378",bafd283f:"4384","8b6141b3":"4426",afa99621:"4453","070c8c93":"4477","50f02128":"4531","51e50f95":"4571",dd059c51:"4613",a32c313f:"4641",c090764b:"4650",ebd05845:"4652","327b0a57":"4665","52f87500":"4786",d6dc384d:"4799","378935ce":"4801","099a3596":"4807","813cfb2f":"4842",d8020439:"4939","646cbece":"4955",fac0eceb:"4969",ee65edec:"5002","9107c65f":"5069",a6397568:"5080","59c6c1db":"5085","3c9432f0":"5109",e2d6ba1f:"5151",b26210db:"5172","945c4294":"5182","21b7a589":"5183","6458864c":"5190","3cc71396":"5217","522ca66b":"5227","89b55a09":"5239","18910d94":"5261","62dc82db":"5265","9ed3f7e3":"5267","45dd886d":"5285","5839343c":"5293",c0650537:"5321","62e81aa6":"5329","9e09f891":"5367","06393fc1":"5413",d58f1ee2:"5478","90239e6e":"5482","726a6c22":"5515","26398b18":"5532","79d28454":"5630","504d78e0":"5664","2ace8790":"5666","2e1ee4ed":"5688",cd461806:"5710","704545ab":"5724",f5fed352:"5730",efe5610c:"5738","05552792":"5754","2d16d24d":"5767",a81cb65f:"5801","42abcd4d":"5805","92f483f2":"5836","4a209014":"5838","564db590":"5873","616631fd":"5900","03b3cfd2":"5935",e84b4e80:"5955","69cda322":"5963","5c1eff22":"5969","4aec9039":"6031",cb867d98:"6055","5887a6b3":"6086",b28bd8b1:"6092",e8f4756d:"6099","9f1829f0":"6107",adce8179:"6183","1dda0a07":"6199",bd6f2233:"6223","3fe65583":"6265","055b225f":"6279",a4c89d62:"6288","45926b62":"6297","1a30ce1a":"6302","0a5c01b2":"6401",e4eafb12:"6495","03b2528f":"6506",d95655b8:"6508","07e708e9":"6527","65c67349":"6536","4bfca71d":"6553","3113b236":"6582","33f4c6a9":"6611","3f80bb14":"6640","5bc657fa":"6719","5112ebe3":"6738","53e9dd7a":"6740",d802bb56:"6777","9f85e773":"6789","0ae57e5e":"6837","141135bb":"6845",c7156cf2:"6863","08aab21d":"6864","5f5da5ff":"6895",c377a04b:"6971","954e932f":"6974","82444e58":"7001",c2b45dbb:"7051","8dfd8953":"7065","8a5390a0":"7071","10e37c04":"7112",fd4b36bb:"7123","23975af2":"7129","098f2604":"7136","926056c1":"7139","8e374c01":"7250",b32c213b:"7251","9a594c98":"7262","9d36f238":"7265",cdd4a9c6:"7273","8bed5a26":"7311","7af31c45":"7395",e3443ce0:"7427",b7ea99f7:"7485","67e77328":"7486","3e4a4cb2":"7489","81e4ed6a":"7492","07006f9e":"7512","616bfcf6":"7539","063d75bd":"7566","2e18ba50":"7613","49145cdf":"7670","638e38ae":"7673",c75d145e:"7677",b744c57f:"7708",ed64c12e:"7718","59df87e8":"7800","3141060a":"7819",c6e65aef:"7847","7ca2e59a":"7858","5af30237":"7932",b8787c81:"7955",db7d4591:"7980",e64edb60:"8044","3d150a24":"8047","169f3d24":"8076","26a0dea9":"8110","0773e78b":"8143","4934de22":"8172","9644aa4e":"8202","98c94590":"8213","2596363d":"8232",fe3f3783:"8278",d4fc3158:"8287","7974de6c":"8299",d26a73b8:"8317",e15bcb33:"8326",bd1cffff:"8341",e66f2658:"8344",eac16e1d:"8349",be895d61:"8369","38e32826":"8378",ac6e050c:"8413",aee9697b:"8438",f584139f:"8456",ac3101e9:"8457",a0aa5253:"8486",eb4c176e:"8492",a7bd4aaa:"8518","9d7352c0":"8524","5d8361b1":"8539","6a734661":"8560","056b386b":"8571","1d3ec39f":"8573","00d14154":"8618","2c2832e4":"8658","28967b3e":"8675","02e41de2":"8686","8af032d3":"8746",d44e0d1c:"8752","73ca4188":"8757","5e7d099e":"8778",d636c09f:"8818","5e253f2f":"8849",c05c66f0:"8853",afde3230:"8856","4eee9c87":"8864","8a14b359":"8919",ed942358:"8961","0f4a5c74":"9006","640696ee":"9048","10ad1fa6":"9055",a64b2578:"9073",e0bec135:"9120","31b73615":"9231","092bf57d":"9241",d86e4bec:"9261",f9bde383:"9297","6aee17c2":"9298","8ee9837e":"9434","3874f1bf":"9450","05fa9a60":"9523","8baf194b":"9533",f149b10e:"9570",f4f85478:"9610",f3467f26:"9627","4c781063":"9639",bb9c591b:"9652","5589c54d":"9654","5e95c892":"9661",cbf3c4ec:"9667","86a8bb6c":"9670",a7edc2bd:"9705","10ea0b82":"9726",b1218054:"9735","12407b36":"9773","4b6eee9a":"9783","7c4a294c":"9792","4ac2e930":"9835","2020ed93":"9953"}[e]||e,t.p+t.u(e)},(()=>{var e={1303:0,532:0};t.f.j=(d,a)=>{var c=t.o(e,d)?e[d]:void 0;if(0!==c)if(c)a.push(c[2]);else if(/^(1303|532)$/.test(d))e[d]=0;else{var f=new Promise(((a,f)=>c=e[d]=[a,f]));a.push(c[2]=f);var b=t.p+t.u(d),r=new Error;t.l(b,(a=>{if(t.o(e,d)&&(0!==(c=e[d])&&(e[d]=void 0),c)){var f=a&&("load"===a.type?"missing":a.type),b=a&&a.target&&a.target.src;r.message="Loading chunk "+d+" failed.\n("+f+": "+b+")",r.name="ChunkLoadError",r.type=f,r.request=b,c[1](r)}}),"chunk-"+d,d)}},t.O.j=d=>0===e[d];var d=(d,a)=>{var c,f,b=a[0],r=a[1],o=a[2],n=0;if(b.some((d=>0!==e[d]))){for(c in r)t.o(r,c)&&(t.m[c]=r[c]);if(o)var i=o(t)}for(d&&d(a);n Capabilities | Serverpod - + diff --git a/docs/cli.html b/docs/cli.html index e27d03dea..1519f5254 100644 --- a/docs/cli.html +++ b/docs/cli.html @@ -4,7 +4,7 @@ Serverpod CLI | Serverpod - + diff --git a/docs/concepts/authentication/basics.html b/docs/concepts/authentication/basics.html index 1f12a459c..900a1710c 100644 --- a/docs/concepts/authentication/basics.html +++ b/docs/concepts/authentication/basics.html @@ -4,7 +4,7 @@ The basics | Serverpod - + diff --git a/docs/concepts/authentication/custom-overrides.html b/docs/concepts/authentication/custom-overrides.html index 45e88e667..49a19a708 100644 --- a/docs/concepts/authentication/custom-overrides.html +++ b/docs/concepts/authentication/custom-overrides.html @@ -4,7 +4,7 @@ Custom overrides | Serverpod - + diff --git a/docs/concepts/authentication/providers/apple.html b/docs/concepts/authentication/providers/apple.html index 6c6f88114..bb26fcf00 100644 --- a/docs/concepts/authentication/providers/apple.html +++ b/docs/concepts/authentication/providers/apple.html @@ -4,7 +4,7 @@ Apple | Serverpod - + diff --git a/docs/concepts/authentication/providers/custom-providers.html b/docs/concepts/authentication/providers/custom-providers.html index 49b9c5f5c..fe8014900 100644 --- a/docs/concepts/authentication/providers/custom-providers.html +++ b/docs/concepts/authentication/providers/custom-providers.html @@ -4,7 +4,7 @@ Custom providers | Serverpod - + diff --git a/docs/concepts/authentication/providers/email.html b/docs/concepts/authentication/providers/email.html index 2b1c4d19b..bb7d10a3c 100644 --- a/docs/concepts/authentication/providers/email.html +++ b/docs/concepts/authentication/providers/email.html @@ -4,7 +4,7 @@ Email | Serverpod - + diff --git a/docs/concepts/authentication/providers/firebase.html b/docs/concepts/authentication/providers/firebase.html index 36e8e8bbb..8fd5fe00e 100644 --- a/docs/concepts/authentication/providers/firebase.html +++ b/docs/concepts/authentication/providers/firebase.html @@ -4,7 +4,7 @@ Firebase | Serverpod - + diff --git a/docs/concepts/authentication/providers/google.html b/docs/concepts/authentication/providers/google.html index 737921463..d781622e9 100644 --- a/docs/concepts/authentication/providers/google.html +++ b/docs/concepts/authentication/providers/google.html @@ -4,7 +4,7 @@ Google | Serverpod - + diff --git a/docs/concepts/authentication/setup.html b/docs/concepts/authentication/setup.html index 32ab41fd7..906354c5c 100644 --- a/docs/concepts/authentication/setup.html +++ b/docs/concepts/authentication/setup.html @@ -4,7 +4,7 @@ Setup | Serverpod - + diff --git a/docs/concepts/authentication/working-with-users.html b/docs/concepts/authentication/working-with-users.html index 9c7c9cb46..50eea46b2 100644 --- a/docs/concepts/authentication/working-with-users.html +++ b/docs/concepts/authentication/working-with-users.html @@ -4,7 +4,7 @@ Working with users | Serverpod - + diff --git a/docs/concepts/backward-compatibility.html b/docs/concepts/backward-compatibility.html index 094fddc7e..ecc2c90fd 100644 --- a/docs/concepts/backward-compatibility.html +++ b/docs/concepts/backward-compatibility.html @@ -4,7 +4,7 @@ Backward compatibility | Serverpod - + diff --git a/docs/concepts/caching.html b/docs/concepts/caching.html index 496759175..3154c9441 100644 --- a/docs/concepts/caching.html +++ b/docs/concepts/caching.html @@ -4,7 +4,7 @@ Caching | Serverpod - + diff --git a/docs/concepts/database/connection.html b/docs/concepts/database/connection.html index 6de00c948..e0a68bedb 100644 --- a/docs/concepts/database/connection.html +++ b/docs/concepts/database/connection.html @@ -4,7 +4,7 @@ Connection | Serverpod - + diff --git a/docs/concepts/database/crud.html b/docs/concepts/database/crud.html index 0d91a0251..04d018a82 100644 --- a/docs/concepts/database/crud.html +++ b/docs/concepts/database/crud.html @@ -4,7 +4,7 @@ CRUD | Serverpod - + @@ -35,7 +35,7 @@

Finding
info

Note that ordering of the entries is important here as it will return the fist row returned by the database query.

Finding multiple rows

To find multiple rows, use the same principle as for finding a single row.

-
var companies = await Company.db.find(
session,
where: (t) => t.id < 100,
limit 50,
);
+
var companies = await Company.db.find(
session,
where: (t) => t.id < 100,
limit: 50,
);

This operation returns a List of your models matching the filtering criteria.

See filter and sort for all filter and sorting operations and pagination for how to paginate the result.

Update

diff --git a/docs/concepts/database/filter.html b/docs/concepts/database/filter.html index abbbedb61..fa2204210 100644 --- a/docs/concepts/database/filter.html +++ b/docs/concepts/database/filter.html @@ -4,7 +4,7 @@ Filter | Serverpod - + diff --git a/docs/concepts/database/indexing.html b/docs/concepts/database/indexing.html index e957fa8cf..72aa8fb44 100644 --- a/docs/concepts/database/indexing.html +++ b/docs/concepts/database/indexing.html @@ -4,7 +4,7 @@ Indexing | Serverpod - + diff --git a/docs/concepts/database/migrations.html b/docs/concepts/database/migrations.html index 74d479e6e..ab2610da5 100644 --- a/docs/concepts/database/migrations.html +++ b/docs/concepts/database/migrations.html @@ -4,7 +4,7 @@ Migrations | Serverpod - + diff --git a/docs/concepts/database/models.html b/docs/concepts/database/models.html index 633f36097..f33034694 100644 --- a/docs/concepts/database/models.html +++ b/docs/concepts/database/models.html @@ -4,7 +4,7 @@ Models | Serverpod - + diff --git a/docs/concepts/database/pagination.html b/docs/concepts/database/pagination.html index 556acbc56..3dea87c85 100644 --- a/docs/concepts/database/pagination.html +++ b/docs/concepts/database/pagination.html @@ -4,7 +4,7 @@ Pagination | Serverpod - + diff --git a/docs/concepts/database/raw-access.html b/docs/concepts/database/raw-access.html index 4990c6836..493816140 100644 --- a/docs/concepts/database/raw-access.html +++ b/docs/concepts/database/raw-access.html @@ -4,7 +4,7 @@ Raw access | Serverpod - + diff --git a/docs/concepts/database/relation-queries.html b/docs/concepts/database/relation-queries.html index fba5ca74b..18a548cdd 100644 --- a/docs/concepts/database/relation-queries.html +++ b/docs/concepts/database/relation-queries.html @@ -4,7 +4,7 @@ Relation queries | Serverpod - + diff --git a/docs/concepts/database/relations/many-to-many.html b/docs/concepts/database/relations/many-to-many.html index c7d33e946..10a5ebcf1 100644 --- a/docs/concepts/database/relations/many-to-many.html +++ b/docs/concepts/database/relations/many-to-many.html @@ -4,7 +4,7 @@ Many-to-Many | Serverpod - + diff --git a/docs/concepts/database/relations/modules.html b/docs/concepts/database/relations/modules.html index 3c8f4cd22..4fb881ee1 100644 --- a/docs/concepts/database/relations/modules.html +++ b/docs/concepts/database/relations/modules.html @@ -4,7 +4,7 @@ Relations with modules | Serverpod - + diff --git a/docs/concepts/database/relations/one-to-many.html b/docs/concepts/database/relations/one-to-many.html index 5576e45a5..3876cee66 100644 --- a/docs/concepts/database/relations/one-to-many.html +++ b/docs/concepts/database/relations/one-to-many.html @@ -4,7 +4,7 @@ One-to-many | Serverpod - + diff --git a/docs/concepts/database/relations/one-to-one.html b/docs/concepts/database/relations/one-to-one.html index c932c53a7..e62cad18e 100644 --- a/docs/concepts/database/relations/one-to-one.html +++ b/docs/concepts/database/relations/one-to-one.html @@ -4,7 +4,7 @@ One-to-one | Serverpod - + diff --git a/docs/concepts/database/relations/referential-actions.html b/docs/concepts/database/relations/referential-actions.html index 04e432897..da4342a45 100644 --- a/docs/concepts/database/relations/referential-actions.html +++ b/docs/concepts/database/relations/referential-actions.html @@ -4,7 +4,7 @@ Referential actions | Serverpod - + diff --git a/docs/concepts/database/relations/self-relations.html b/docs/concepts/database/relations/self-relations.html index f03cfea3f..97bd56e3e 100644 --- a/docs/concepts/database/relations/self-relations.html +++ b/docs/concepts/database/relations/self-relations.html @@ -4,7 +4,7 @@ Self-relations | Serverpod - + diff --git a/docs/concepts/database/sort.html b/docs/concepts/database/sort.html index 5eb26d05e..0cfc6a6aa 100644 --- a/docs/concepts/database/sort.html +++ b/docs/concepts/database/sort.html @@ -4,7 +4,7 @@ Sort | Serverpod - + diff --git a/docs/concepts/database/transactions.html b/docs/concepts/database/transactions.html index 5c2d3ebfa..276fecc2d 100644 --- a/docs/concepts/database/transactions.html +++ b/docs/concepts/database/transactions.html @@ -4,7 +4,7 @@ Transactions | Serverpod - + diff --git a/docs/concepts/exceptions.html b/docs/concepts/exceptions.html index 39bc1a984..aa1ebdd2d 100644 --- a/docs/concepts/exceptions.html +++ b/docs/concepts/exceptions.html @@ -4,7 +4,7 @@ Error handling and exceptions | Serverpod - + diff --git a/docs/concepts/file-uploads.html b/docs/concepts/file-uploads.html index be94a04d1..ff79912fe 100644 --- a/docs/concepts/file-uploads.html +++ b/docs/concepts/file-uploads.html @@ -4,7 +4,7 @@ Uploading files | Serverpod - + diff --git a/docs/concepts/health-checks.html b/docs/concepts/health-checks.html index 160362477..f37170406 100644 --- a/docs/concepts/health-checks.html +++ b/docs/concepts/health-checks.html @@ -4,7 +4,7 @@ Health checks | Serverpod - + diff --git a/docs/concepts/logging.html b/docs/concepts/logging.html index 0d456d736..1e768b620 100644 --- a/docs/concepts/logging.html +++ b/docs/concepts/logging.html @@ -4,7 +4,7 @@ Logging | Serverpod - + diff --git a/docs/concepts/models.html b/docs/concepts/models.html index c674ae427..eb3df66b0 100644 --- a/docs/concepts/models.html +++ b/docs/concepts/models.html @@ -4,7 +4,7 @@ Working with models | Serverpod - + diff --git a/docs/concepts/modules.html b/docs/concepts/modules.html index b695ecbb3..223cb9aae 100644 --- a/docs/concepts/modules.html +++ b/docs/concepts/modules.html @@ -4,7 +4,7 @@ Modules | Serverpod - + diff --git a/docs/concepts/scheduling.html b/docs/concepts/scheduling.html index bf057a57e..8fcc0a62d 100644 --- a/docs/concepts/scheduling.html +++ b/docs/concepts/scheduling.html @@ -4,7 +4,7 @@ Scheduling | Serverpod - + diff --git a/docs/concepts/serialization.html b/docs/concepts/serialization.html index 5bf536e89..ba24174b0 100644 --- a/docs/concepts/serialization.html +++ b/docs/concepts/serialization.html @@ -4,7 +4,7 @@ Custom serialization | Serverpod - + diff --git a/docs/concepts/sessions.html b/docs/concepts/sessions.html index fa840cb01..7b44e3c9e 100644 --- a/docs/concepts/sessions.html +++ b/docs/concepts/sessions.html @@ -4,7 +4,7 @@ Sessions | Serverpod - + diff --git a/docs/concepts/streams.html b/docs/concepts/streams.html index f06f1adc4..5e2bab0e3 100644 --- a/docs/concepts/streams.html +++ b/docs/concepts/streams.html @@ -4,7 +4,7 @@ Streams and messaging | Serverpod - + diff --git a/docs/concepts/webserver.html b/docs/concepts/webserver.html index 60bec9d4c..7d85dfcc3 100644 --- a/docs/concepts/webserver.html +++ b/docs/concepts/webserver.html @@ -4,7 +4,7 @@ Web server | Serverpod - + diff --git a/docs/concepts/working-with-endpoints.html b/docs/concepts/working-with-endpoints.html index cc3187ce6..29179f3b5 100644 --- a/docs/concepts/working-with-endpoints.html +++ b/docs/concepts/working-with-endpoints.html @@ -4,7 +4,7 @@ Working with endpoints | Serverpod - + diff --git a/docs/contribute.html b/docs/contribute.html index 29ca7bef2..86dad89fc 100644 --- a/docs/contribute.html +++ b/docs/contribute.html @@ -4,7 +4,7 @@ Contribute | Serverpod - + diff --git a/docs/deployments/deploying-to-aws.html b/docs/deployments/deploying-to-aws.html index 56f8a77a9..efac89712 100644 --- a/docs/deployments/deploying-to-aws.html +++ b/docs/deployments/deploying-to-aws.html @@ -4,7 +4,7 @@ AWS EC2 with Terraform | Serverpod - + diff --git a/docs/deployments/deploying-to-gce-terraform.html b/docs/deployments/deploying-to-gce-terraform.html index 4b2b88ab1..b171860e0 100644 --- a/docs/deployments/deploying-to-gce-terraform.html +++ b/docs/deployments/deploying-to-gce-terraform.html @@ -4,7 +4,7 @@ Google Cloud Engine with Terraform | Serverpod - + diff --git a/docs/deployments/deploying-to-gcr-console.html b/docs/deployments/deploying-to-gcr-console.html index 76d374ff1..03f5b7439 100644 --- a/docs/deployments/deploying-to-gcr-console.html +++ b/docs/deployments/deploying-to-gcr-console.html @@ -4,7 +4,7 @@ Google Cloud Run with CGP Console | Serverpod - + diff --git a/docs/deployments/deployment-strategy.html b/docs/deployments/deployment-strategy.html index 94c955402..13bd3adfe 100644 --- a/docs/deployments/deployment-strategy.html +++ b/docs/deployments/deployment-strategy.html @@ -4,7 +4,7 @@ Choosing deployment strategy | Serverpod - + diff --git a/docs/deployments/general.html b/docs/deployments/general.html index 4b56c94f3..59b4aa2da 100644 --- a/docs/deployments/general.html +++ b/docs/deployments/general.html @@ -4,7 +4,7 @@ Hosting elsewhere | Serverpod - + diff --git a/docs/get-started.html b/docs/get-started.html index a2066adea..ab1ce26d1 100644 --- a/docs/get-started.html +++ b/docs/get-started.html @@ -4,7 +4,7 @@ Get started | Serverpod - + diff --git a/docs/index.html b/docs/index.html index 4c972e76d..1e86faca4 100644 --- a/docs/index.html +++ b/docs/index.html @@ -4,7 +4,7 @@ Installing Serverpod | Serverpod - + diff --git a/docs/insights.html b/docs/insights.html index 1490ede40..4ec8e7edf 100644 --- a/docs/insights.html +++ b/docs/insights.html @@ -4,7 +4,7 @@ Serverpod Insights | Serverpod - + diff --git a/docs/lsp.html b/docs/lsp.html index 3280ab7d7..b189547e1 100644 --- a/docs/lsp.html +++ b/docs/lsp.html @@ -4,7 +4,7 @@ Serverpod LSP | Serverpod - + diff --git a/docs/next.html b/docs/next.html index b1ba5c96a..aa770fb82 100644 --- a/docs/next.html +++ b/docs/next.html @@ -4,7 +4,7 @@ Installing Serverpod | Serverpod - + diff --git a/docs/next/capabilities.html b/docs/next/capabilities.html index 121b662ee..ca6330d4c 100644 --- a/docs/next/capabilities.html +++ b/docs/next/capabilities.html @@ -4,7 +4,7 @@ Capabilities | Serverpod - + diff --git a/docs/next/cli.html b/docs/next/cli.html index b30a354fa..8d407aa66 100644 --- a/docs/next/cli.html +++ b/docs/next/cli.html @@ -4,7 +4,7 @@ Serverpod CLI | Serverpod - + diff --git a/docs/next/concepts/authentication/basics.html b/docs/next/concepts/authentication/basics.html index dce919fad..d60b4b34d 100644 --- a/docs/next/concepts/authentication/basics.html +++ b/docs/next/concepts/authentication/basics.html @@ -4,7 +4,7 @@ The basics | Serverpod - + diff --git a/docs/next/concepts/authentication/custom-overrides.html b/docs/next/concepts/authentication/custom-overrides.html index 3ebbffe9d..4bb827e32 100644 --- a/docs/next/concepts/authentication/custom-overrides.html +++ b/docs/next/concepts/authentication/custom-overrides.html @@ -4,7 +4,7 @@ Custom overrides | Serverpod - + diff --git a/docs/next/concepts/authentication/providers/apple.html b/docs/next/concepts/authentication/providers/apple.html index 45095fd79..47b14d172 100644 --- a/docs/next/concepts/authentication/providers/apple.html +++ b/docs/next/concepts/authentication/providers/apple.html @@ -4,7 +4,7 @@ Apple | Serverpod - + diff --git a/docs/next/concepts/authentication/providers/custom-providers.html b/docs/next/concepts/authentication/providers/custom-providers.html index c3756748f..39beeb710 100644 --- a/docs/next/concepts/authentication/providers/custom-providers.html +++ b/docs/next/concepts/authentication/providers/custom-providers.html @@ -4,7 +4,7 @@ Custom providers | Serverpod - + diff --git a/docs/next/concepts/authentication/providers/email.html b/docs/next/concepts/authentication/providers/email.html index 99a283f5d..c671ff78e 100644 --- a/docs/next/concepts/authentication/providers/email.html +++ b/docs/next/concepts/authentication/providers/email.html @@ -4,7 +4,7 @@ Email | Serverpod - + diff --git a/docs/next/concepts/authentication/providers/firebase.html b/docs/next/concepts/authentication/providers/firebase.html index c0e5aad1d..4587c0e4a 100644 --- a/docs/next/concepts/authentication/providers/firebase.html +++ b/docs/next/concepts/authentication/providers/firebase.html @@ -4,7 +4,7 @@ Firebase | Serverpod - + diff --git a/docs/next/concepts/authentication/providers/google.html b/docs/next/concepts/authentication/providers/google.html index 320c179af..777284514 100644 --- a/docs/next/concepts/authentication/providers/google.html +++ b/docs/next/concepts/authentication/providers/google.html @@ -4,7 +4,7 @@ Google | Serverpod - + diff --git a/docs/next/concepts/authentication/setup.html b/docs/next/concepts/authentication/setup.html index 8f39eb53b..1268b0887 100644 --- a/docs/next/concepts/authentication/setup.html +++ b/docs/next/concepts/authentication/setup.html @@ -4,7 +4,7 @@ Setup | Serverpod - + diff --git a/docs/next/concepts/authentication/working-with-users.html b/docs/next/concepts/authentication/working-with-users.html index f4acc57e9..d68bf8196 100644 --- a/docs/next/concepts/authentication/working-with-users.html +++ b/docs/next/concepts/authentication/working-with-users.html @@ -4,7 +4,7 @@ Working with users | Serverpod - + diff --git a/docs/next/concepts/backward-compatibility.html b/docs/next/concepts/backward-compatibility.html index eaf6b1e3d..860f09797 100644 --- a/docs/next/concepts/backward-compatibility.html +++ b/docs/next/concepts/backward-compatibility.html @@ -4,7 +4,7 @@ Backward compatibility | Serverpod - + diff --git a/docs/next/concepts/caching.html b/docs/next/concepts/caching.html index 835b8c7a3..8e30f985e 100644 --- a/docs/next/concepts/caching.html +++ b/docs/next/concepts/caching.html @@ -4,7 +4,7 @@ Caching | Serverpod - + diff --git a/docs/next/concepts/database/connection.html b/docs/next/concepts/database/connection.html index e8ba529da..a0208b9aa 100644 --- a/docs/next/concepts/database/connection.html +++ b/docs/next/concepts/database/connection.html @@ -4,7 +4,7 @@ Connection | Serverpod - + diff --git a/docs/next/concepts/database/crud.html b/docs/next/concepts/database/crud.html index eaa6e4226..49844ebaa 100644 --- a/docs/next/concepts/database/crud.html +++ b/docs/next/concepts/database/crud.html @@ -4,7 +4,7 @@ CRUD | Serverpod - + @@ -35,7 +35,7 @@

Finding
info

Note that ordering of the entries is important here as it will return the fist row returned by the database query.

Finding multiple rows

To find multiple rows, use the same principle as for finding a single row.

-
var companies = await Company.db.find(
session,
where: (t) => t.id < 100,
limit 50,
);
+
var companies = await Company.db.find(
session,
where: (t) => t.id < 100,
limit: 50,
);

This operation returns a List of your models matching the filtering criteria.

See filter and sort for all filter and sorting operations and pagination for how to paginate the result.

Update

diff --git a/docs/next/concepts/database/filter.html b/docs/next/concepts/database/filter.html index 7aeca9698..7b51b5598 100644 --- a/docs/next/concepts/database/filter.html +++ b/docs/next/concepts/database/filter.html @@ -4,7 +4,7 @@ Filter | Serverpod - + diff --git a/docs/next/concepts/database/indexing.html b/docs/next/concepts/database/indexing.html index c5862958f..e25703358 100644 --- a/docs/next/concepts/database/indexing.html +++ b/docs/next/concepts/database/indexing.html @@ -4,7 +4,7 @@ Indexing | Serverpod - + diff --git a/docs/next/concepts/database/migrations.html b/docs/next/concepts/database/migrations.html index 9e852f11e..ac0020adb 100644 --- a/docs/next/concepts/database/migrations.html +++ b/docs/next/concepts/database/migrations.html @@ -4,7 +4,7 @@ Migrations | Serverpod - + diff --git a/docs/next/concepts/database/models.html b/docs/next/concepts/database/models.html index 462ceb728..e796b1c7d 100644 --- a/docs/next/concepts/database/models.html +++ b/docs/next/concepts/database/models.html @@ -4,7 +4,7 @@ Models | Serverpod - + diff --git a/docs/next/concepts/database/pagination.html b/docs/next/concepts/database/pagination.html index 1b0a5014f..1d523f520 100644 --- a/docs/next/concepts/database/pagination.html +++ b/docs/next/concepts/database/pagination.html @@ -4,7 +4,7 @@ Pagination | Serverpod - + diff --git a/docs/next/concepts/database/raw-access.html b/docs/next/concepts/database/raw-access.html index 11707a0c1..8205af137 100644 --- a/docs/next/concepts/database/raw-access.html +++ b/docs/next/concepts/database/raw-access.html @@ -4,7 +4,7 @@ Raw access | Serverpod - + diff --git a/docs/next/concepts/database/relation-queries.html b/docs/next/concepts/database/relation-queries.html index 3e2eb938d..76738ff76 100644 --- a/docs/next/concepts/database/relation-queries.html +++ b/docs/next/concepts/database/relation-queries.html @@ -4,7 +4,7 @@ Relation queries | Serverpod - + diff --git a/docs/next/concepts/database/relations/many-to-many.html b/docs/next/concepts/database/relations/many-to-many.html index 14361f35e..0d96bd95a 100644 --- a/docs/next/concepts/database/relations/many-to-many.html +++ b/docs/next/concepts/database/relations/many-to-many.html @@ -4,7 +4,7 @@ Many-to-Many | Serverpod - + diff --git a/docs/next/concepts/database/relations/modules.html b/docs/next/concepts/database/relations/modules.html index e687492a5..d9235d636 100644 --- a/docs/next/concepts/database/relations/modules.html +++ b/docs/next/concepts/database/relations/modules.html @@ -4,7 +4,7 @@ Relations with modules | Serverpod - + diff --git a/docs/next/concepts/database/relations/one-to-many.html b/docs/next/concepts/database/relations/one-to-many.html index c695bdb96..f74a9a12e 100644 --- a/docs/next/concepts/database/relations/one-to-many.html +++ b/docs/next/concepts/database/relations/one-to-many.html @@ -4,7 +4,7 @@ One-to-many | Serverpod - + diff --git a/docs/next/concepts/database/relations/one-to-one.html b/docs/next/concepts/database/relations/one-to-one.html index 1eeb6f4e3..87eb2cbbc 100644 --- a/docs/next/concepts/database/relations/one-to-one.html +++ b/docs/next/concepts/database/relations/one-to-one.html @@ -4,7 +4,7 @@ One-to-one | Serverpod - + diff --git a/docs/next/concepts/database/relations/referential-actions.html b/docs/next/concepts/database/relations/referential-actions.html index 06d3a175a..b3190fe09 100644 --- a/docs/next/concepts/database/relations/referential-actions.html +++ b/docs/next/concepts/database/relations/referential-actions.html @@ -4,7 +4,7 @@ Referential actions | Serverpod - + diff --git a/docs/next/concepts/database/relations/self-relations.html b/docs/next/concepts/database/relations/self-relations.html index 0e13cd61b..1e5893fc7 100644 --- a/docs/next/concepts/database/relations/self-relations.html +++ b/docs/next/concepts/database/relations/self-relations.html @@ -4,7 +4,7 @@ Self-relations | Serverpod - + diff --git a/docs/next/concepts/database/sort.html b/docs/next/concepts/database/sort.html index a27b84463..0653ed1f3 100644 --- a/docs/next/concepts/database/sort.html +++ b/docs/next/concepts/database/sort.html @@ -4,7 +4,7 @@ Sort | Serverpod - + diff --git a/docs/next/concepts/database/transactions.html b/docs/next/concepts/database/transactions.html index 73734d34e..e90f76a3d 100644 --- a/docs/next/concepts/database/transactions.html +++ b/docs/next/concepts/database/transactions.html @@ -4,7 +4,7 @@ Transactions | Serverpod - + diff --git a/docs/next/concepts/exceptions.html b/docs/next/concepts/exceptions.html index cf1d90fc9..57ace217a 100644 --- a/docs/next/concepts/exceptions.html +++ b/docs/next/concepts/exceptions.html @@ -4,7 +4,7 @@ Error handling and exceptions | Serverpod - + diff --git a/docs/next/concepts/file-uploads.html b/docs/next/concepts/file-uploads.html index 386df564a..0a34b27b8 100644 --- a/docs/next/concepts/file-uploads.html +++ b/docs/next/concepts/file-uploads.html @@ -4,7 +4,7 @@ Uploading files | Serverpod - + diff --git a/docs/next/concepts/health-checks.html b/docs/next/concepts/health-checks.html index fb4fae45d..788ffa876 100644 --- a/docs/next/concepts/health-checks.html +++ b/docs/next/concepts/health-checks.html @@ -4,7 +4,7 @@ Health checks | Serverpod - + diff --git a/docs/next/concepts/logging.html b/docs/next/concepts/logging.html index f59e4a64f..915e834e5 100644 --- a/docs/next/concepts/logging.html +++ b/docs/next/concepts/logging.html @@ -4,7 +4,7 @@ Logging | Serverpod - + diff --git a/docs/next/concepts/models.html b/docs/next/concepts/models.html index 15c15321b..e0cf582de 100644 --- a/docs/next/concepts/models.html +++ b/docs/next/concepts/models.html @@ -4,7 +4,7 @@ Working with models | Serverpod - + diff --git a/docs/next/concepts/modules.html b/docs/next/concepts/modules.html index 9ab55e565..9c2f6a253 100644 --- a/docs/next/concepts/modules.html +++ b/docs/next/concepts/modules.html @@ -4,7 +4,7 @@ Modules | Serverpod - + diff --git a/docs/next/concepts/scheduling.html b/docs/next/concepts/scheduling.html index 0b9238277..fbce30a47 100644 --- a/docs/next/concepts/scheduling.html +++ b/docs/next/concepts/scheduling.html @@ -4,7 +4,7 @@ Scheduling | Serverpod - + diff --git a/docs/next/concepts/serialization.html b/docs/next/concepts/serialization.html index c5d99eac0..af9da81c0 100644 --- a/docs/next/concepts/serialization.html +++ b/docs/next/concepts/serialization.html @@ -4,7 +4,7 @@ Custom serialization | Serverpod - + diff --git a/docs/next/concepts/sessions.html b/docs/next/concepts/sessions.html index 2472a96ee..15df9725d 100644 --- a/docs/next/concepts/sessions.html +++ b/docs/next/concepts/sessions.html @@ -4,7 +4,7 @@ Sessions | Serverpod - + diff --git a/docs/next/concepts/streams.html b/docs/next/concepts/streams.html index 482abcdf1..f5042fbc5 100644 --- a/docs/next/concepts/streams.html +++ b/docs/next/concepts/streams.html @@ -4,7 +4,7 @@ Streams and messaging | Serverpod - + diff --git a/docs/next/concepts/webserver.html b/docs/next/concepts/webserver.html index e3c708068..a2dc41f2c 100644 --- a/docs/next/concepts/webserver.html +++ b/docs/next/concepts/webserver.html @@ -4,7 +4,7 @@ Web server | Serverpod - + diff --git a/docs/next/concepts/working-with-endpoints.html b/docs/next/concepts/working-with-endpoints.html index b0a0782fe..0c0a526b7 100644 --- a/docs/next/concepts/working-with-endpoints.html +++ b/docs/next/concepts/working-with-endpoints.html @@ -4,7 +4,7 @@ Working with endpoints | Serverpod - + diff --git a/docs/next/contribute.html b/docs/next/contribute.html index 03e7228bf..b12f95e06 100644 --- a/docs/next/contribute.html +++ b/docs/next/contribute.html @@ -4,7 +4,7 @@ Contribute | Serverpod - + diff --git a/docs/next/deployments/deploying-to-aws.html b/docs/next/deployments/deploying-to-aws.html index 1abc7c697..ad7b31af1 100644 --- a/docs/next/deployments/deploying-to-aws.html +++ b/docs/next/deployments/deploying-to-aws.html @@ -4,7 +4,7 @@ AWS EC2 with Terraform | Serverpod - + diff --git a/docs/next/deployments/deploying-to-gce-terraform.html b/docs/next/deployments/deploying-to-gce-terraform.html index 27b5b56aa..5c980b0f3 100644 --- a/docs/next/deployments/deploying-to-gce-terraform.html +++ b/docs/next/deployments/deploying-to-gce-terraform.html @@ -4,7 +4,7 @@ Google Cloud Engine with Terraform | Serverpod - + diff --git a/docs/next/deployments/deploying-to-gcr-console.html b/docs/next/deployments/deploying-to-gcr-console.html index f4e20516f..7d7222b78 100644 --- a/docs/next/deployments/deploying-to-gcr-console.html +++ b/docs/next/deployments/deploying-to-gcr-console.html @@ -4,7 +4,7 @@ Google Cloud Run with CGP Console | Serverpod - + diff --git a/docs/next/deployments/deployment-strategy.html b/docs/next/deployments/deployment-strategy.html index 46455e7ea..410278f13 100644 --- a/docs/next/deployments/deployment-strategy.html +++ b/docs/next/deployments/deployment-strategy.html @@ -4,7 +4,7 @@ Choosing deployment strategy | Serverpod - + diff --git a/docs/next/deployments/general.html b/docs/next/deployments/general.html index 13ba181d9..9538d03d4 100644 --- a/docs/next/deployments/general.html +++ b/docs/next/deployments/general.html @@ -4,7 +4,7 @@ Hosting elsewhere | Serverpod - + diff --git a/docs/next/get-started.html b/docs/next/get-started.html index 25a0fbbd2..90beb27ab 100644 --- a/docs/next/get-started.html +++ b/docs/next/get-started.html @@ -4,7 +4,7 @@ Get started | Serverpod - + diff --git a/docs/next/insights.html b/docs/next/insights.html index 7ca0ab04e..4293fa286 100644 --- a/docs/next/insights.html +++ b/docs/next/insights.html @@ -4,7 +4,7 @@ Serverpod Insights | Serverpod - + diff --git a/docs/next/lsp.html b/docs/next/lsp.html index ee281d797..d9105daee 100644 --- a/docs/next/lsp.html +++ b/docs/next/lsp.html @@ -4,7 +4,7 @@ Serverpod LSP | Serverpod - + diff --git a/docs/next/roadmap.html b/docs/next/roadmap.html index 8975c2467..50342977b 100644 --- a/docs/next/roadmap.html +++ b/docs/next/roadmap.html @@ -4,7 +4,7 @@ Roadmap | Serverpod - + diff --git a/docs/next/support.html b/docs/next/support.html index f15f68710..dbb44255d 100644 --- a/docs/next/support.html +++ b/docs/next/support.html @@ -4,7 +4,7 @@ Support & community | Serverpod - + diff --git a/docs/next/tutorials/authentication.html b/docs/next/tutorials/authentication.html index 2b58b58f5..258ee9113 100644 --- a/docs/next/tutorials/authentication.html +++ b/docs/next/tutorials/authentication.html @@ -4,7 +4,7 @@ Authentication | Serverpod - + diff --git a/docs/next/tutorials/code-example.html b/docs/next/tutorials/code-example.html index da07c0c13..5ed04a68e 100644 --- a/docs/next/tutorials/code-example.html +++ b/docs/next/tutorials/code-example.html @@ -4,7 +4,7 @@ Code examples | Serverpod - + diff --git a/docs/next/tutorials/first-app.html b/docs/next/tutorials/first-app.html index 0cb5327b5..8b3a587d1 100644 --- a/docs/next/tutorials/first-app.html +++ b/docs/next/tutorials/first-app.html @@ -4,7 +4,7 @@ Build your first app | Serverpod - + diff --git a/docs/next/tutorials/videos.html b/docs/next/tutorials/videos.html index 8aa5773ca..abe68f355 100644 --- a/docs/next/tutorials/videos.html +++ b/docs/next/tutorials/videos.html @@ -4,7 +4,7 @@ Videos | Serverpod - + diff --git a/docs/next/upgrading/upgrade-to-one-point-two.html b/docs/next/upgrading/upgrade-to-one-point-two.html index 1eab89420..75bf9ad81 100644 --- a/docs/next/upgrading/upgrade-to-one-point-two.html +++ b/docs/next/upgrading/upgrade-to-one-point-two.html @@ -4,7 +4,7 @@ Upgrade to 1.2 | Serverpod - + diff --git a/docs/next/upgrading/upgrade-to-two.html b/docs/next/upgrading/upgrade-to-two.html index 7c61aca13..d107a2eb1 100644 --- a/docs/next/upgrading/upgrade-to-two.html +++ b/docs/next/upgrading/upgrade-to-two.html @@ -4,7 +4,7 @@ Upgrade to 2.0 | Serverpod - + diff --git a/docs/roadmap.html b/docs/roadmap.html index 5e8f9cf58..99d2318a2 100644 --- a/docs/roadmap.html +++ b/docs/roadmap.html @@ -4,7 +4,7 @@ Roadmap | Serverpod - + diff --git a/docs/support.html b/docs/support.html index dc0683efa..d5c6a157d 100644 --- a/docs/support.html +++ b/docs/support.html @@ -4,7 +4,7 @@ Support & community | Serverpod - + diff --git a/docs/tutorials/authentication.html b/docs/tutorials/authentication.html index 47f11cca0..78d6558d7 100644 --- a/docs/tutorials/authentication.html +++ b/docs/tutorials/authentication.html @@ -4,7 +4,7 @@ Authentication | Serverpod - + diff --git a/docs/tutorials/code-example.html b/docs/tutorials/code-example.html index 0a020c110..044ad6e23 100644 --- a/docs/tutorials/code-example.html +++ b/docs/tutorials/code-example.html @@ -4,7 +4,7 @@ Code examples | Serverpod - + diff --git a/docs/tutorials/first-app.html b/docs/tutorials/first-app.html index 16c02181e..7847b3dd2 100644 --- a/docs/tutorials/first-app.html +++ b/docs/tutorials/first-app.html @@ -4,7 +4,7 @@ Build your first app | Serverpod - + diff --git a/docs/tutorials/videos.html b/docs/tutorials/videos.html index 1da081f30..a0a47dabe 100644 --- a/docs/tutorials/videos.html +++ b/docs/tutorials/videos.html @@ -4,7 +4,7 @@ Videos | Serverpod - + diff --git a/docs/upgrading/upgrade-to-one-point-two.html b/docs/upgrading/upgrade-to-one-point-two.html index e7aae777d..cc35fdadd 100644 --- a/docs/upgrading/upgrade-to-one-point-two.html +++ b/docs/upgrading/upgrade-to-one-point-two.html @@ -4,7 +4,7 @@ Upgrade to 1.2 | Serverpod - +