Asterisk - The Open Source Telephony Project
18.5.0
|
PostgreSQL plugin for Asterisk RealTime Architecture. More...
#include "asterisk.h"
#include <libpq-fe.h>
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
Go to the source code of this file.
Data Structures | |
struct | columns |
struct | tables::psql_columns |
struct | psql_tables |
struct | tables |
Macros | |
#define | ESCAPE_CLAUSE (USE_BACKSLASH_AS_STRING ? " ESCAPE '\\'" : " ESCAPE '\\\\'") |
#define | ESCAPE_STRING(buffer, stringname) |
#define | has_schema_support (version > 70300 ? 1 : 0) |
#define | IS_SQL_LIKE_CLAUSE(x) ((x) && ast_ends_with(x, " LIKE")) |
#define | MAX_DB_OPTION_SIZE 64 |
#define | release_table(table) ast_rwlock_unlock(&(table)->lock); |
#define | RES_CONFIG_PGSQL_CONF "res_pgsql.conf" |
#define | USE_BACKSLASH_AS_STRING (version >= 90100 ? 1 : 0) |
Enumerations | |
enum | { RQ_WARN, RQ_CREATECLOSE, RQ_CREATECHAR } |
Functions | |
static void | __init_escapebuf_buf (void) |
static void | __init_findtable_buf (void) |
static void | __init_semibuf_buf (void) |
static void | __init_sql_buf (void) |
static void | __init_where_buf (void) |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static int | _pgsql_exec (const char *database, const char *tablename, const char *sql, PGresult **result) |
Helper function for pgsql_exec. For running querys, use pgsql_exec() More... | |
struct ast_module * | AST_MODULE_SELF_SYM (void) |
static struct ast_config * | config_pgsql (const char *database, const char *table, const char *file, struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl, const char *who_asked) |
static int | destroy_pgsql (const char *database, const char *table, const char *keyfield, const char *lookup, const struct ast_variable *fields) |
static void | destroy_table (struct tables *table) |
static struct columns * | find_column (struct tables *t, const char *colname) |
static struct tables * | find_table (const char *database, const char *orig_tablename) |
static char * | handle_cli_realtime_pgsql_cache (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_realtime_pgsql_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static int | load_module (void) |
static int | parse_config (int reload) |
static int | pgsql_exec (const char *database, const char *tablename, const char *sql, PGresult **result) |
Do a postgres query, with reconnection support. More... | |
static int | pgsql_reconnect (const char *database) |
static struct ast_config * | realtime_multi_pgsql (const char *database, const char *table, const struct ast_variable *fields) |
static struct ast_variable * | realtime_pgsql (const char *database, const char *tablename, const struct ast_variable *fields) |
static int | reload (void) |
static int | require_pgsql (const char *database, const char *tablename, va_list ap) |
static int | store_pgsql (const char *database, const char *table, const struct ast_variable *fields) |
static int | unload_module (void) |
static int | unload_pgsql (const char *database, const char *tablename) |
static int | update2_pgsql (const char *database, const char *tablename, const struct ast_variable *lookup_fields, const struct ast_variable *update_fields) |
static int | update_pgsql (const char *database, const char *tablename, const char *keyfield, const char *lookup, const struct ast_variable *fields) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PostgreSQL RealTime Configuration Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_REALTIME_DRIVER, .requires = "extconfig", } |
static const struct ast_module_info * | ast_module_info = &__mod_info |
static struct ast_cli_entry | cli_realtime [] |
static time_t | connect_time = 0 |
static char | dbappname [MAX_DB_OPTION_SIZE] = "" |
static char | dbhost [MAX_DB_OPTION_SIZE] = "" |
static char | dbname [MAX_DB_OPTION_SIZE] = "" |
static char | dbpass [MAX_DB_OPTION_SIZE] = "" |
static int | dbport = 5432 |
static char | dbsock [MAX_DB_OPTION_SIZE] = "" |
static char | dbuser [MAX_DB_OPTION_SIZE] = "" |
static struct ast_threadstorage | escapebuf_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_escapebuf_buf , .custom_init = NULL , } |
static struct ast_threadstorage | findtable_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_findtable_buf , .custom_init = NULL , } |
static struct ast_config_engine | pgsql_engine |
static ast_mutex_t | pgsql_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } |
static PGconn * | pgsqlConn = NULL |
static struct psql_tables | psql_tables = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , } |
static enum { ... } | requirements |
static struct ast_threadstorage | semibuf_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_semibuf_buf , .custom_init = NULL , } |
static struct ast_threadstorage | sql_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_sql_buf , .custom_init = NULL , } |
static int | version |
static struct ast_threadstorage | where_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_where_buf , .custom_init = NULL , } |
PostgreSQL plugin for Asterisk RealTime Architecture.
PostgreSQL http://www.postgresql.org
Definition in file res_config_pgsql.c.
#define ESCAPE_CLAUSE (USE_BACKSLASH_AS_STRING ? " ESCAPE '\\'" : " ESCAPE '\\\\'") |
Definition at line 388 of file res_config_pgsql.c.
Referenced by realtime_multi_pgsql(), and realtime_pgsql().
#define ESCAPE_STRING | ( | buffer, | |
stringname | |||
) |
Definition at line 98 of file res_config_pgsql.c.
Referenced by destroy_pgsql(), realtime_multi_pgsql(), realtime_pgsql(), store_pgsql(), update2_pgsql(), and update_pgsql().
#define has_schema_support (version > 70300 ? 1 : 0) |
Definition at line 54 of file res_config_pgsql.c.
Referenced by find_table().
#define IS_SQL_LIKE_CLAUSE | ( | x | ) | ((x) && ast_ends_with(x, " LIKE")) |
Definition at line 387 of file res_config_pgsql.c.
Referenced by realtime_multi_pgsql(), and realtime_pgsql().
#define MAX_DB_OPTION_SIZE 64 |
Definition at line 57 of file res_config_pgsql.c.
#define release_table | ( | table | ) | ast_rwlock_unlock(&(table)->lock); |
Definition at line 372 of file res_config_pgsql.c.
Referenced by handle_cli_realtime_pgsql_cache(), require_pgsql(), update2_pgsql(), and update_pgsql().
#define RES_CONFIG_PGSQL_CONF "res_pgsql.conf" |
Definition at line 50 of file res_config_pgsql.c.
Referenced by config_pgsql(), and parse_config().
#define USE_BACKSLASH_AS_STRING (version >= 90100 ? 1 : 0) |
Definition at line 55 of file res_config_pgsql.c.
anonymous enum |
Enumerator | |
---|---|
RQ_WARN | |
RQ_CREATECLOSE | |
RQ_CREATECHAR |
Definition at line 91 of file res_config_pgsql.c.
|
static |
Definition at line 47 of file res_config_pgsql.c.
|
static |
Definition at line 45 of file res_config_pgsql.c.
|
static |
Definition at line 48 of file res_config_pgsql.c.
|
static |
Definition at line 44 of file res_config_pgsql.c.
|
static |
Definition at line 46 of file res_config_pgsql.c.
|
static |
Definition at line 1722 of file res_config_pgsql.c.
|
static |
Definition at line 1722 of file res_config_pgsql.c.
|
static |
Helper function for pgsql_exec. For running querys, use pgsql_exec()
Connect if not currently connected. Run the given query.
database | database name we are connected to (used for error logging) |
tablename | table name we are connected to (used for error logging) |
sql | sql query string to execute |
result | pointer for where to store the result handle |
Definition at line 144 of file res_config_pgsql.c.
References ast_debug, ast_log, LOG_ERROR, LOG_NOTICE, NULL, pgsql_reconnect(), and pgsqlConn.
Referenced by pgsql_exec().
struct ast_module* AST_MODULE_SELF_SYM | ( | void | ) |
Definition at line 1722 of file res_config_pgsql.c.
|
static |
Definition at line 1132 of file res_config_pgsql.c.
References ast_category_append(), ast_category_new_dynamic, ast_config_internal_load(), ast_copy_string(), ast_debug, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_str_buffer(), ast_str_set(), ast_str_thread_get(), ast_variable_append(), ast_variable_new, dbname, columns::last, LOG_WARNING, NULL, pgsql_exec(), pgsql_lock, RAII_VAR, RES_CONFIG_PGSQL_CONF, result, and sql_buf.
|
static |
Definition at line 1052 of file res_config_pgsql.c.
References ast_debug, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_str_append(), ast_str_buffer(), ast_str_set(), ast_str_thread_get(), ast_strlen_zero, buf1, buf2, dbname, ESCAPE_STRING, escapebuf_buf, LOG_WARNING, ast_variable::name, ast_variable::next, NULL, pgsql_exec(), pgsql_lock, pgsql_reconnect(), pgsqlConn, RAII_VAR, result, sql_buf, ast_variable::value, and where_buf.
|
static |
Definition at line 117 of file res_config_pgsql.c.
References ast_free, AST_LIST_REMOVE_HEAD, ast_rwlock_destroy, ast_rwlock_unlock, ast_rwlock_wrlock, tables::columns, columns::list, and tables::lock.
Referenced by find_table(), unload_module(), and unload_pgsql().
Definition at line 374 of file res_config_pgsql.c.
References AST_LIST_TRAVERSE, tables::columns, columns::list, columns::name, and NULL.
Referenced by update2_pgsql(), and update_pgsql().
|
static |
Definition at line 250 of file res_config_pgsql.c.
References ast_alloca, ast_calloc, ast_debug, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_rwlock_init, ast_rwlock_rdlock, ast_str_buffer(), ast_str_set(), ast_str_thread_get(), ast_strdupa, ast_strlen_zero, ast_verb, tables::columns, destroy_table(), findtable_buf, has_schema_support, columns::hasdefault, columns::len, columns::list, tables::lock, LOG_ERROR, columns::name, tables::name, columns::notnull, NULL, pgsql_exec(), pgsql_lock, pgsqlConn, RAII_VAR, result, table, and columns::type.
Referenced by handle_cli_realtime_pgsql_cache(), require_pgsql(), update2_pgsql(), and update_pgsql().
|
static |
Definition at line 1615 of file res_config_pgsql.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strdup, CLI_GENERATE, CLI_INIT, tables::columns, ast_cli_entry::command, ast_cli_args::fd, find_table(), columns::len, columns::list, ast_cli_args::n, columns::name, tables::name, columns::notnull, NULL, release_table, columns::type, ast_cli_entry::usage, and ast_cli_args::word.
|
static |
Definition at line 1669 of file res_config_pgsql.c.
References ast_cli_args::argc, ast_cli(), ast_cli_print_timestr_fromseconds(), AST_MODFLAG_LOAD_ORDER, AST_MODPRI_REALTIME_DRIVER, AST_MODULE_INFO(), AST_MODULE_SUPPORT_EXTENDED, ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero, ASTERISK_GPL_KEY, buf, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, connect_time, dbhost, dbname, dbport, dbsock, dbuser, ast_cli_args::fd, load_module(), NULL, pgsql_lock, pgsqlConn, reload(), unload_module(), and ast_cli_entry::usage.
|
static |
Definition at line 1389 of file res_config_pgsql.c.
References ARRAY_LEN, ast_cli_register_multiple, ast_config_engine_register(), AST_MODULE_LOAD_DECLINE, and parse_config().
Referenced by handle_cli_realtime_pgsql_status().
|
static |
Definition at line 1434 of file res_config_pgsql.c.
References ast_config_destroy(), ast_config_load, ast_copy_string(), ast_debug, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero, ast_variable_retrieve(), ast_verb, config, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, dbappname, dbhost, dbname, dbpass, dbport, dbsock, dbuser, DEBUG_ATLEAST, LOG_DEBUG, LOG_WARNING, NULL, pgsql_lock, pgsql_reconnect(), pgsqlConn, RES_CONFIG_PGSQL_CONF, RQ_CREATECHAR, RQ_CREATECLOSE, and RQ_WARN.
Referenced by load_module(), and reload().
|
static |
Do a postgres query, with reconnection support.
Connect if not currently connected. Run the given query and if we're disconnected afterwards, reconnect and query again.
database | database name we are connected to (used for error logging) |
tablename | table name we are connected to (used for error logging) |
sql | sql query string to execute |
result | pointer for where to store the result handle |
Definition at line 218 of file res_config_pgsql.c.
References _pgsql_exec(), ast_debug, ast_log, and LOG_NOTICE.
Referenced by config_pgsql(), destroy_pgsql(), find_table(), realtime_multi_pgsql(), realtime_pgsql(), require_pgsql(), store_pgsql(), update2_pgsql(), and update_pgsql().
|
static |
Definition at line 1555 of file res_config_pgsql.c.
References ast_copy_string(), ast_debug, ast_free, ast_log, ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_set(), ast_strlen_zero, connect_time, dbappname, dbhost, dbname, dbpass, dbport, dbsock, dbuser, LOG_ERROR, NULL, pgsqlConn, S_OR, and version.
Referenced by _pgsql_exec(), destroy_pgsql(), parse_config(), realtime_multi_pgsql(), realtime_pgsql(), store_pgsql(), update2_pgsql(), and update_pgsql().
|
static |
Definition at line 524 of file res_config_pgsql.c.
References ast_calloc, ast_category_append(), ast_category_new_anonymous, ast_category_rename(), ast_config_destroy(), ast_config_new(), ast_debug, ast_free, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_realtime_decode_chunk(), ast_str_append(), ast_str_buffer(), ast_str_set(), ast_str_thread_get(), ast_strdupa, ast_strip(), ast_strlen_zero, ast_variable_append(), ast_variable_new, dbname, ESCAPE_CLAUSE, ESCAPE_STRING, escapebuf_buf, IS_SQL_LIKE_CLAUSE, LOG_ERROR, LOG_WARNING, ast_variable::name, ast_variable::next, NULL, pgsql_exec(), pgsql_lock, pgsql_reconnect(), pgsqlConn, RAII_VAR, result, sql_buf, strsep(), ast_variable::value, and var.
|
static |
Definition at line 390 of file res_config_pgsql.c.
References ast_calloc, ast_debug, ast_free, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_realtime_decode_chunk(), ast_str_append(), ast_str_buffer(), ast_str_set(), ast_str_thread_get(), ast_strip(), ast_strlen_zero, ast_variable_new, dbname, ESCAPE_CLAUSE, ESCAPE_STRING, escapebuf_buf, IS_SQL_LIKE_CLAUSE, LOG_ERROR, LOG_WARNING, ast_variable::name, ast_variable::next, NULL, pgsql_exec(), pgsql_lock, pgsql_reconnect(), pgsqlConn, RAII_VAR, result, sql_buf, strsep(), ast_variable::value, and var.
|
static |
Definition at line 1427 of file res_config_pgsql.c.
References parse_config().
Referenced by handle_cli_realtime_pgsql_status().
|
static |
Definition at line 1211 of file res_config_pgsql.c.
References ast_debug, ast_free, AST_LIST_TRAVERSE, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_rq_is_int(), ast_str_buffer(), ast_str_create, ast_str_set(), tables::columns, dbname, find_table(), columns::len, columns::list, LOG_ERROR, LOG_WARNING, columns::name, pgsql_exec(), pgsql_lock, release_table, result, RQ_CHAR, RQ_CREATECHAR, RQ_DATE, RQ_DATETIME, RQ_FLOAT, RQ_INTEGER1, RQ_INTEGER2, RQ_INTEGER3, RQ_INTEGER4, RQ_INTEGER8, RQ_UINTEGER1, RQ_UINTEGER2, RQ_UINTEGER3, RQ_UINTEGER4, RQ_UINTEGER8, RQ_WARN, columns::size, table, and columns::type.
|
static |
Definition at line 969 of file res_config_pgsql.c.
References ast_debug, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_str_append(), ast_str_buffer(), ast_str_set(), ast_str_thread_get(), buf, dbname, ESCAPE_STRING, escapebuf_buf, LOG_WARNING, ast_variable::name, ast_variable::next, NULL, pgsql_exec(), pgsql_lock, pgsql_reconnect(), pgsqlConn, RAII_VAR, result, sql_buf, ast_variable::value, and where_buf.
|
static |
Definition at line 1401 of file res_config_pgsql.c.
References ARRAY_LEN, ast_cli_unregister_multiple(), ast_config_engine_deregister(), AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_mutex_lock, ast_mutex_unlock, destroy_table(), columns::list, NULL, pgsql_lock, pgsqlConn, and table.
Referenced by handle_cli_realtime_pgsql_status().
|
static |
Definition at line 1347 of file res_config_pgsql.c.
References ast_debug, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, dbname, destroy_table(), columns::list, and tables::name.
|
static |
Definition at line 843 of file res_config_pgsql.c.
References ast_debug, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_str_append(), ast_str_buffer(), ast_str_set(), ast_str_thread_get(), dbname, ESCAPE_STRING, escapebuf_buf, find_column(), find_table(), columns::first, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_variable::name, ast_variable::next, NULL, pgsql_exec(), pgsql_lock, pgsql_reconnect(), pgsqlConn, RAII_VAR, release_table, result, sql_buf, table, ast_variable::value, and where_buf.
|
static |
Definition at line 701 of file res_config_pgsql.c.
References ast_debug, AST_LIST_TRAVERSE, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_str_append(), ast_str_buffer(), ast_str_set(), ast_str_thread_get(), tables::columns, dbname, ESCAPE_STRING, escapebuf_buf, find_column(), find_table(), columns::list, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_variable::name, columns::name, ast_variable::next, NULL, pgsql_exec(), pgsql_lock, pgsql_reconnect(), pgsqlConn, RAII_VAR, release_table, result, sql_buf, table, and ast_variable::value.
|
static |
Definition at line 1722 of file res_config_pgsql.c.
|
static |
Definition at line 1722 of file res_config_pgsql.c.
|
static |
Definition at line 93 of file res_config_pgsql.c.
|
static |
Definition at line 84 of file res_config_pgsql.c.
Referenced by handle_cli_realtime_pgsql_status(), and pgsql_reconnect().
|
static |
Definition at line 81 of file res_config_pgsql.c.
Referenced by parse_config(), and pgsql_reconnect().
|
static |
Definition at line 77 of file res_config_pgsql.c.
Referenced by aMYSQL_connect(), handle_cli_realtime_pgsql_status(), parse_config(), and pgsql_reconnect().
|
static |
Definition at line 80 of file res_config_pgsql.c.
Referenced by config_pgsql(), destroy_pgsql(), handle_cli_realtime_pgsql_status(), parse_config(), pgsql_reconnect(), realtime_multi_pgsql(), realtime_pgsql(), require_pgsql(), store_pgsql(), unload_pgsql(), update2_pgsql(), and update_pgsql().
|
static |
Definition at line 79 of file res_config_pgsql.c.
Referenced by aMYSQL_connect(), parse_config(), and pgsql_reconnect().
|
static |
Definition at line 83 of file res_config_pgsql.c.
Referenced by handle_cli_realtime_pgsql_status(), parse_config(), and pgsql_reconnect().
|
static |
Definition at line 82 of file res_config_pgsql.c.
Referenced by handle_cli_realtime_pgsql_status(), parse_config(), and pgsql_reconnect().
|
static |
Definition at line 78 of file res_config_pgsql.c.
Referenced by handle_cli_realtime_pgsql_status(), parse_config(), and pgsql_reconnect().
|
static |
Definition at line 47 of file res_config_pgsql.c.
Referenced by destroy_pgsql(), realtime_multi_pgsql(), realtime_pgsql(), store_pgsql(), update2_pgsql(), and update_pgsql().
|
static |
Definition at line 45 of file res_config_pgsql.c.
Referenced by find_table().
|
static |
Definition at line 1376 of file res_config_pgsql.c.
|
static |
Definition at line 43 of file res_config_pgsql.c.
Referenced by config_pgsql(), destroy_pgsql(), find_table(), handle_cli_realtime_pgsql_status(), parse_config(), realtime_multi_pgsql(), realtime_pgsql(), require_pgsql(), store_pgsql(), unload_module(), update2_pgsql(), and update_pgsql().
|
static |
Definition at line 52 of file res_config_pgsql.c.
Referenced by _pgsql_exec(), destroy_pgsql(), find_table(), handle_cli_realtime_pgsql_status(), parse_config(), pgsql_reconnect(), realtime_multi_pgsql(), realtime_pgsql(), store_pgsql(), unload_module(), update2_pgsql(), and update_pgsql().
|
static |
enum { ... } requirements |
|
static |
Definition at line 48 of file res_config_pgsql.c.
|
static |
Definition at line 44 of file res_config_pgsql.c.
Referenced by config_pgsql(), destroy_pgsql(), realtime_multi_pgsql(), realtime_pgsql(), store_pgsql(), update2_pgsql(), and update_pgsql().
|
static |
Definition at line 53 of file res_config_pgsql.c.
Referenced by pgsql_reconnect().
|
static |
Definition at line 46 of file res_config_pgsql.c.
Referenced by destroy_pgsql(), store_pgsql(), and update2_pgsql().