docs.datacontroller.io/macros/index.html
2023-05-17 10:41:48 +00:00

1158 lines
28 KiB
HTML

<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="Data Controller comes with a battle tested macro library supporting multiple load types and target databases.">
<link rel="canonical" href="https://docs.datacontroller.io/macros/">
<link rel="shortcut icon" href="../img/favicon.ico">
<meta name="generator" content="mkdocs-1.1.2, mkdocs-material-6.1.0">
<title>Macros - Data Controller for SAS® Documentation</title>
<link rel="stylesheet" href="../assets/stylesheets/main.bc7e593a.min.css">
<link rel="stylesheet" href="../assets/stylesheets/palette.ab28b872.min.css">
<meta name="theme-color" content="#ffffff">
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,400i,700%7CUbuntu+Mono&display=fallback">
<style>body,input{font-family:"Open Sans",-apple-system,BlinkMacSystemFont,Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Ubuntu Mono",SFMono-Regular,Consolas,Menlo,monospace}</style>
<link rel="manifest" href="../manifest.webmanifest" crossorigin="use-credentials">
<link rel="stylesheet" href="../font-awesome.css">
<meta name="author" content="Allan Bowe">
<meta property="og:type" content="website" />
<meta property="og:title" content="Data Controller Macro Library">
<meta property="og:url" content="https://docs.datacontroller.io/macros/" />
<meta property='og:image' content="https://i.imgur.com/8iuEDQ9.png" />
<meta property="og:image:type" content="image/png" />
<meta property="og:description" content="Data Controller comes with a battle tested macro library supporting multiple load types and target databases." />
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function () {
var u = "https://analytics.4gl.io/";
_paq.push(['setTrackerUrl', u + 'matomo.php']);
_paq.push(['setSiteId', '4']);
var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0];
g.async = true; g.src = u + 'matomo.js'; s.parentNode.insertBefore(g, s);
})();
</script>
<!-- End Matomo Code -->
</head>
<body dir="ltr" data-md-color-scheme="" data-md-color-primary="white" data-md-color-accent="amber">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#data-controller-macros" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header" data-md-component="header">
<nav class="md-header-nav md-grid" aria-label="Header">
<a href="https://docs.datacontroller.io" title="Data Controller for SAS® Documentation" class="md-header-nav__button md-logo" aria-label="Data Controller for SAS® Documentation">
<img src="../img/favicon.ico" alt="logo">
</a>
<label class="md-header-nav__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2z"/></svg>
</label>
<div class="md-header-nav__title" data-md-component="header-title">
<div class="md-header-nav__ellipsis">
<span class="md-header-nav__topic md-ellipsis">
Data Controller for SAS® Documentation
</span>
<span class="md-header-nav__topic md-ellipsis">
Macros
</span>
</div>
</div>
<label class="md-header-nav__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0116 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 019.5 16 6.5 6.5 0 013 9.5 6.5 6.5 0 019.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5z"/></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" data-md-state="active">
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0116 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 019.5 16 6.5 6.5 0 013 9.5 6.5 6.5 0 019.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12z"/></svg>
</label>
<button type="reset" class="md-search__icon md-icon" aria-label="Clear" data-md-component="search-reset" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/></svg>
</button>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list"></ol>
</div>
</div>
</div>
</div>
</div>
<div class="md-header-nav__source">
<a href="https://github.com/datacontroller/dcdocs.github.io/" title="Go to repository" class="md-source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M439.55 236.05L244 40.45a28.87 28.87 0 00-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 01-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 000 40.81l195.61 195.6a28.86 28.86 0 0040.8 0l194.69-194.69a28.86 28.86 0 000-40.81z"/></svg>
</div>
<div class="md-source__repository">
datacontroller/dcdocs.github.io
</div>
</a>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="navigation">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href="https://docs.datacontroller.io" title="Data Controller for SAS® Documentation" class="md-nav__button md-logo" aria-label="Data Controller for SAS® Documentation">
<img src="../img/favicon.ico" alt="logo">
</a>
Data Controller for SAS® Documentation
</label>
<div class="md-nav__source">
<a href="https://github.com/datacontroller/dcdocs.github.io/" title="Go to repository" class="md-source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M439.55 236.05L244 40.45a28.87 28.87 0 00-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 01-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 000 40.81l195.61 195.6a28.86 28.86 0 0040.8 0l194.69-194.69a28.86 28.86 0 000-40.81z"/></svg>
</div>
<div class="md-source__repository">
datacontroller/dcdocs.github.io
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." class="md-nav__link">
Home
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle" data-md-toggle="nav-2" type="checkbox" id="nav-2">
<label class="md-nav__link" for="nav-2">
User Guide
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" aria-label="User Guide" data-md-level="1">
<label class="md-nav__title" for="nav-2">
<span class="md-nav__icon md-icon"></span>
User Guide
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../dc-overview/" class="md-nav__link">
Overview
</a>
</li>
<li class="md-nav__item">
<a href="../dc-userguide/" class="md-nav__link">
DC User Guide
</a>
</li>
<li class="md-nav__item">
<a href="../dcu-datacatalog/" class="md-nav__link">
Data Catalog
</a>
</li>
<li class="md-nav__item">
<a href="../dcu-lineage/" class="md-nav__link">
Data Lineage
</a>
</li>
<li class="md-nav__item">
<a href="../dcu-fileupload/" class="md-nav__link">
File Uploads
</a>
</li>
<li class="md-nav__item">
<a href="../filter/" class="md-nav__link">
Filter Mechanism
</a>
</li>
<li class="md-nav__item">
<a href="../locking-mechanism/" class="md-nav__link">
Locking Mechanism
</a>
</li>
<li class="md-nav__item">
<a href="../dcu-tableviewer/" class="md-nav__link">
Table Viewer
</a>
</li>
<li class="md-nav__item">
<a href="../viewboxes/" class="md-nav__link">
ViewBoxes
</a>
</li>
<li class="md-nav__item">
<a href="../admin-services/" class="md-nav__link">
Admin Services
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle" data-md-toggle="nav-3" type="checkbox" id="nav-3">
<label class="md-nav__link" for="nav-3">
Table Guide
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" aria-label="Table Guide" data-md-level="1">
<label class="md-nav__title" for="nav-3">
<span class="md-nav__icon md-icon"></span>
Table Guide
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../tables/mpe_audit/" class="md-nav__link">
MPE_AUDIT
</a>
</li>
<li class="md-nav__item">
<a href="../tables/mpe_column_level_security/" class="md-nav__link">
MPE_COLUMN_LEVEL_SECURITY
</a>
</li>
<li class="md-nav__item">
<a href="../tables/mpe_config/" class="md-nav__link">
MPE_CONFIG
</a>
</li>
<li class="md-nav__item">
<a href="../tables/mpe_datacatalog_libs/" class="md-nav__link">
MPE_DATACATALOG_LIBS
</a>
</li>
<li class="md-nav__item">
<a href="../tables/mpe_datacatalog_tabs/" class="md-nav__link">
MPE_DATACATALOG_TABS
</a>
</li>
<li class="md-nav__item">
<a href="../tables/mpe_datacatalog_vars/" class="md-nav__link">
MPE_DATACATALOG_VARS
</a>
</li>
<li class="md-nav__item">
<a href="../tables/mpe_datastatus_libs/" class="md-nav__link">
MPE_DATASTATUS_LIBS
</a>
</li>
<li class="md-nav__item">
<a href="../tables/mpe_datastatus_tabs/" class="md-nav__link">
MPE_DATASTATUS_TABS
</a>
</li>
<li class="md-nav__item">
<a href="../tables/mpe_lockanytable/" class="md-nav__link">
MPE_LOCKANYTABLE
</a>
</li>
<li class="md-nav__item">
<a href="../tables/mpe_review/" class="md-nav__link">
MPE_REVIEW
</a>
</li>
<li class="md-nav__item">
<a href="../tables/mpe_submit/" class="md-nav__link">
MPE_SUBMIT
</a>
</li>
<li class="md-nav__item">
<a href="../tables/mpe_tables/" class="md-nav__link">
MPE_TABLES
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle" data-md-toggle="nav-4" type="checkbox" id="nav-4">
<label class="md-nav__link" for="nav-4">
Configuration
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" aria-label="Configuration" data-md-level="1">
<label class="md-nav__title" for="nav-4">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../column-level-security/" class="md-nav__link">
Column Level Security
</a>
</li>
<li class="md-nav__item">
<a href="../dcc-dates/" class="md-nav__link">
Dates / Datetimes
</a>
</li>
<li class="md-nav__item">
<a href="../dynamic-cell-dropdown/" class="md-nav__link">
Dynamic Cell Dropdown
</a>
</li>
<li class="md-nav__item">
<a href="../emails/" class="md-nav__link">
Emails
</a>
</li>
<li class="md-nav__item">
<a href="../excel/" class="md-nav__link">
Excel Formulas
</a>
</li>
<li class="md-nav__item">
<a href="../formats/" class="md-nav__link">
Formats
</a>
</li>
<li class="md-nav__item">
<a href="../dcc-groups/" class="md-nav__link">
Groups
</a>
</li>
<li class="md-nav__item">
<a href="../libraries/" class="md-nav__link">
Libraries
</a>
</li>
<li class="md-nav__item">
<a href="../dcc-options/" class="md-nav__link">
Options
</a>
</li>
<li class="md-nav__item">
<a href="../row-level-security/" class="md-nav__link">
Row Level Security
</a>
</li>
<li class="md-nav__item">
<a href="../dcc-security/" class="md-nav__link">
Security
</a>
</li>
<li class="md-nav__item">
<a href="../dcc-selectbox/" class="md-nav__link">
Selectboxes
</a>
</li>
<li class="md-nav__item">
<a href="../dcc-tables/" class="md-nav__link">
Tables
</a>
</li>
<li class="md-nav__item">
<a href="../dcc-validations/" class="md-nav__link">
Validations
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" type="checkbox" id="__toc">
<a href="./" class="md-nav__link md-nav__link--active">
Macros
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle" data-md-toggle="nav-6" type="checkbox" id="nav-6">
<label class="md-nav__link" for="nav-6">
Installation
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" aria-label="Installation" data-md-level="1">
<label class="md-nav__title" for="nav-6">
<span class="md-nav__icon md-icon"></span>
Installation
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../dci-requirements/" class="md-nav__link">
System Requirements
</a>
</li>
<li class="md-nav__item">
<a href="../dci-deploysasviya/" class="md-nav__link">
SAS Viya Deploy
</a>
</li>
<li class="md-nav__item">
<a href="../dci-deploysas9/" class="md-nav__link">
SAS 9 Deploy
</a>
</li>
<li class="md-nav__item">
<a href="../dci-stpinstance/" class="md-nav__link">
SAS 9 Dedicated STP
</a>
</li>
<li class="md-nav__item">
<a href="../dci-troubleshooting/" class="md-nav__link">
Troubleshooting
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle" data-md-toggle="nav-7" type="checkbox" id="nav-7">
<label class="md-nav__link" for="nav-7">
Legal
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" aria-label="Legal" data-md-level="1">
<label class="md-nav__title" for="nav-7">
<span class="md-nav__icon md-icon"></span>
Legal
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../privacy/" class="md-nav__link">
Privacy Policy
</a>
</li>
<li class="md-nav__item">
<a href="../evaluation-agreement/" class="md-nav__link">
Evaluation Licence
</a>
</li>
<li class="md-nav__item">
<a href="../licences/" class="md-nav__link">
Other Licences
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../videos/" class="md-nav__link">
Videos
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
<label class="md-nav__link" for="nav-9">
Roadmap
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" aria-label="Roadmap" data-md-level="1">
<label class="md-nav__title" for="nav-9">
<span class="md-nav__icon md-icon"></span>
Roadmap
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../roadmap/" class="md-nav__link">
Overview
</a>
</li>
<li class="md-nav__item">
<a href="../api/" class="md-nav__link">
DC API
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
</nav>
</div>
</div>
</div>
<div class="md-content">
<article class="md-content__inner md-typeset">
<a href="https://github.com/datacontroller/dcdocs.github.io/edit/master/docs/macros.md" title="Edit this page" class="md-content__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20.71 7.04c.39-.39.39-1.04 0-1.41l-2.34-2.34c-.37-.39-1.02-.39-1.41 0l-1.84 1.83 3.75 3.75M3 17.25V21h3.75L17.81 9.93l-3.75-3.75L3 17.25z"/></svg>
</a>
<h1 id="data-controller-macros">Data Controller Macros<a class="headerlink" href="#data-controller-macros" title="Permanent link">&para;</a></h1>
<p>"Under the hood" of Data Controller, SAS Macros are used for dynamic loading of all kinds of data thanks to the SAS ACCESS engines, including (but not limited to):</p>
<ul>
<li>Base (v9)</li>
<li>SPDE</li>
<li>CAS</li>
<li>TERADATA</li>
<li>POSTGRES</li>
<li>NETEZZA</li>
<li>ORACLE</li>
<li>REDSHIFT</li>
<li>OLEDB</li>
</ul>
<p>Native pass through is also available for optimised data loads in the following engines:</p>
<ul>
<li>Microsoft SQL SERVER</li>
<li>Amazon REDSHIFT</li>
<li>PostgreSQL</li>
</ul>
<p>The macros work dynamically, taking data types / lengths etc from the table metadata at runtime. Data Controller macros are available for unlimited (internal) use by licenced customers. They are currently in use, in production, in dozens of SAS environments globally and have been battle tested on large data volumes as well as some more esoteric gotchas such as:</p>
<ul>
<li>Short numerics</li>
<li>WLATIN1 vs UTF-8</li>
<li>High numerical precision</li>
<li>Long strings</li>
<li>High column volume</li>
<li>New data types in CAS (Type 6 as well as 1 &amp; 2)</li>
</ul>
<p>Multiple load types are supported (full REPLACE, regular UPDATE, SCD2 loads, even BITEMPORAL). Composite keys are of course possible, so are retained keys (and the max key value can be table or data driven). Keys are taken from the staging table, so they could be based on an md5 hash, a UUID, or whatever you choose. It just needs to fit within the constraints of a SAS data step (so, max 32767 width for a character variable, 8 bytes numerical precision).</p>
<p>A column (eg PROCESSED_DTTM) may be nominated to retain the current timestamp when doing any type of upload.</p>
<p>If the stage table has columns that are not in the base table, the extra columns are ignored. If the base table has columns that are not in the stage table, the process aborts.</p>
<p>There is also a <a href="/locking-mechanism/">locking mechanism</a> to avoid conflict where multiple users (or jobs) are trying to load the same table at the same time. If the loader cannot get a lock, it will keep trying for a configurable amount of time, until it does.</p>
<p>In the process of data discovery and comparing the hashes of the data values there are checks at every step of the way - the macro will abort if there are any WARNINGs or ERRORs or anything else awry. Some of these checks may be turned off for performance (eg the check for uniqueness of the business key in the staging table).</p>
<p>All dataloads are tracked in an output table, which shows the the number of observations added / modified / deleted, as well as the user identity performing the load, the timestamp, the library / table being loaded, and a descriptive (user provided) message for the load.</p>
<p><img alt="DC Loader results" src="https://i.imgur.com/2GFPxPF.png" /></p>
<p>The macros are fully documented with Doxygen, similar to the SASjs <a href="https://core.sasjs.io">Macro Core Library</a>.</p>
<p>The minimum amount of information needed to load a table is:</p>
<ul>
<li>Staging Library (default WORK)</li>
<li>Staging Table</li>
<li>Base Library</li>
<li>Base Table</li>
<li>Business Key fields</li>
<li>Load Type</li>
</ul>
<p>An invocation of the loader macro might look something like this:</p>
<p><img alt="SAS Loader" src="https://i.imgur.com/Hzca1WG.png" /></p>
<p>A single (one year) subscription to data controller provides perpetual usage of the macros. Contact <a href="https://www.linkedin.com/in/allanbowe">Allan Bowe</a> for pricing details.</p>
</article>
</div>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-nav">
<nav class="md-footer-nav__inner md-grid" aria-label="Footer">
<a href="../dcc-validations/" class="md-footer-nav__link md-footer-nav__link--prev" rel="prev">
<div class="md-footer-nav__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12z"/></svg>
</div>
<div class="md-footer-nav__title">
<div class="md-ellipsis">
<span class="md-footer-nav__direction">
Previous
</span>
Validations
</div>
</div>
</a>
<a href="../dci-requirements/" class="md-footer-nav__link md-footer-nav__link--next" rel="next">
<div class="md-footer-nav__title">
<div class="md-ellipsis">
<span class="md-footer-nav__direction">
Next
</span>
System Requirements
</div>
</div>
<div class="md-footer-nav__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4z"/></svg>
</div>
</a>
</nav>
</div>
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-footer-copyright">
<div class="md-footer-copyright__highlight">
All rights reserved &copy;2022 Bowe IO Ltd.
</div>
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
</div>
</div>
</footer>
</div>
<script src="../assets/javascripts/vendor.6a3d08fc.min.js"></script>
<script src="../assets/javascripts/bundle.71201edf.min.js"></script><script id="__lang" type="application/json">{"clipboard.copy": "Copy to clipboard", "clipboard.copied": "Copied to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.placeholder": "Type to start searching", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.term.missing": "Missing"}</script>
<script>
app = initialize({
base: "..",
features: [],
search: Object.assign({
worker: "../assets/javascripts/worker/search.4ac00218.min.js"
}, typeof search !== "undefined" && search)
})
</script>
</body>
</html>