# Functional Data Manipulation Language (FDML)

The functional data manipulation interface provided by &clsql; includes functions for inserting, updating and deleting records in existing database tables and executing SQL queries and statements with the results of queries returned as Lisp types. SQL statements expressed as strings may be executed with the `query` and `execute-command` functions. The `select` function, on the other hand, allows for the construction of queries in Lisp using the symbolic SQL syntax. Finally, iterative manipulation of query results is supported by `do-query`, `map-query` and an extended clause for the `loop` macro.

*CACHE-TABLE-QUERIES-DEFAULT*

*CACHE-TABLE-QUERIES-DEFAULT*

Specifies the default behaviour for caching of attribute types.

Variable

### Value Type

A valid argument to the `action` parameter of `cache-table-queries`, i.e. one of

- &t;
- &nil;
- :flush

.

### Initial Value

nil

### Description

Specifies the default behaivour for caching of attribute types. Meaningful values are &t;, &nil; and :flush as described for the `action` argument to `cache-table-queries`.

### Examples

None.

### Affected By

None.

### See Also

- `cache-table-queries`

### Notes

None.

CACHE-TABLE-QUERIES

CACHE-TABLE-QUERIES

Control the caching of table attribute types.

Function

### Syntax

          cache-table-queries table &key action database =>

### Arguments and Values

`table`

- A string representing a database table, &t; or :default.

`action`

- &t;, &nil; or :flush.

`database`

- A database object. This will default to the value of *default-database*.

### Description

Controls the caching of attribute type information on the table specified by `table` in `database` which defaults to *default-database*. `action` specifies the caching behaviour to adopt. If its value is &t; then attribute type information is cached whereas if its value is &nil; then attribute type information is not cached. If `action` is :flush then all existing type information in the cache for `table` is removed, but caching is still enabled. `table` may be a string representing a table for which the caching action is to be taken while the caching action is applied to all tables if `table` is &t;. Alternatively, when `table` is :default, the default caching action specified by *cache-table-queries-default* is applied to all tables for which a caching action has not been explicitly set.

### Examples

    (setf *cache-table-queries-default* t)
    => T
    (create-table [foo]
                  '(([id] integer)
                    ([height] float)
                    ([name] (string 24))
                    ([comments] varchar)))
    =>
    (cache-table-queries "foo")
    =>
    (list-attribute-types "foo")
    => (("id" :INT4 4 NIL 1) ("height" :FLOAT8 8 NIL 1) ("name" :BPCHAR 24 NIL 1)
        ("comments" :VARCHAR 255 NIL 1))
    (drop-table "foo")
    =>
    (create-table [foo]
                  '(([id] integer)
                    ([height] float)
                    ([name] (string 36))
                    ([comments] (string 100))))
    =>
    (cache-table-queries "foo" :action :flush)
    =>
    (list-attribute-types "foo")
    => (("id" :INT4 4 NIL 1) ("height" :FLOAT8 8 NIL 1) ("name" :BPCHAR 36 NIL 1)
        ("comments" :BPCHAR 100 NIL 1))

### Side Effects

The internal attribute cache for `database` is modified.

### Affected by

- *cache-table-queries-default*

### Exceptional Situations

None.

### See Also

- *cache-table-queries-default*

### Notes

None.

INSERT-RECORDS

INSERT-RECORDS

Insert tuples of data into a database table.

Function

### Syntax

          insert-records &key into attributes values av-pairs query database =>

### Arguments and Values

`into`

- A string, symbol or symbolic SQL expression representing the name of a table existing in `database`.

`attributes`

- A list of attribute identifiers or &nil;.

`values`

- A list of attribute values or &nil;.

`av-pairs`

- A list of attribute identifier/value pairs or &nil;.

`query`

- A query expression or &nil;.

`database`

- A database object. This will default to the value of *default-database*.

### Description

Inserts records into the table specified by `into` in `database` which defaults to *default-database*.

There are five ways of specifying the values inserted into each row. In the first `values` contains a list of values to insert and `attributes`, `av-pairs` and `query` are &nil;. This can be used when values are supplied for all attributes in `into`. In the second, `attributes` is a list of column names, `values` is a corresponding list of values and `av-pairs` and `query` are &nil;. In the third, `attributes`, `values` and `query` are &nil; and `av-pairs` is an alist of (attribute value) pairs. In the fourth, `values`, `av-pairs` and `attributes` are &nil; and `query` is a symbolic SQL query expression in which the selected columns also exist in `into`. In the fifth method, `values` and `av-pairs` are nil and `attributes` is a list of column names and `query` is a symbolic SQL query expression which returns values for the specified columns.

### Examples

    (select [first-name] [last-name] [email]
            :from [employee]
            :where [= [emplid] 11]
            :field-names nil)
    => NIL
    (insert-records :into [employee]
                    :attributes '(emplid groupid first_name last_name email
                                  ecompanyid managerid)
                    :values '(11 1 "Yuri" "Gagarin" "gagarin@soviet.org"
                              1 1))
    =>
    (select [first-name] [last-name] [email]
            :from [employee]
            :where [= [emplid] 11]
            :field-names nil)
    => (("Yuri" "Gagarin" "gagarin@soviet.org"))

### Side Effects

Modifications are made to the underlying database.

### Affected by

None.

### Exceptional Situations

An error of type sql-database-data-error is signalled if `table` is not an existing table in `database` or if the specified attributes are not found.

### See Also

- `update-records`
- `delete-records`

### Notes

None.

UPDATE-RECORDS

UPDATE-RECORDS

Updates the values of existing records.

Function

### Syntax

          update-records table &key  attributes values av-pairs where database =>

### Arguments and Values

`table`

- A string, symbol or symbolic SQL expression representing the name of a table existing in `database`.

`attributes`

- A list of attribute identifiers or &nil;.

`values`

- A list of attribute values or &nil;.

`av-pairs`

- A list of attribute identifier/value pairs or &nil;.

`where`

- A symbolic SQL expression.

`database`

- A database object. This will default to the value of *default-database*.

### Description

Updates the attribute values of existing records satsifying the SQL expression `where` in the table specified by `table` in `database` which defaults to *default-database*.

There are three ways of specifying the values to update for each row. In the first, `values` contains a list of values to use in the update and `attributes` and `av-pairs` are &nil;. This can be used when values are supplied for all attributes in `table`. In the second, `attributes` is a list of column names, `values` is a corresponding list of values and `av-pairs` is &nil;. In the third, `attributes` and `values` are &nil; and `av-pairs` is an alist of (attribute value) pairs.

### Examples

    (select [first-name] [last-name] [email]
            :from [employee]
            :where [= [emplid] 1]
            :field-names nil)
    => (("Vladimir" "Lenin" "lenin@soviet.org"))
    (update-records [employee]
                    :av-pairs'((first_name "Yuri")
                               (last_name "Gagarin")
                               (email "gagarin@soviet.org"))
                    :where [= [emplid] 1])
    =>
    (select [first-name] [last-name] [email]
            :from [employee]
            :where [= [emplid] 1]
            :field-names nil)
    => (("Yuri" "Gagarin" "gagarin@soviet.org"))

### Side Effects

Modifications are made to the underlying database.

### Affected by

None.

### Exceptional Situations

An error of type sql-database-data-error is signalled if `table` is not an existing table in `database`, if the specified attributes are not found or if the SQL statement resulting from the symbolic expression `where` does not return a Boolean value.

If the execution of the SQL query leads to any errors, an error of type sql-database-error is signalled.

### See Also

- `insert-records`
- `delete-records`

### Notes

None.

DELETE-RECORDS

DELETE-RECORDS

Delete records from a database table.

Function

### Syntax

          delete-records &key from where database =>

### Arguments and Values

`from`

- A string, symbol or symbolic SQL expression representing the name of a table existing in `database`.

`where`

- A symbolic SQL expression.

`database`

- A database object. This will default to the value of *default-database*.

### Description

Deletes records satisfying the SQL expression `where` from the table specified by `from` in `database` specifies a database which defaults to *default-database*.

### Examples

    (select [first-name] [last-name] [email]
            :from [employee]
            :where [= [emplid] 11]
            :field-names nil)
    => (("Yuri" "Gagarin" "gagarin@soviet.org"))
    (delete-records :from [employee] :where [= [emplid] 11])
    =>
    (select [first-name] [last-name] [email]
            :from [employee]
            :where [= [emplid] 11]
            :field-names nil)
    => NIL

### Side Effects

Modifications are made to the underlying database.

### Affected by

None.

### Exceptional Situations

An error of type sql-database-data-error is signalled if `from` is not an existing table in `database` or if the SQL statement resulting from the symbolic expression `where` does not return a Boolean value.

### See Also

- `insert-records`
- `update-records`

### Notes

None.

EXECUTE-COMMAND

EXECUTE-COMMAND

Execute an SQL command which returns no values.

Generic Function

### Syntax

          execute-command sql-expression &key database =>

### Arguments and Values

`sql-expression`

- An sql expression that represents an SQL statement which will return no values.

`database`

- A database object. This will default to the value of *default-database*.

### Description

Executes the SQL command `sql-expression`, which may be a symbolic SQL expression or a string representing any SQL statement apart from a query, on the supplied `database` which defaults to *default-database*.

### Examples

            (execute-command "create table eventlog (time char(30),event char(70))")
            =>

            (execute-command "create table eventlog (time char(30),event char(70))")
            >>
            >> While accessing database #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {480B2B6D}>
            >>   with expression "create table eventlog (time char(30),event char(70))":
            >>   Error NIL: ERROR:  amcreate: eventlog relation already exists
            >>   has occurred.
            >>
            >> Restarts:
            >>   0: [ABORT] Return to Top-Level.
            >>
            >> Debug  (type H for help)
            >>
            >> (CLSQL-POSTGRESQL::|(PCL::FAST-METHOD DATABASE-EXECUTE-COMMAND (T POSTGRESQL-DATABASE))|
            >>  #<unused-arg>
            >>  #<unused-arg>
            >>  #<unavailable-arg>
            >>  #<unavailable-arg>)
            >> Source: (ERROR 'SQL-DATABASE-ERROR :DATABASE DATABASE :EXPRESSION ...)
            >> 0] 0

            (execute-command "drop table eventlog")
            =>

### Side Effects

Whatever effects the execution of the SQL statement has on the underlying database, if any.

### Affected by

None.

### Exceptional Situations

If the execution of the SQL statement leads to any errors, an error of type sql-database-error is signalled.

### See Also

- `query`

### Notes

None.

QUERY

QUERY

Execute an SQL query and return the tuples as a list.

Generic Function

### Syntax

          query query-expression &key database result-types flatp field-names => result

### Arguments and Values

`query-expression`

- An sql expression that represents an SQL query which is expected to return a (possibly empty) result set.

`database`

- A database object. This will default to the value of *default-database*.

`flatp`

- A Boolean whose default value is &nil;.

`result-types`

- A field type specifier. The default is :auto;.

  The purpose of this argument is cause &clsql; to import SQL numeric fields into numeric Lisp objects rather than strings. This reduces the cost of allocating a temporary string and the &clsql; users' inconvenience of converting number strings into number objects.

  A value of :auto causes &clsql; to automatically convert SQL fields into a numeric format where applicable. The default value of &nil; causes all fields to be returned as strings regardless of the SQL type. Otherwise a list is expected which has a element for each field that specifies the conversion. Valid type identifiers are:

  - :int Field is imported as a signed integer, from 8-bits to 64-bits depending upon the field type.
  - :double Field is imported as a double-float number.
  - t Field is imported as a string.
  If the list is shorter than the number of fields, the a value of t is assumed for the field. If the list is longer than the number of fields, the extra elements are ignored.

`field-names`

- A boolean with a default value of &t;. When &t;, this function returns a second value of a list of field names. When &nil;, this function only returns one value - the list of rows.

result

- A list representing the result set obtained. For each tuple in the result set, there is an element in this list, which is itself a list of all the attribute values in the tuple.

### Description

Executes the SQL query expression `query-expression`, which may be an SQL expression or a string, on the supplied `database` which defaults to *default-database*. `result-types` is a list of symbols which specifies the lisp type for each field returned by `query-expression`.

If `result-types` is &nil; all results are returned as strings whereas the default value of :auto means that the lisp types are automatically computed for each field.

`field-names` is &t; by default which means that the second value returned is a list of strings representing the columns selected by `query-expression`. If `field-names` is &nil;, the list of column names is not returned as a second value.

`flatp` has a default value of &nil; which means that the results are returned as a list of lists.If FLATP is &t; and only one result is returned for each record selected by `query-expression`, the results are returned as elements of a list.

### Examples

    (query "select emplid,first_name,last_name,height from employee where emplid = 1")
    => ((1 "Vladimir" "Lenin" 1.5564661d0)),
       ("emplid" "first_name" "last_name" "height")

    (query "select emplid,first_name,last_name,height from employee where emplid = 1"
           :field-names nil)
    => ((1 "Vladimir" "Lenin" 1.5564661d0))

    (query "select emplid,first_name,last_name,height from employee where emplid = 1"
           :field-names nil
           :result-types nil)
    => (("1" "Vladimir" "Lenin" "1.5564661"))

    (query "select emplid,first_name,last_name,height from employee where emplid = 1"
           :field-names nil
           :result-types '(:int t t :double))
    => ((1 "Vladimir" "Lenin" 1.5564661))

    (query "select last_name from employee where emplid > 5" :flatp t)
    => ("Andropov" "Chernenko" "Gorbachev" "Yeltsin" "Putin"),
       ("last_name")

    (query "select last_name from employee where emplid > 10"
           :flatp t
           :field-names nil)
    => NIL

### Side Effects

Whatever effects the execution of the SQL query has on the underlying database, if any.

### Affected by

None.

### Exceptional Situations

If the execution of the SQL query leads to any errors, an error of type sql-database-error is signalled.

### See Also

- `execute-command`
- `print-query`
- `do-query`
- `map-query`
- `loop`
- `select`

### Notes

The `field-names` and `result-types` keyword arguments are a &clsql; extension.

PRINT-QUERY

PRINT-QUERY

Prints a tabular report of query results.

Function

### Syntax

          print-query query-expression &key titles formats sizes stream database =>

### Arguments and Values

`query-expression`

- An sql expression that represents an SQL query which is expected to return a (possibly empty) result set.

`database`

- A database object. This will default to the value of *default-database*.

`titles`

- A list of strings or &nil; which is the default value.

`formats`

- A list of strings, &nil; or &t; which is the default value.

`sizes`

- A list of numbers, &nil; or &t; which is the default value.

`stream`

- An output stream or &t; which is the default value.

### Description

Prints a tabular report of the results returned by the SQL query `query-expression`, which may be a symbolic SQL expression or a string, in `database` which defaults to *default-database*. The report is printed onto `stream` which has a default value of &t; which means that *standard-output* is used. The `title` argument, which defaults to &nil;, allows the specification of a list of strings to use as column titles in the tabular output. `sizes` accepts a list of column sizes, one for each column selected by `query-expression`, to use in formatting the tabular report. The default value of &t; means that minimum sizes are computed. `formats` is a list of format strings to be used for printing each column selected by `query-expression`. The default value of `formats` is &t; meaning that ~A is used to format all columns or ~VA if column sizes are used.

### Examples

    (print-query [select [emplid] [first-name] [last-name] [email]
                         :from [employee]
                         :where [< [emplid] 5]]
                  :titles '("ID" "FORENAME" "SURNAME" "EMAIL"))
    ID FORENAME SURNAME  EMAIL
    1  Vladimir Lenin    lenin@soviet.org
    2  Josef    Stalin   stalin@soviet.org
    3  Leon     Trotsky  trotsky@soviet.org
    4  Nikita   Kruschev kruschev@soviet.org
    =>

    (print-query "select emplid,first_name,last_name,email from employee where emplid >= 5"
                 :titles '("ID" "FORENAME" "SURNAME" "EMAIL"))
    ID FORENAME   SURNAME   EMAIL
    5  Leonid     Brezhnev  brezhnev@soviet.org
    6  Yuri       Andropov  andropov@soviet.org
    7  Konstantin Chernenko chernenko@soviet.org
    8  Mikhail    Gorbachev gorbachev@soviet.org
    9  Boris      Yeltsin   yeltsin@soviet.org
    10 Vladimir   Putin     putin@soviet.org
    =>

### Side Effects

None.

### Affected by

None.

### Exceptional Situations

If the execution of the SQL query leads to any errors, an error of type sql-database-error is signalled.

### See Also

- `query`
- `do-query`
- `map-query`
- `loop`
- `select`

### Notes

None.

SELECT

SELECT

Executes a query given the supplied constraints.

Function

### Syntax

          select &rest identifiers &key all distinct from group-by having limit offset order-by set-operation where result-types field-names flatp refresh caching database => result

### Arguments and Values

`identifiers`

- A set of sql expressions each of which indicates a column to query.

`all`

- A Boolean.

`distinct`

- A Boolean.

`from`

- One or more SQL expression representing tables.

`group-by`

- An SQL expression.

`having`

- An SQL expression.

`limit`

- A non-negative integer.

`offset`

- A non-negative integer.

`order-by`

- An SQL expression.

`set-operation`

- An SQL expression.

`where`

- An SQL expression.

`database`

- A database object. This will default to the value of *default-database*.

`flatp`

- A Boolean whose default value is &nil;.

`result-types`

- A field type specifier. The default is :auto.

  The purpose of this argument is cause &clsql; to import SQL numeric fields into numeric Lisp objects rather than strings. This reduces the cost of allocating a temporary string and the &clsql; users' inconvenience of converting number strings into number objects.

  A value of :auto causes &clsql; to automatically convert SQL fields into a numeric format where applicable. The default value of &nil; causes all fields to be returned as strings regardless of the SQL type. Otherwise a list is expected which has a element for each field that specifies the conversion. Valid type identifiers are:

  - :int Field is imported as a signed integer, from 8-bits to 64-bits depending upon the field type.
  - :double Field is imported as a double-float number.
  - t Field is imported as a string.
  If the list is shorter than the number of fields, the a value of t is assumed for the field. If the list is longer than the number of fields, the extra elements are ignored.

`field-names`

- A boolean with a default value of &t;. When &t;, this function returns a second value of a list of field names. When &nil;, this function only returns one value - the list of rows.

`refresh`

- This value is only considered when CLOS objects are being selected. A boolean with a default value of &nil;. When the value of the `caching` keyword is &t;, a second equivalent `select` call will return the same view class instance objects. When `refresh` is &t;, then slots of the existing instances are updated as necessary. In such cases, you may wish to override the hook `instance-refresh`.

`caching`

- This value is only considered when CLOS objects are being selected. A boolean with a default value of `*default-caching*`. &clsql; caches objects in accordance with the &commonsql; interface: a second equivalent `select` call will return the same view class instance objects.

`result`

- A list representing the result set obtained. For each tuple in the result set, there is an element in this list, which is itself a list of all the attribute values in the tuple.

### Description

Executes a query on `database`, which has a default value of *default-database*, specified by the SQL expressions supplied using the remaining arguments in `args`. The `select` function can be used to generate queries in both functional and object oriented contexts.

In the functional case, the required arguments specify the columns selected by the query and may be symbolic SQL expressions or strings representing attribute identifiers. Type modified identifiers indicate that the values selected from the specified column are converted to the specified lisp type. The keyword arguments `all`, `distinct`, `from`, `group-by`, `having`, `limit`, `offset`, `order-by`, `set-operation` and `where` are used to specify, using the symbolic SQL syntax, the corresponding components of the SQL query generated by the call to `select`.

`result-types` is a list of symbols which specifies the lisp type for each field returned by the query. If `result-types` is &nil; all results are returned as strings whereas the default value of :auto means that the lisp types are automatically computed for each field. `field-names` is &t; by default which means that the second value returned is a list of strings representing the columns selected by the query. If `field-names` is &nil;, the list of column names is not returned as a second value.

In the object oriented case, the required arguments to `select` are symbols denoting View Classes which specify the database tables to query. In this case, `select` returns a list of View Class instances whose slots are set from the attribute values of the records in the specified table. Slot-value is a legal operator which can be employed as part of the symbolic SQL syntax used in the `where` keyword argument to `select`. `refresh` is &nil; by default which means that the View Class instances returned are retrieved from a cache if an equivalent call to `select` has previously been issued. If `refresh` is true, the View Class instances returned are updated as necessary from the database and the generic function `instance-refreshed` is called to perform any necessary operations on the updated instances.

In both object oriented and functional contexts, `flatp` has a default value of &nil; which means that the results are returned as a list of lists. If `flatp` is t and only one result is returned for each record selected in the query, the results are returned as elements of a list.

### Examples

    (select [first-name] :from [employee] :flatp t :distinct t
                         :field-names nil
                         :result-types nil
                         :order-by [first-name])
    => ("Boris" "Josef" "Konstantin" "Leon" "Leonid" "Mikhail" "Nikita" "Vladimir"
        "Yuri")

    (select [first-name] [count [*]] :from [employee]
    	                         :result-types nil
    			         :group-by [first-name]
    			         :order-by [first-name]
    			         :field-names nil)
    => (("Boris" "1") ("Josef" "1") ("Konstantin" "1") ("Leon" "1") ("Leonid" "1")
        ("Mikhail" "1") ("Nikita" "1") ("Vladimir" "2") ("Yuri" "1"))

    (select [last-name] :from [employee]
                        :where [like [email] "%org"]
    		    :order-by [last-name]
    		    :field-names nil
    		    :result-types nil
    		    :flatp t)
    => ("Andropov" "Brezhnev" "Chernenko" "Gorbachev" "Kruschev" "Lenin" "Putin"
        "Stalin" "Trotsky" "Yeltsin")

    (select [max [emplid]] :from [employee]
                           :flatp t
    	               :field-names nil
                           :result-types :auto)
    => (10)

    (select [avg [height]] :from [employee] :flatp t :field-names nil)
    => (1.58999584d0)

    (select [emplid] [last-name] :from [employee] :where [= [emplid] 1])
    => ((1 "Lenin")),
       ("emplid" "last_name")

    (select [emplid :string] :from [employee]
                             :where [= 1 [emplid]]
                             :field-names nil
                             :flatp t)
    => ("1")

    (select [emplid] :from [employee] :order-by [emplid]
                     :where [not [between [* [emplid] 10] [* 5 10] [* 10 10]]]
                     :field-names nil
                     :flatp t)
    => (1 2 3 4)

    (select [emplid] :from [employee]
            :where [in [emplid] '(1 2 3 4)]
            :flatp t
            :order-by [emplid]
            :field-names nil)
    => (1 2 3 4)

    (select [emplid] :from [employee]
            :order-by [emplid]
            :limit 5
            :offset 3
            :field-names nil
            :flatp t)
    => (4 5 6 7 8)

    (select [first-name] [last-name] :from [employee]
            :field-names nil
            :order-by '(([first-name] :asc) ([last-name] :desc)))
    => (("Boris" "Yeltsin") ("Josef" "Stalin") ("Konstantin" "Chernenko")
        ("Leon" "Trotsky") ("Leonid" "Brezhnev") ("Mikhail" "Gorbachev")
        ("Nikita" "Kruschev") ("Vladimir" "Putin") ("Vladimir" "Lenin")
        ("Yuri" "Andropov"))

    (select [last-name] :from [employee]
                     :set-operation [union [select [first-name] :from [employee]
                                                   :order-by [last-name]]]
                     :flatp t
                     :result-types nil
                     :field-names nil)
    => ("Andropov" "Boris" "Brezhnev" "Chernenko" "Gorbachev" "Josef" "Konstantin"
        "Kruschev" "Lenin" "Leon" "Leonid" "Mikhail" "Nikita" "Putin" "Stalin"
        "Trotsky" "Vladimir" "Yeltsin" "Yuri")

### Side Effects

Whatever effects the execution of the SQL query has on the underlying database, if any.

### Affected by

None.

### Exceptional Situations

If the execution of the SQL query leads to any errors, an error of type sql-database-error is signalled.

### See Also

- `query`
- `print-query`
- `do-query`
- `map-query`
- `loop`
- `instance-refreshed`

### Notes

The `select` function is actually implemented in &clsql; with a single &rest parameter (which is subsequently destructured) rather than the keyword parameters presented here for the purposes of exposition. This means that incorrect or missing keywords or values may not trigger errors in the way that they would if `select` had been defined using keyword arguments.

The `field-names` and `result-types` keyword arguments are a &clsql; extension.

`select` is common across the functional and object-oriented data manipulation languages.

DO-QUERY

DO-QUERY

Iterate over all the tuples of a query.

Macro

### Syntax

          do-query ((&rest args) query-expression &key database result-types &body body => result

### Arguments and Values

`args`

- A list of variable names.

`query-expression`

- An sql expression that represents an SQL query which is expected to return a (possibly empty) result set, where each tuple has as many attributes as `function` takes arguments.

`database`

- A database object. This will default to *default-database*.

`result-types`

- A field type specifier. The default is &nil;. See `query` for the semantics of this argument.

`body`

- A body of Lisp code, like in a `destructuring-bind` form.

`result`

- The result of executing `body`.

### Description

Repeatedly executes `body` within a binding of `args` on the fields of each row selected by the SQL query `query-expression`, which may be a string or a symbolic SQL expression, in `database` which defaults to *default-database*.

The body of code is executed in a block named nil which may be returned from prematurely via `return` or `return-from`. In this case the result of evaluating the `do-query` form will be the one supplied to `return` or `return-from`. Otherwise the result will be nil.

The body of code appears also is if wrapped in a `destructuring-bind` form, thus allowing declarations at the start of the body, especially those pertaining to the bindings of the variables named in `args`.

`result-types` is a list of symbols which specifies the lisp type for each field returned by `query-expression`. If `result-types` is &nil; all results are returned as strings whereas the default value of :auto means that the lisp types are automatically computed for each field.

`query-expression` may be an object query (i.e., the selection arguments refer to View Classes), in which case `args` are bound to the tuples of View Class instances returned by the object oriented query.

### Examples

    (do-query ((salary name) "select salary,name from simple")
      (format t "~30A gets $~2,5$~%" name (read-from-string salary)))
    >> Mai, Pierre                    gets $10000.00
    >> Hacker, Random J.              gets $08000.50
    => NIL

    (do-query ((salary name) "select salary,name from simple")
      (return (cons salary name)))
    => ("10000.00" . "Mai, Pierre")

    (let ((result '()))
      (do-query ((name) [select [last-name] :from [employee]
                                :order-by [last-name]])
        (push name result))
      result)
    => ("Yeltsin" "Trotsky" "Stalin" "Putin" "Lenin" "Kruschev" "Gorbachev"
        "Chernenko" "Brezhnev" "Andropov")

    (let ((result '()))
      (do-query ((e) [select 'employee :order-by [last-name]])
        (push (slot-value e 'last-name) result))
      result)
    => ("Yeltsin" "Trotsky" "Stalin" "Putin" "Lenin" "Kruschev" "Gorbachev"
        "Chernenko" "Brezhnev" "Andropov")

### Side Effects

Whatever effects the execution of the SQL query has on the underlying database, if any.

### Affected by

None.

### Exceptional Situations

If the execution of the SQL query leads to any errors, an error of type sql-database-error is signalled.

If the number of variable names in `args` and the number of attributes in the tuples in the result set don't match up, an error is signalled.

### See Also

- `query`
- `map-query`
- `print-query`
- `loop`
- `select`

### Notes

The `result-types` keyword argument is a &clsql; extension.

`do-query` is common across the functional and object-oriented data manipulation languages.

LOOP

LOOP

Extension to Common Lisp `Loop` to iterate over all the tuples of a query via a loop clause.

Loop Clause

### Syntax

    {as | for} var [type-spec] being {each | the} {record | records | tuple | tuples} {in | of} query [from database]

### Arguments and Values

`var`

- A `d-var-spec`, as defined in the grammar for `loop`-clauses in the ANSI Standard for Common Lisp. This allows for the usual loop-style destructuring.

`type-spec`

- An optional `type-spec` either simple or destructured, as defined in the grammar for `loop`-clauses in the ANSI Standard for Common Lisp.

`query`

- An sql expression that represents an SQL query which is expected to return a (possibly empty) result set, where each tuple has as many attributes as `function` takes arguments.

`database`

- An optional database object. This will default to the value of *default-database*.

### Description

This clause is an iteration driver for `loop`, that binds the given variable (possibly destructured) to the consecutive tuples (which are represented as lists of attribute values) in the result set returned by executing the SQL `query` expression on the `database` specified.

`query` may be an object query (i.e., the selection arguments refer to View Classes), in which case the supplied variable is bound to the tuples of View Class instances returned by the object oriented query.

### Examples

    (defvar *my-db* (connect '("dent" "newesim" "dent" "dent"))
    "My database"
    => *MY-DB*
    (loop with time-graph = (make-hash-table :test #'equal)
       with event-graph = (make-hash-table :test #'equal)
       for (time event) being the tuples of "select time,event from log"
       from *my-db*
       do
         (incf (gethash time time-graph 0))
         (incf (gethash event event-graph 0))
       finally
         (flet ((show-graph (k v) (format t "~40A => ~5D~%" k v)))
           (format t "~&Time-Graph:~%===========~%")
           (maphash #'show-graph time-graph)
           (format t "~&~%Event-Graph:~%============~%")
           (maphash #'show-graph event-graph))
         (return (values time-graph event-graph)))
    >> Time-Graph:
    >> ===========
    >> D                                        => 53000
    >> X                                        =>     3
    >> test-me                                  =>  3000
    >>
    >> Event-Graph:
    >> ============
    >> CLOS Benchmark entry.                    =>  9000
    >> Demo Text...                             =>     3
    >> doit-text                                =>  3000
    >> C    Benchmark entry.                    => 12000
    >> CLOS Benchmark entry                     => 32000
    => #<EQUAL hash table, 3 entries {48350A1D}>
    => #<EQUAL hash table, 5 entries {48350FCD}>

    (loop for (forename surname)
          being each tuple in
            [select [first-name] [last-name] :from [employee]
                    :order-by [last-name]]
          collect (concatenate 'string forename " " surname))
    => ("Yuri Andropov" "Leonid Brezhnev" "Konstantin Chernenko" "Mikhail Gorbachev"
        "Nikita Kruschev" "Vladimir Lenin" "Vladimir Putin" "Josef Stalin"
        "Leon Trotsky" "Boris Yeltsin")

    (loop for (e) being the records in
         [select 'employee :where [< [emplid] 4] :order-by [emplid]]
      collect (slot-value e 'last-name))
    => ("Lenin" "Stalin" "Trotsky")

### Side Effects

Whatever effects the execution of the SQL query has on the underlying database, if any.

### Affected by

None.

### Exceptional Situations

If the execution of the SQL query leads to any errors, an error of type sql-database-error is signalled.

Otherwise, any of the exceptional situations of `loop` applies.

### See Also

- `query`
- `map-query`
- `do-query`
- `print-query`
- `select`

### Notes

The `database` loop keyword is a &clsql; extension.

The extended `loop` syntax is common across the functional and object-oriented data manipulation languages.

MAP-QUERY

MAP-QUERY

Map a function over all the tuples from a query

Function

### Syntax

    map-query output-type-spec function query-expression &key database result-types => result

### Arguments and Values

`output-type-spec`

- A sequence type specifier or nil.

`function`

- A function designator. `function` takes a single argument which is the atom value for a query single with a single column or is a list of values for a multi-column query.

`query-expression`

- An sql expression that represents an SQL query which is expected to return a (possibly empty) result set.

`database`

- A database object. This will default to the value of *default-database*.

`result-types`

- A field type specifier. The default is &nil;. See `query` for the semantics of this argument.

result

- If `output-type-spec` is a type specifier other than nil, then a sequence of the type it denotes. Otherwise nil is returned.

### Description

Applies `function` to the successive tuples in the result set returned by executing the SQL `query-expression`. If the `output-type-spec` is nil, then the result of each application of `function` is discarded, and `map-query` returns nil. Otherwise the result of each successive application of `function` is collected in a sequence of type `output-type-spec`, where the jths element is the result of applying `function` to the attributes of the jths tuple in the result set. The collected sequence is the result of the call to `map-query`.

If the `output-type-spec` is a subtype of `list`, the result will be a `list`.

If the `result-type` is a subtype of `vector`, then if the implementation can determine the element type specified for the `result-type`, the element type of the resulting array is the result of upgrading that element type; or, if the implementation can determine that the element type is unspecified (or *), the element type of the resulting array is `t`; otherwise, an error is signaled.

If `result-types` is &nil; all results are returned as strings whereas the default value of :auto means that the lisp types are automatically computed for each field.

`query-expression` may be an object query (i.e., the selection arguments refer to View Classes), in which case the supplied function is applied to the tuples of View Class instances returned by the object oriented query.

### Examples

    (map-query 'list #'(lambda (tuple)
                         (multiple-value-bind (salary name) tuple
                            (declare (ignorable name))
                            (read-from-string salary)))
                "select salary,name from simple where salary > 8000")
    => (10000.0 8000.5)

    (map-query '(vector double-float)
               #'(lambda (tuple)
                   (multiple-value-bind (salary name) tuple
                      (declare (ignorable name))
                      (let ((*read-default-float-format* 'double-float))
                        (coerce (read-from-string salary) 'double-float))
               "select salary,name from simple where salary > 8000")))
    => #(10000.0d0 8000.5d0)
    (type-of *)
    => (SIMPLE-ARRAY DOUBLE-FLOAT (2))

    (let (list)
      (values (map-query nil #'(lambda (tuple)
                                 (multiple-value-bind (salary name) tuple
                                   (push (cons name (read-from-string salary)) list))
                             "select salary,name from simple where salary > 8000"))
              list))
    => NIL
    => (("Hacker, Random J." . 8000.5) ("Mai, Pierre" . 10000.0))

    (map-query 'vector #'identity
               [select [last-name] :from [employee] :flatp t
                       :order-by [last-name]])
    => #("Andropov" "Brezhnev" "Chernenko" "Gorbachev" "Kruschev" "Lenin" "Putin"
         "Stalin" "Trotsky" "Yeltsin")

    (map-query 'list #'identity
               [select [first-name] [last-name] :from [employee]
                       :order-by [last-name]])
    => (("Yuri" "Andropov") ("Leonid" "Brezhnev") ("Konstantin" "Chernenko")
        ("Mikhail" "Gorbachev") ("Nikita" "Kruschev") ("Vladimir" "Lenin")
        ("Vladimir" "Putin") ("Josef" "Stalin") ("Leon" "Trotsky")
        ("Boris" "Yeltsin"))

    (map-query 'list #'last-name [select 'employee :order-by [emplid]])
    => ("Lenin" "Stalin" "Trotsky" "Kruschev" "Brezhnev" "Andropov" "Chernenko"
        "Gorbachev" "Yeltsin" "Putin")

### Side Effects

Whatever effects the execution of the SQL query has on the underlying database, if any.

### Affected by

None.

### Exceptional Situations

If the execution of the SQL query leads to any errors, an error of type sql-database-error is signalled.

An error of type type-error must be signaled if the `output-type-spec` is not a recognizable subtype of `list`, not a recognizable subtype of `vector`, and not nil.

An error of type type-error should be signaled if `output-type-spec` specifies the number of elements and the size of the result set is different from that number.

### See Also

- `query`
- `do-query`
- `print-query`
- `loop`
- `select`

### Notes

The `result-types` keyword argument is a &clsql; extension.

`map-query` is common across the functional and object-oriented data manipulation languages.