From: Michael Wallner Date: Wed, 15 Oct 2014 12:35:23 +0000 (+0200) Subject: finish pq\Query X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=8ca926b19e417db747f046038909d818352b29a3;p=mdref%2Fmdref-pq-gateway finish pq\Query --- diff --git a/pq-gateway/pq/Query/AsyncExecutor.md b/pq-gateway/pq/Query/AsyncExecutor.md new file mode 100644 index 0000000..d7804d6 --- /dev/null +++ b/pq-gateway/pq/Query/AsyncExecutor.md @@ -0,0 +1,7 @@ +# class pq\Query\AsyncExecutor extends pq\Query\Executor + +An asynchronous query executor implementation. +See pq\Query\Executor for inherited methods and properties. + +> ***NOTE:*** + This asynchronous executor implementation depends on [React/Promise](https://github.com/reactphp/promise). diff --git a/pq-gateway/pq/Query/AsyncExecutor/execute.md b/pq-gateway/pq/Query/AsyncExecutor/execute.md new file mode 100644 index 0000000..29cbde9 --- /dev/null +++ b/pq-gateway/pq/Query/AsyncExecutor/execute.md @@ -0,0 +1,18 @@ +# Promise pq\Query\AsyncExecutor::execute(pq\Query\WriterInterface $query, callable $callback) + +Execute the query asynchronously and let the callback process the result on resolve. + +> ***NOTE:*** + This asynchronous executor implementation depends on [React/Promise](https://github.com/reactphp/promise). + +## Params: + +* pq\Query\Writer $query + The query to execute. +* callable $callback + The result processing callback as function(pq\Result $result) + +## Returns: + +* mixed, the return value of the callback. + diff --git a/pq-gateway/pq/Query/Executor.md b/pq-gateway/pq/Query/Executor.md new file mode 100644 index 0000000..f7ed021 --- /dev/null +++ b/pq-gateway/pq/Query/Executor.md @@ -0,0 +1,15 @@ +# class pq\Query\Executor implements pq\Query\ExecutorInterface + +A synchronous query executor implementation. + +## Properties: + +* protected pq\Connection $conn + The PostgreSQL connection. +* protected SplObjectStorage $observers + Attached observers. +* protected pq\Query\WriterInterface + The query being executed. +* protected pq\Result $result + The query result. + diff --git a/pq-gateway/pq/Query/Executor/__construct.md b/pq-gateway/pq/Query/Executor/__construct.md new file mode 100644 index 0000000..f54f2a5 --- /dev/null +++ b/pq-gateway/pq/Query/Executor/__construct.md @@ -0,0 +1,9 @@ +# void pq\Query\Executor::__construct(pq\Connection $conn) + +Create a new query executor. + +## Params: + +* pq\Connection $conn + The PostgreSQL connection to use. + diff --git a/pq-gateway/pq/Query/Executor/attach.md b/pq-gateway/pq/Query/Executor/attach.md new file mode 100644 index 0000000..41b7035 --- /dev/null +++ b/pq-gateway/pq/Query/Executor/attach.md @@ -0,0 +1,9 @@ +# void pq\Query\Executor::attach(SplObserver $observer) + +Implements SplSubject. +Attach a new observer. + +## Params: + +* SplObserver $observer + diff --git a/pq-gateway/pq/Query/Executor/detach.md b/pq-gateway/pq/Query/Executor/detach.md new file mode 100644 index 0000000..c389251 --- /dev/null +++ b/pq-gateway/pq/Query/Executor/detach.md @@ -0,0 +1,9 @@ +# void pq\Query\Executor::detach(SplObserver $observer) + +Implements SplSubject. +Detach an observer. + +## Params: + +* SplObserver $observer + An observer already attached. diff --git a/pq-gateway/pq/Query/Executor/execute.md b/pq-gateway/pq/Query/Executor/execute.md new file mode 100644 index 0000000..45a1837 --- /dev/null +++ b/pq-gateway/pq/Query/Executor/execute.md @@ -0,0 +1,15 @@ +# mixed pq\Query\Executor pq\Query\Executor::execute(\pq\Query\Writer $query, callable $callback); + +Execute the query and process the result with the callback. + +## Params: + +* pq\Query\Writer $query + The query to execute. +* callable $callback + The result processing callback as function(pq\Result $result) + +## Returns: + +* mixed, the return value of the callback. + diff --git a/pq-gateway/pq/Query/Executor/getConnection.md b/pq-gateway/pq/Query/Executor/getConnection.md new file mode 100644 index 0000000..f082774 --- /dev/null +++ b/pq-gateway/pq/Query/Executor/getConnection.md @@ -0,0 +1,11 @@ +# pq\Connection pq\Query\Executor::getConnection() + +Retrieve the coonection used by the executor. + +## Params: + +None. + +## Returns: + +* pq\Connection, the currently used connection. diff --git a/pq-gateway/pq/Query/Executor/getQuery.md b/pq-gateway/pq/Query/Executor/getQuery.md new file mode 100644 index 0000000..59a6ffa --- /dev/null +++ b/pq-gateway/pq/Query/Executor/getQuery.md @@ -0,0 +1,11 @@ +# pq\Query\Writer pq\Query\Executor::getQuery() + +Retrieve the current query. + +## Params: + +None. + +## Returns: + +* pq\Query\Writer, the current query to execute. diff --git a/pq-gateway/pq/Query/Executor/getResult.md b/pq-gateway/pq/Query/Executor/getResult.md new file mode 100644 index 0000000..85ac065 --- /dev/null +++ b/pq-gateway/pq/Query/Executor/getResult.md @@ -0,0 +1,11 @@ +# pq\Result pq\Query\Executor::getResult() + +Retrieve the result of the current query. + +## Params: + +None. + +## Returns: + +* pq\Result, the result of the current query. diff --git a/pq-gateway/pq/Query/Executor/notify.md b/pq-gateway/pq/Query/Executor/notify.md new file mode 100644 index 0000000..7c156a2 --- /dev/null +++ b/pq-gateway/pq/Query/Executor/notify.md @@ -0,0 +1,8 @@ +# void pq\Query\Executor::notify() + +Implements SplSubject. +Update all observers. + +## Params: + +None. diff --git a/pq-gateway/pq/Query/Executor/setConnection.md b/pq-gateway/pq/Query/Executor/setConnection.md new file mode 100644 index 0000000..4d08c74 --- /dev/null +++ b/pq-gateway/pq/Query/Executor/setConnection.md @@ -0,0 +1,12 @@ +# pq\Query\Executor pq\Query\Executor::setConnection(pq\Connection $conn) + +Set the connection the executor should use. + +## Params: + +* pq\Connection $conn + The connection to use. + +## Return: + +* pq\Query\Executor, self. diff --git a/pq-gateway/pq/Query/ExecutorInterface.md b/pq-gateway/pq/Query/ExecutorInterface.md new file mode 100644 index 0000000..a477fda --- /dev/null +++ b/pq-gateway/pq/Query/ExecutorInterface.md @@ -0,0 +1,4 @@ +# interface pq\Query\ExecutorInterface extends SplSubject + +API to execute queries assembled by pq\Query\WriterInterface. + diff --git a/pq-gateway/pq/Query/ExecutorInterface/execute.md b/pq-gateway/pq/Query/ExecutorInterface/execute.md new file mode 100644 index 0000000..1f56990 --- /dev/null +++ b/pq-gateway/pq/Query/ExecutorInterface/execute.md @@ -0,0 +1,20 @@ +# mixed pq\Query\ExecutorInterface pq\Query\ExecutorInterface::execute(\pq\Query\WriterInterface $query, callable $callback); + +Execute the query and process the result with the callback. + +> ***NOTE:*** + This method should notify the observers twice. + Once before the query gets executed and can be retrieved by pq\Query\ExecutorInterface::getQuery(). + And once after executing the query and the result can be retrieved by pq\Query\ExecutorInterface::getResult(). + +## Params: + +* pq\Query\WriterInterface $query + The query to execute. +* callable $callback + The result processing callback as function(pq\Result $result) + +## Returns: + +* mixed, the return value of the callback. + diff --git a/pq-gateway/pq/Query/ExecutorInterface/getConnection.md b/pq-gateway/pq/Query/ExecutorInterface/getConnection.md new file mode 100644 index 0000000..e9140c9 --- /dev/null +++ b/pq-gateway/pq/Query/ExecutorInterface/getConnection.md @@ -0,0 +1,11 @@ +# pq\Connection pq\Query\ExecutorInterface::getConnection() + +Retrieve the coonection used by the executor. + +## Params: + +None. + +## Returns: + +* pq\Connection, the currently used connection. diff --git a/pq-gateway/pq/Query/ExecutorInterface/getQuery.md b/pq-gateway/pq/Query/ExecutorInterface/getQuery.md new file mode 100644 index 0000000..83eaf23 --- /dev/null +++ b/pq-gateway/pq/Query/ExecutorInterface/getQuery.md @@ -0,0 +1,11 @@ +# pq\Query\WriterInterface pq\Query\ExecutorInterface::getQuery() + +Retrieve the current query. + +## Params: + +None. + +## Returns: + +* pq\Query\WriterInterface, the current query to execute. diff --git a/pq-gateway/pq/Query/ExecutorInterface/getResult.md b/pq-gateway/pq/Query/ExecutorInterface/getResult.md new file mode 100644 index 0000000..142493b --- /dev/null +++ b/pq-gateway/pq/Query/ExecutorInterface/getResult.md @@ -0,0 +1,11 @@ +# pq\Result pq\Query\ExecutorInterface::getResult() + +Retrieve the result of the current query. + +## Params: + +None. + +## Returns: + +* pq\Result, the result of the current query. diff --git a/pq-gateway/pq/Query/ExecutorInterface/setConnection.md b/pq-gateway/pq/Query/ExecutorInterface/setConnection.md new file mode 100644 index 0000000..32977db --- /dev/null +++ b/pq-gateway/pq/Query/ExecutorInterface/setConnection.md @@ -0,0 +1,12 @@ +# pq\Query\ExecutorInterface pq\Query\ExecutorInterface::setConnection(pq\Connection $conn) + +Set the connection the executor should use. + +## Params: + +* pq\Connection $conn + The connection to use. + +## Return: + +* pq\Query\ExecutorInterface, self. diff --git a/pq-gateway/pq/Query/Expr.md b/pq-gateway/pq/Query/Expr.md new file mode 100644 index 0000000..6e03976 --- /dev/null +++ b/pq-gateway/pq/Query/Expr.md @@ -0,0 +1,10 @@ +# class pq\Query\Expr + +A query expression. + +## Properties: + +* protected string $expression + The expression. +* protected pq\Query\Expr $next + The next expression in a linked list. diff --git a/pq-gateway/pq/Query/Expr/__construct.md b/pq-gateway/pq/Query/Expr/__construct.md new file mode 100644 index 0000000..4990323 --- /dev/null +++ b/pq-gateway/pq/Query/Expr/__construct.md @@ -0,0 +1,12 @@ +# void pq\Query\Expr::__construct(string $e[, string ...$args]) + +Create a new expression. +If the number of arguments is greater than 1, then all arguments are stringified by sprintf. + +## Params: + +* string $e + The expression (possibly a sprintf format string). +* string ...$args + A variable list of sprintf substitution parameters. + diff --git a/pq-gateway/pq/Query/Expr/__toString.md b/pq-gateway/pq/Query/Expr/__toString.md new file mode 100644 index 0000000..1edde71 --- /dev/null +++ b/pq-gateway/pq/Query/Expr/__toString.md @@ -0,0 +1,12 @@ +# string pq\Query\Expr::__toString() + +Retrieve the string representation. +All of the expressions within the linked list are concatenated. + +## Params: + +None. + +## Returns: + +* string, the expression and all next expressions concatenated. diff --git a/pq-gateway/pq/Query/Expr/add.md b/pq-gateway/pq/Query/Expr/add.md new file mode 100644 index 0000000..0a2c15f --- /dev/null +++ b/pq-gateway/pq/Query/Expr/add.md @@ -0,0 +1,16 @@ +# pq\Query\Expr pq\Query\Expr::add(pq\Query\Expr $next) + +Add an expression at the end of the linked list. + +## Params: + +* pq\Query\Expr $next + The expression to add. + +## Returns: + +* pq\Query\Expr, self. + +## Throws: + +* UnexpectedValueException, if the receiving expression is NULL. diff --git a/pq-gateway/pq/Query/Expr/isNull.md b/pq-gateway/pq/Query/Expr/isNull.md new file mode 100644 index 0000000..396fffe --- /dev/null +++ b/pq-gateway/pq/Query/Expr/isNull.md @@ -0,0 +1,11 @@ +# bool pq\Query\Expr::isNull() + +Whether the expression is the literal NULL. + +## Params: + +None. + +## Returns: + +* bool, whether the expression case insensitively equals NULL. diff --git a/pq-gateway/pq/Query/Expressible.md b/pq-gateway/pq/Query/Expressible.md new file mode 100644 index 0000000..48a8d6c --- /dev/null +++ b/pq-gateway/pq/Query/Expressible.md @@ -0,0 +1,11 @@ +# class pq\Query\Expressible implements pq\Query\ExpressibleInterface + +An implementation to express column data changes. +See pq\Query\Expressible::mod() for an example. + +## Properties: + +* protected string $name + The name. +* protected mixed $data + The data. diff --git a/pq-gateway/pq/Query/Expressible/__construct.md b/pq-gateway/pq/Query/Expressible/__construct.md new file mode 100644 index 0000000..0eae689 --- /dev/null +++ b/pq-gateway/pq/Query/Expressible/__construct.md @@ -0,0 +1,10 @@ +# void pq\Query\Expressible::__construct(string $name, mixed $data) + +Create a new column data change expression. + +## Params: + +* string $name + The name (of the column). +* mixed $data + The data (of the column). diff --git a/pq-gateway/pq/Query/Expressible/__toString.md b/pq-gateway/pq/Query/Expressible/__toString.md new file mode 100644 index 0000000..faf2016 --- /dev/null +++ b/pq-gateway/pq/Query/Expressible/__toString.md @@ -0,0 +1,11 @@ +# string pq\Query\Expressible::__toString() + +Retrieve the contained value as string. + +## Params: + +None. + +## Returns: + +* string, the contained value. diff --git a/pq-gateway/pq/Query/Expressible/get.md b/pq-gateway/pq/Query/Expressible/get.md new file mode 100644 index 0000000..1d8b869 --- /dev/null +++ b/pq-gateway/pq/Query/Expressible/get.md @@ -0,0 +1,11 @@ +# mixed pq\Query\Expressible::get() + +Retrieve the contained value. + +## Params: + +None. + +## Returns: + +* mixed, the contained data/expression. diff --git a/pq-gateway/pq/Query/Expressible/isExpr.md b/pq-gateway/pq/Query/Expressible/isExpr.md new file mode 100644 index 0000000..8f0e612 --- /dev/null +++ b/pq-gateway/pq/Query/Expressible/isExpr.md @@ -0,0 +1,12 @@ +# bool pq\Query\Expressible::isExpr() + +Check whether the implementor already contains a expression, i.e. pq\Query\Expr. + +## Params: + +None. + +## Returns: + +* bool, whether we actually contain an expression. + diff --git a/pq-gateway/pq/Query/Expressible/mod.md b/pq-gateway/pq/Query/Expressible/mod.md new file mode 100644 index 0000000..11f8cea --- /dev/null +++ b/pq-gateway/pq/Query/Expressible/mod.md @@ -0,0 +1,77 @@ +# pq\Query\Expressible pq\Query\Expressible::mod(mixed $data[, string $op = NULL]) + +Modify the contained data, turning it into an expression, i.e. pq\Query\Expr. + +## Params: + +* mixed $data + Modifying data. +* Optional string $op = NULL + The intended operator (defaults to "+" for numeric values and "||" for strings). + +## Returns: + +* pq\Query\Expressible, self. + + +## Example: + + isExpr(), (string) $column, $column->get()); + + echo "\n"; + + $column->mod(1); // append "+ 1" + var_dump($column->isExpr(), (string) $column, $column->get()); + + echo "\n"; + + $column->set("'Hello'"); + var_dump($column->isExpr(), (string) $column, $column->get()); + + echo "\n"; + + $column->mod("' World!'"); + var_dump($column->isExpr(), (string) $column, $column->get()); + + ?> + +Yields: + + bool(false) + string(1) "5" + int(5) + + bool(true) + string(11) "example + 1" + object(pq\Query\Expr)#3 (2) { + ["expression":protected]=> + string(7) "example" + ["next":protected]=> + object(pq\Query\Expr)#4 (2) { + ["expression":protected]=> + string(3) "+ 1" + ["next":protected]=> + NULL + } + } + + bool(false) + string(7) "'Hello'" + string(7) "'Hello'" + + bool(true) + string(20) "example || ' World!'" + object(pq\Query\Expr)#3 (2) { + ["expression":protected]=> + string(7) "example" + ["next":protected]=> + object(pq\Query\Expr)#4 (2) { + ["expression":protected]=> + string(12) "|| ' World!'" + ["next":protected]=> + NULL + } + } diff --git a/pq-gateway/pq/Query/Expressible/set.md b/pq-gateway/pq/Query/Expressible/set.md new file mode 100644 index 0000000..99163c7 --- /dev/null +++ b/pq-gateway/pq/Query/Expressible/set.md @@ -0,0 +1,12 @@ +# pq\Query\Expressible pq\Query\Expressible::set(mixed $data) + +Set the contained data. + +## Params: + +* mixed $data + The data. + +## Returns: + +* pq\Query\Expressible, self. diff --git a/pq-gateway/pq/Query/ExpressibleInterface.md b/pq-gateway/pq/Query/ExpressibleInterface.md new file mode 100644 index 0000000..83ec13e --- /dev/null +++ b/pq-gateway/pq/Query/ExpressibleInterface.md @@ -0,0 +1,3 @@ +# interface ExpressibleInterface + +API to express column data changes. diff --git a/pq-gateway/pq/Query/ExpressibleInterface/__toString.md b/pq-gateway/pq/Query/ExpressibleInterface/__toString.md new file mode 100644 index 0000000..ffac5e3 --- /dev/null +++ b/pq-gateway/pq/Query/ExpressibleInterface/__toString.md @@ -0,0 +1,11 @@ +# string pq\Query\ExpressibleInterface::__toString() + +Retrieve the contained value as string. + +## Params: + +None. + +## Returns: + +* string, the contained value. diff --git a/pq-gateway/pq/Query/ExpressibleInterface/get.md b/pq-gateway/pq/Query/ExpressibleInterface/get.md new file mode 100644 index 0000000..238e3cf --- /dev/null +++ b/pq-gateway/pq/Query/ExpressibleInterface/get.md @@ -0,0 +1,11 @@ +# mixed pq\Query\ExpressibleInterface::get() + +Retrieve the contained value. + +## Params: + +None. + +## Returns: + +* mixed, the contained data/expression. diff --git a/pq-gateway/pq/Query/ExpressibleInterface/isExpr.md b/pq-gateway/pq/Query/ExpressibleInterface/isExpr.md new file mode 100644 index 0000000..a1a64d2 --- /dev/null +++ b/pq-gateway/pq/Query/ExpressibleInterface/isExpr.md @@ -0,0 +1,12 @@ +# bool pq\Query\ExpressibleInterface::isExpr() + +Check whether the implementor already contains a expression, i.e. pq\Query\Expr. + +## Params: + +None. + +## Returns: + +* bool, whether we actually contain an expression. + diff --git a/pq-gateway/pq/Query/ExpressibleInterface/mod.md b/pq-gateway/pq/Query/ExpressibleInterface/mod.md new file mode 100644 index 0000000..5922913 --- /dev/null +++ b/pq-gateway/pq/Query/ExpressibleInterface/mod.md @@ -0,0 +1,14 @@ +# pq\Query\ExpressibleInterface pq\Query\ExpressibleInterface::mod(mixed $data[, string $op = NULL]) + +Modify the contained data, turning it into an expression, i.e. pq\Query\Expr. + +## Params: + +* mixed $data + Modifying data. +* Optional string $op = NULL + The intended operator (defaults to "+" for numeric values and "||" for strings). + +## Returns: + +* pq\Query\ExpressibleInterface, self. diff --git a/pq-gateway/pq/Query/ExpressibleInterface/set.md b/pq-gateway/pq/Query/ExpressibleInterface/set.md new file mode 100644 index 0000000..65787fd --- /dev/null +++ b/pq-gateway/pq/Query/ExpressibleInterface/set.md @@ -0,0 +1,12 @@ +# pq\Query\ExpressibleInterface pq\Query\ExpressibleInterface::set(mixed $data) + +Set the contained data. + +## Params: + +* mixed $data + The data. + +## Returns: + +* pq\Query\ExpressibleInterface, self. diff --git a/pq-gateway/pq/Query/Writer/__construct.md b/pq-gateway/pq/Query/Writer/__construct.md new file mode 100644 index 0000000..d3a4385 --- /dev/null +++ b/pq-gateway/pq/Query/Writer/__construct.md @@ -0,0 +1,12 @@ +# void pq\Query\Writer::__construct([string $query = ""[, array $params = array()[, array $types = array()]]]) + +Create a new query writer. + +## Params: + +* Optional string $query = "" + The initial query string. +* Optional array $params = array() + The initial query parameters. +* Optional array $types = array() + The initial query parameters' types. diff --git a/pq-gateway/pq/Query/Writer/criteria.md b/pq-gateway/pq/Query/Writer/criteria.md index 0f27ae5..3c89d1b 100644 --- a/pq-gateway/pq/Query/Writer/criteria.md +++ b/pq-gateway/pq/Query/Writer/criteria.md @@ -2,6 +2,10 @@ Write nested AND/OR criteria to the query string. +The criteria can either be a simple accociative array, where the keys build the left hand operand plus the operator and the values make up the right hand operand and will be passed to pq\Query\Writer::param(). All concatenated together by AND clauses. + +Using multiple arrays, the above logic will be applied to each array and then concatenated by OR clauses. + ## Params: * array $criteria diff --git a/pq-gateway/pq/Query/Writer/param.md b/pq-gateway/pq/Query/Writer/param.md index 9a7e9a7..2a4e241 100644 --- a/pq-gateway/pq/Query/Writer/param.md +++ b/pq-gateway/pq/Query/Writer/param.md @@ -11,7 +11,7 @@ Remember the parameter with any associated type and return $N to be written to t ## Returns: -* string, '$N', to be used with pq\Query\Writer::write(), where N is tne number of this parameter. +* string, '$N', to be used with pq\Query\Writer::write(), where N is the number of this parameter. ## Example: diff --git a/pq-gateway/pq/Query/Writer/reduce.md b/pq-gateway/pq/Query/Writer/reduce.md new file mode 100644 index 0000000..3ce1e44 --- /dev/null +++ b/pq-gateway/pq/Query/Writer/reduce.md @@ -0,0 +1,16 @@ +# protected string pq\Query\Writer::reduce(string $q, mixed $v) + +An array_reduce() helper for pq\Query\Writer::write(). + +## Params: + +* string $q + Query string. +* mixed $v + Query parts to append to $q, joined by commas if of type array. + +## Returns: + +* string, the concatenated arguments. + + diff --git a/pq-gateway/pq/Query/WriterInterface/criteria.md b/pq-gateway/pq/Query/WriterInterface/criteria.md index 374e1d1..3363e7c 100644 --- a/pq-gateway/pq/Query/WriterInterface/criteria.md +++ b/pq-gateway/pq/Query/WriterInterface/criteria.md @@ -10,32 +10,3 @@ Write nested AND/OR criteria to the query string. ## Returns: * pq\Query\WriterInterface, self. - -## Example: - - write("select * from account where") - ->criteria([ - ["id >" => 1, "id <" => 5], - ["name =" => "mike"] - ]); - - var_dump((string) $q, $q->getParams()); - - ?> - -Yields: - - string(84) "select * from account where ( ( ( id > $1 ) AND ( id < $2 ) ) OR ( ( name = $3 ) ) )" - array(3) { - [0]=> - int(1) - [1]=> - int(5) - [2]=> - string(4) "mike" - } diff --git a/pq-gateway/pq/Query/WriterInterface/param.md b/pq-gateway/pq/Query/WriterInterface/param.md index f674fba..40e3726 100644 --- a/pq-gateway/pq/Query/WriterInterface/param.md +++ b/pq-gateway/pq/Query/WriterInterface/param.md @@ -11,25 +11,4 @@ Remember the parameter with any associated type and return $N to be written to t ## Returns: -* string, '$N', to be used with pq\Query\WriterInterface::write(), where N is tne number of this parameter. - -## Example: - - write("SELECT", $writer->param(1)); - - var_dump((string) $writer, $writer->getParams()); - - ?> - -Yields: - - string(9) "SELECT $1" - array(1) { - [0]=> - int(1) - } +* string, '$N', to be used with pq\Query\WriterInterface::write(), where N is the number of this parameter.