-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
574 additions
and
500 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,269 @@ | ||
<!DOCTYPE HTML> | ||
<html lang="en" class="light sidebar-visible" dir="ltr"> | ||
<head> | ||
<!-- Book generated using mdBook --> | ||
<meta charset="UTF-8"> | ||
<title>Data Sets - DORM - The Dry ORM</title> | ||
|
||
|
||
<!-- Custom HTML head --> | ||
|
||
<meta name="description" content=""> | ||
<meta name="viewport" content="width=device-width, initial-scale=1"> | ||
<meta name="theme-color" content="#ffffff"> | ||
|
||
<link rel="icon" href="favicon.svg"> | ||
<link rel="shortcut icon" href="favicon.png"> | ||
<link rel="stylesheet" href="css/variables.css"> | ||
<link rel="stylesheet" href="css/general.css"> | ||
<link rel="stylesheet" href="css/chrome.css"> | ||
<link rel="stylesheet" href="css/print.css" media="print"> | ||
|
||
<!-- Fonts --> | ||
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css"> | ||
<link rel="stylesheet" href="fonts/fonts.css"> | ||
|
||
<!-- Highlight.js Stylesheets --> | ||
<link rel="stylesheet" href="highlight.css"> | ||
<link rel="stylesheet" href="tomorrow-night.css"> | ||
<link rel="stylesheet" href="ayu-highlight.css"> | ||
|
||
<!-- Custom theme stylesheets --> | ||
|
||
|
||
<!-- Provide site root to javascript --> | ||
<script> | ||
var path_to_root = ""; | ||
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light"; | ||
</script> | ||
<!-- Start loading toc.js asap --> | ||
<script src="toc.js"></script> | ||
</head> | ||
<body> | ||
<div id="body-container"> | ||
<!-- Work around some values being stored in localStorage wrapped in quotes --> | ||
<script> | ||
try { | ||
var theme = localStorage.getItem('mdbook-theme'); | ||
var sidebar = localStorage.getItem('mdbook-sidebar'); | ||
|
||
if (theme.startsWith('"') && theme.endsWith('"')) { | ||
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1)); | ||
} | ||
|
||
if (sidebar.startsWith('"') && sidebar.endsWith('"')) { | ||
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1)); | ||
} | ||
} catch (e) { } | ||
</script> | ||
|
||
<!-- Set the theme before any content is loaded, prevents flash --> | ||
<script> | ||
var theme; | ||
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { } | ||
if (theme === null || theme === undefined) { theme = default_theme; } | ||
const html = document.documentElement; | ||
html.classList.remove('light') | ||
html.classList.add(theme); | ||
html.classList.add("js"); | ||
</script> | ||
|
||
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden"> | ||
|
||
<!-- Hide / unhide sidebar before it is displayed --> | ||
<script> | ||
var sidebar = null; | ||
var sidebar_toggle = document.getElementById("sidebar-toggle-anchor"); | ||
if (document.body.clientWidth >= 1080) { | ||
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { } | ||
sidebar = sidebar || 'visible'; | ||
} else { | ||
sidebar = 'hidden'; | ||
} | ||
sidebar_toggle.checked = sidebar === 'visible'; | ||
html.classList.remove('sidebar-visible'); | ||
html.classList.add("sidebar-" + sidebar); | ||
</script> | ||
|
||
<nav id="sidebar" class="sidebar" aria-label="Table of contents"> | ||
<!-- populated by js --> | ||
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox> | ||
<noscript> | ||
<iframe class="sidebar-iframe-outer" src="toc.html"></iframe> | ||
</noscript> | ||
<div id="sidebar-resize-handle" class="sidebar-resize-handle"> | ||
<div class="sidebar-resize-indicator"></div> | ||
</div> | ||
</nav> | ||
|
||
<div id="page-wrapper" class="page-wrapper"> | ||
|
||
<div class="page"> | ||
<div id="menu-bar-hover-placeholder"></div> | ||
<div id="menu-bar" class="menu-bar sticky"> | ||
<div class="left-buttons"> | ||
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar"> | ||
<i class="fa fa-bars"></i> | ||
</label> | ||
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list"> | ||
<i class="fa fa-paint-brush"></i> | ||
</button> | ||
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu"> | ||
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li> | ||
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li> | ||
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li> | ||
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li> | ||
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li> | ||
</ul> | ||
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar"> | ||
<i class="fa fa-search"></i> | ||
</button> | ||
</div> | ||
|
||
<h1 class="menu-title">DORM - The Dry ORM</h1> | ||
|
||
<div class="right-buttons"> | ||
<a href="print.html" title="Print this book" aria-label="Print this book"> | ||
<i id="print-button" class="fa fa-print"></i> | ||
</a> | ||
|
||
</div> | ||
</div> | ||
|
||
<div id="search-wrapper" class="hidden"> | ||
<form id="searchbar-outer" class="searchbar-outer"> | ||
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header"> | ||
</form> | ||
<div id="searchresults-outer" class="searchresults-outer hidden"> | ||
<div id="searchresults-header" class="searchresults-header"></div> | ||
<ul id="searchresults"> | ||
</ul> | ||
</div> | ||
</div> | ||
|
||
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM --> | ||
<script> | ||
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible'); | ||
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible'); | ||
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) { | ||
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1); | ||
}); | ||
</script> | ||
|
||
<div id="content" class="content"> | ||
<main> | ||
<h1 id="data-sets"><a class="header" href="#data-sets">Data Sets</a></h1> | ||
<p>Most of Rust apps operate with data which is readily available in memory. Business apps | ||
are stateless, loading too much data is an anti-pattern.</p> | ||
<p>Depending of the capabilities of the underlying data storage layer, you should look to | ||
create as many requests and retrieve as little data as possible.</p> | ||
<p><code>DataSet</code> is is a representation of collection of records - stored remotely.</p> | ||
<h2 id="readabledataset-and-writabledataset"><a class="header" href="#readabledataset-and-writabledataset">ReadableDataSet and WritableDataSet</a></h2> | ||
<p>DORM provides two traits: <code>ReadableDataSet</code> and <code>WritableDataSet</code>. DORM also provides | ||
several implementations of these traits:</p> | ||
<ul> | ||
<li><code>sql::Table</code> - implements both <code>ReadableDataSet</code> and <code>WritableDataSet</code>.</li> | ||
<li><code>sql::Query</code> - implements <code>ReadableDataSet</code> only.</li> | ||
</ul> | ||
<p>Design of DORM allow you to extend those into NoSQL (like MongoDB or GraphQL sources) | ||
as well as custom RestAPI sources. Those extensions do not need to be part of DORM, | ||
they can be implemented as separate crates.</p> | ||
<h2 id="operating-with-data-sets"><a class="header" href="#operating-with-data-sets">Operating with Data sets</a></h2> | ||
<p>At the very basic level - you can iterate through a readable data set.</p> | ||
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)] | ||
</span><span class="boring">fn main() { | ||
</span>let set_of_clients = Client::table(); | ||
|
||
for client in set_of_clients.get().await? { | ||
println!("{}", client.name); | ||
} | ||
<span class="boring">}</span></code></pre></pre> | ||
<p>But quite often the advanced persistence layer could allow us to do much more. DORM approach is | ||
to provide ways how one Data Set can yield a different Data Set. Here are some examples:</p> | ||
<ul> | ||
<li>Get a set containing subset of records - by filtering.</li> | ||
<li>Converting <code>sql::table</code> into <code>sql::query</code> for further manipulation.</li> | ||
<li>Execute operation over set, such as calculate sum of a field from all records, or create comma-separated list of values.</li> | ||
<li>Modify or delete multiple records.</li> | ||
</ul> | ||
<p>DORM prefers to off-load operation execution to the persistence layer, but because this may increase | ||
complexity, DORM also provides a way to abstract this complexity away.</p> | ||
<h3 id="example---lazy-expression-fields"><a class="header" href="#example---lazy-expression-fields">Example - Lazy expression fields</a></h3> | ||
<p>In our introduction example, we came across an aggregate field: <code>total</code>:</p> | ||
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)] | ||
</span><span class="boring">fn main() { | ||
</span>table | ||
.has_many("line_items", "order_id", || Box::new(LineItem::table())) | ||
.with_expression("total", |t| { | ||
let item = t.sub_line_items(); | ||
item.sum(item.total()).render_chunk() | ||
}) | ||
<span class="boring">}</span></code></pre></pre> | ||
<p>Lets examine more generally what is happening here. Use of <code>has_many</code> creates</p> | ||
<p>This is a very simple example of a lazy expression field. It is a field that is calculated | ||
by a closure. The closure is passed a reference to the table. The closure can then use | ||
the table to create a new field.</p> | ||
<p>The above example is equivalent to this SQL:</p> | ||
<pre><code class="language-sql">SELECT id, | ||
(SELECT SUM((SELECT price FROM product WHERE id = product_id) * quantity) | ||
FROM order_line WHERE order_line.order_id = ord.id) AS total | ||
FROM ord | ||
</code></pre> | ||
<p>In this example, we are using a sub-query to calculate the total. The sub-query is | ||
created by calling <code>sub_line_items()</code> on the table. This method returns a new table | ||
that is a subset of the original table. The sub-query is then used to create a new | ||
field called <code>total</code> that is a sum of the price and quantity.</p> | ||
<p>The implementation | ||
of <code>sql::Table</code> however provides ability to create new Data Sets from existing ones.</p> | ||
|
||
</main> | ||
|
||
<nav class="nav-wrapper" aria-label="Page navigation"> | ||
<!-- Mobile navigation buttons --> | ||
<a rel="prev" href="introduction.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left"> | ||
<i class="fa fa-angle-left"></i> | ||
</a> | ||
|
||
<a rel="next prefetch" href="1-table-and-fields.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right"> | ||
<i class="fa fa-angle-right"></i> | ||
</a> | ||
|
||
<div style="clear: both"></div> | ||
</nav> | ||
</div> | ||
</div> | ||
|
||
<nav class="nav-wide-wrapper" aria-label="Page navigation"> | ||
<a rel="prev" href="introduction.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left"> | ||
<i class="fa fa-angle-left"></i> | ||
</a> | ||
|
||
<a rel="next prefetch" href="1-table-and-fields.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right"> | ||
<i class="fa fa-angle-right"></i> | ||
</a> | ||
</nav> | ||
|
||
</div> | ||
|
||
|
||
|
||
|
||
<script> | ||
window.playground_copyable = true; | ||
</script> | ||
|
||
|
||
<script src="elasticlunr.min.js"></script> | ||
<script src="mark.min.js"></script> | ||
<script src="searcher.js"></script> | ||
|
||
<script src="clipboard.min.js"></script> | ||
<script src="highlight.js"></script> | ||
<script src="book.js"></script> | ||
|
||
<!-- Custom JS scripts --> | ||
|
||
|
||
</div> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.