Moves abstypes content into manual.

This commit is contained in:
Grzegorz Adam Hankiewicz 2014-05-11 09:58:44 +02:00
commit a16f762ce2
2 changed files with 65 additions and 152 deletions

View file

@ -1542,6 +1542,10 @@ of a distinct type that it **does not** imply a subtype relation between it
and its base type. Explicit type conversions from a distinct type to its
base type and vice versa are allowed.
Modelling currencies
~~~~~~~~~~~~~~~~~~~~
A distinct type can be used to model different physical `units`:idx: with a
numerical base type, for example. The following example models currencies.
@ -1649,6 +1653,67 @@ certain builtin operations to be lifted:
Currently only the dot accessor can be borrowed in this way.
Avoiding SQL injection attacks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
An SQL statement that is passed from Nimrod to an SQL database might be
modelled as a string. However, using string templates and filling in the
values is vulnerable to the famous `SQL injection attack`:idx:\:
.. code-block:: nimrod
import strutils
proc query(db: TDbHandle, statement: string) = ...
var
username: string
db.query("SELECT FROM users WHERE name = '$1'" % username)
# Horrible security hole, but the compiler does not mind!
This can be avoided by distinguishing strings that contain SQL from strings
that don't. Distinct types provide a means to introduce a new string type
``TSQL`` that is incompatible with ``string``:
.. code-block:: nimrod
type
TSQL = distinct string
proc query(db: TDbHandle, statement: TSQL) = ...
var
username: string
db.query("SELECT FROM users WHERE name = '$1'" % username)
# Error at compile time: `query` expects an SQL string!
It is an essential property of abstract types that they **do not** imply a
subtype relation between the abtract type and its base type. Explict type
conversions from ``string`` to ``TSQL`` are allowed:
.. code-block:: nimrod
import strutils, sequtils
proc properQuote(s: string): TSQL =
# quotes a string properly for an SQL statement
return TSQL(s)
proc `%` (frmt: TSQL, values: openarray[string]): TSQL =
# quote each argument:
let v = values.mapIt(TSQL, properQuote(it))
# we need a temporary type for the type conversion :-(
type TStrSeq = seq[string]
# call strutils.`%`:
result = TSQL(string(frmt) % TStrSeq(v))
db.query("SELECT FROM users WHERE name = '$1'".TSQL % [username])
Now we have compile-time checking against SQL injection attacks. Since
``"".TSQL`` is transformed to ``TSQL("")`` no new syntax is needed for nice
looking ``TSQL`` string literals. The hypothetical ``TSQL`` type actually
exists in the library as the `TSqlQuery type <db_sqlite.html#TSqlQuery>`_ of
modules like `db_sqlite <db_sqlite.html>`_.
Void type