28 require_once DOL_DOCUMENT_ROOT.
'/core/db/DoliDB.class.php';
40 const LABEL =
'MySQL or MariaDB';
62 if (!empty($conf->db->character_set)) {
63 $this->forcecharset = $conf->db->character_set;
65 if (!empty($conf->db->dolibarr_main_db_collation)) {
66 $this->forcecollate = $conf->db->dolibarr_main_db_collation;
69 $this->database_user = $user;
70 $this->database_host = $host;
71 $this->database_port = $port;
73 $this->transaction_opened = 0;
77 if (!class_exists(
'mysqli')) {
78 $this->connected =
false;
80 $this->
error =
"Mysqli PHP functions for using Mysqli driver are not available in this version of PHP. Try to use another driver.";
81 dol_syslog(get_class($this).
"::DoliDBMysqli : Mysqli PHP functions for using Mysqli driver are not available in this version of PHP. Try to use another driver.", LOG_ERR);
85 $this->connected =
false;
87 $this->
error = $langs->trans(
"ErrorWrongHostParameter");
88 dol_syslog(get_class($this).
"::DoliDBMysqli : Connect error, wrong host parameters", LOG_ERR);
93 $this->
db = $this->
connect($host, $user, $pass,
'', $port);
95 if ($this->
db && empty($this->
db->connect_errno)) {
96 $this->connected =
true;
99 $this->connected =
false;
101 $this->
error = empty($this->
db) ?
'Failed to connect' : $this->
db->connect_error;
102 dol_syslog(get_class($this).
"::DoliDBMysqli Connect error: ".$this->
error, LOG_ERR);
106 if ($this->connected && $name) {
108 $this->database_selected =
true;
109 $this->database_name = $name;
113 $clientmustbe = empty($conf->db->dolibarr_main_db_character_set) ?
'utf8' : $conf->db->dolibarr_main_db_character_set;
114 if (preg_match(
'/latin1/', $clientmustbe)) {
115 $clientmustbe =
'utf8';
118 if ($this->
db->character_set_name() != $clientmustbe) {
119 $this->
db->set_charset($clientmustbe);
121 $collation = $conf->db->dolibarr_main_db_collation;
122 if (preg_match(
'/latin1/', $collation)) {
123 $collation =
'utf8_unicode_ci';
126 if (!preg_match(
'/general/', $collation)) {
127 $this->
db->query(
"SET collation_connection = ".$collation);
131 $this->database_selected =
false;
132 $this->database_name =
'';
135 dol_syslog(get_class($this).
"::DoliDBMysqli : Select_db error ".$this->
error, LOG_ERR);
139 $this->database_selected =
false;
141 if ($this->connected) {
143 $clientmustbe = empty($conf->db->dolibarr_main_db_character_set) ?
'utf8' : $conf->db->dolibarr_main_db_character_set;
144 if (preg_match(
'/latin1/', $clientmustbe)) {
145 $clientmustbe =
'utf8';
147 if (preg_match(
'/utf8mb4/', $clientmustbe)) {
148 $clientmustbe =
'utf8';
151 if ($this->
db->character_set_name() != $clientmustbe) {
152 $this->
db->set_charset($clientmustbe);
154 $collation = $conf->db->dolibarr_main_db_collation;
155 if (preg_match(
'/latin1/', $collation)) {
156 $collation =
'utf8_unicode_ci';
158 if (preg_match(
'/utf8mb4/', $collation)) {
159 $collation =
'utf8_unicode_ci';
162 if (!preg_match(
'/general/', $collation)) {
163 $this->
db->query(
"SET collation_connection = ".$collation);
179 return " FORCE INDEX(".preg_replace(
'/[^a-z0-9_]/',
'', $nameofindex).
")";
206 dol_syslog(get_class($this).
"::select_db database=".$database, LOG_DEBUG);
209 $result = $this->
db->select_db($database);
228 public function connect($host, $login, $passwd, $name, $port = 0)
230 dol_syslog(get_class($this).
"::connect host=$host, port=$port, login=$login, passwd=--hidden--, name=$name", LOG_DEBUG);
239 $tmp =
new mysqli($host, $login, $passwd, $name, $port);
241 dol_syslog(get_class($this).
"::connect failed", LOG_DEBUG);
253 return $this->
db->server_info;
263 return $this->
db->client_info;
276 if ($this->transaction_opened > 0) {
277 dol_syslog(get_class($this).
"::close Closing a connection with an opened transaction depth=".$this->transaction_opened, LOG_ERR);
279 $this->connected =
false;
280 return $this->
db->close();
297 public function query($query, $usesavepoint = 0,
$type =
'auto', $result_mode = 0)
299 global $conf, $dolibarr_main_db_readonly;
301 $query = trim($query);
303 if (!in_array($query, array(
'BEGIN',
'COMMIT',
'ROLLBACK'))) {
304 $SYSLOG_SQL_LIMIT = 10000;
305 dol_syslog(
'sql='.substr($query, 0, $SYSLOG_SQL_LIMIT), LOG_DEBUG);
311 if (!empty($dolibarr_main_db_readonly)) {
312 if (preg_match(
'/^(INSERT|UPDATE|REPLACE|DELETE|CREATE|ALTER|TRUNCATE|DROP)/i', $query)) {
313 $this->
lasterror =
'Application in read-only mode';
321 if (!$this->database_name) {
323 $ret = $this->
db->query($query, $result_mode);
325 $ret = $this->
db->query($query, $result_mode);
328 dol_syslog(get_class($this).
"::query Exception in query instead of returning an error: ".$e->getMessage(), LOG_ERR);
332 if (!preg_match(
"/^COMMIT/i", $query) && !preg_match(
"/^ROLLBACK/i", $query)) {
339 if (empty($conf->global->SYSLOG_LEVEL) || $conf->global->SYSLOG_LEVEL < LOG_DEBUG) {
340 dol_syslog(get_class($this).
"::query SQL Error query: ".$query, LOG_ERR);
342 dol_syslog(get_class($this).
"::query SQL Error message: ".$this->
lasterrno.
" ".$this->lasterror, LOG_ERR);
346 $this->_results = $ret;
363 if (!is_object($resultset)) {
364 $resultset = $this->_results;
366 return $resultset->fetch_object();
381 if (!is_object($resultset)) {
382 $resultset = $this->_results;
384 return $resultset->fetch_array();
398 if (!is_bool($resultset)) {
399 if (!is_object($resultset)) {
400 $resultset = $this->_results;
402 return $resultset->fetch_row();
421 if (!is_object($resultset)) {
422 $resultset = $this->_results;
424 return isset($resultset->num_rows) ? $resultset->num_rows : 0;
439 if (!is_object($resultset)) {
440 $resultset = $this->_results;
444 return $this->
db->affected_rows;
454 public function free($resultset =
null)
457 if (!is_object($resultset)) {
458 $resultset = $this->_results;
461 if (is_object($resultset)) {
462 $resultset->free_result();
474 return $this->
db->real_escape_string((
string) $stringtoencode);
486 return str_replace(
'_',
'\_', (
string) $stringtoencode);
497 return str_replace(array(
'\\',
'_',
'%'), array(
'\\\\',
'\_',
'\%'), (
string) $stringtoencode);
507 if (!$this->connected) {
509 return 'DB_ERROR_FAILED_TO_CONNECT';
512 $errorcode_map = array(
513 1004 =>
'DB_ERROR_CANNOT_CREATE',
514 1005 =>
'DB_ERROR_CANNOT_CREATE',
515 1006 =>
'DB_ERROR_CANNOT_CREATE',
516 1007 =>
'DB_ERROR_ALREADY_EXISTS',
517 1008 =>
'DB_ERROR_CANNOT_DROP',
518 1022 =>
'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
519 1025 =>
'DB_ERROR_NO_FOREIGN_KEY_TO_DROP',
520 1044 =>
'DB_ERROR_ACCESSDENIED',
521 1046 =>
'DB_ERROR_NODBSELECTED',
522 1048 =>
'DB_ERROR_CONSTRAINT',
523 1050 =>
'DB_ERROR_TABLE_ALREADY_EXISTS',
524 1051 =>
'DB_ERROR_NOSUCHTABLE',
525 1054 =>
'DB_ERROR_NOSUCHFIELD',
526 1060 =>
'DB_ERROR_COLUMN_ALREADY_EXISTS',
527 1061 =>
'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
528 1062 =>
'DB_ERROR_RECORD_ALREADY_EXISTS',
529 1064 =>
'DB_ERROR_SYNTAX',
530 1068 =>
'DB_ERROR_PRIMARY_KEY_ALREADY_EXISTS',
531 1075 =>
'DB_ERROR_CANT_DROP_PRIMARY_KEY',
532 1091 =>
'DB_ERROR_NOSUCHFIELD',
533 1100 =>
'DB_ERROR_NOT_LOCKED',
534 1136 =>
'DB_ERROR_VALUE_COUNT_ON_ROW',
535 1146 =>
'DB_ERROR_NOSUCHTABLE',
536 1215 =>
'DB_ERROR_CANNOT_ADD_FOREIGN_KEY_CONSTRAINT',
537 1216 =>
'DB_ERROR_NO_PARENT',
538 1217 =>
'DB_ERROR_CHILD_EXISTS',
539 1396 =>
'DB_ERROR_USER_ALREADY_EXISTS',
540 1451 =>
'DB_ERROR_CHILD_EXISTS',
541 1826 =>
'DB_ERROR_KEY_NAME_ALREADY_EXISTS'
544 if (isset($errorcode_map[$this->
db->errno])) {
545 return $errorcode_map[$this->
db->errno];
547 $errno = $this->
db->errno;
548 return ($errno ?
'DB_ERROR_'.$errno :
'0');
559 if (!$this->connected) {
561 return 'Not connected. Check setup parameters in conf/conf.php file and your mysql client and server versions';
563 return $this->
db->error;
578 return $this->
db->insert_id;
589 public function encrypt($fieldorvalue, $withQuotes = 1)
594 $cryptType = (!empty($conf->db->dolibarr_main_db_encryption) ? $conf->db->dolibarr_main_db_encryption : 0);
597 $cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey) ? $conf->db->dolibarr_main_db_cryptkey :
'');
599 $escapedstringwithquotes = ($withQuotes ?
"'" :
"").$this->
escape($fieldorvalue).($withQuotes ?
"'" :
"");
601 if ($cryptType && !empty($cryptKey)) {
602 if ($cryptType == 2) {
603 $escapedstringwithquotes =
"AES_ENCRYPT(".$escapedstringwithquotes.
", '".$this->
escape($cryptKey).
"')";
604 } elseif ($cryptType == 1) {
605 $escapedstringwithquotes =
"DES_ENCRYPT(".$escapedstringwithquotes.
", '".$this->
escape($cryptKey).
"')";
609 return $escapedstringwithquotes;
623 $cryptType = (!empty($conf->db->dolibarr_main_db_encryption) ? $conf->db->dolibarr_main_db_encryption : 0);
626 $cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey) ? $conf->db->dolibarr_main_db_cryptkey :
'');
630 if ($cryptType && !empty($cryptKey)) {
631 if ($cryptType == 2) {
632 $return =
'AES_DECRYPT('.$value.
',\''.$cryptKey.
'\')
';
633 } elseif ($cryptType == 1) {
634 $return = 'DES_DECRYPT(
'.$value.',\
''.$cryptKey.
'\')
';
642 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
648 public function DDLGetConnectId()
651 $resql = $this->query('SELECT CONNECTION_ID()
');
653 $row = $this->fetch_row($resql);
660 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
672 public function DDLCreateDb($database, $charset = '', $collation = '', $owner = '')
675 if (empty($charset)) {
676 $charset = $this->forcecharset;
678 if (empty($collation)) {
679 $collation = $this->forcecollate;
682 // ALTER DATABASE dolibarr_db DEFAULT CHARACTER SET latin DEFAULT COLLATE latin1_swedish_ci
683 $sql = "CREATE DATABASE `".$this->escape($database)."`";
684 $sql .= " DEFAULT CHARACTER SET `".$this->escape($charset)."` DEFAULT COLLATE `".$this->escape($collation)."`";
686 dol_syslog($sql, LOG_DEBUG);
687 $ret = $this->query($sql);
689 // We try again for compatibility with Mysql < 4.1.1
690 $sql = "CREATE DATABASE `".$this->escape($database)."`";
691 dol_syslog($sql, LOG_DEBUG);
692 $ret = $this->query($sql);
697 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
705 public function DDLListTables($database, $table = '')
708 $listtables = array();
712 $tmptable = preg_replace('/[^a-z0-9\.\-\_%]/i
', '', $table);
714 $like = "LIKE '".$this->escape($tmptable)."'";
716 $tmpdatabase = preg_replace('/[^a-z0-9\.\-\_]/i
', '', $database);
718 $sql = "SHOW TABLES FROM `".$tmpdatabase."` ".$like.";";
720 $result = $this->query($sql);
722 while ($row = $this->fetch_row($result)) {
723 $listtables[] = $row[0];
729 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
736 public function DDLInfoTable($table)
739 $infotables = array();
741 $tmptable = preg_replace('/[^a-z0-9\.\-\_]/i
', '', $table);
743 $sql = "SHOW FULL COLUMNS FROM ".$tmptable.";";
745 dol_syslog($sql, LOG_DEBUG);
746 $result = $this->query($sql);
748 while ($row = $this->fetch_row($result)) {
749 $infotables[] = $row;
755 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
768 public function DDLCreateTable($table, $fields, $primary_key, $type, $unique_keys = null, $fulltext_keys = null, $keys = null)
771 // FIXME: $fulltext_keys parameter is unused
774 $sqluq = $sqlk = array();
776 // cles recherchees dans le tableau des descriptions (fields) : type,value,attribute,null,default,extra
777 // ex. : $fields['rowid'] = array('type'=>'int','value
'=>'11
','null'=>'not
null','extra
'=> 'auto_increment
');
778 $sql = "CREATE TABLE ".$table."(";
780 $sqlfields = array();
781 foreach ($fields as $field_name => $field_desc) {
782 $sqlfields[$i] = $field_name." ";
783 $sqlfields[$i] .= $field_desc['type'];
784 if (preg_match("/^[^\s]/i", $field_desc['value
'])) {
785 $sqlfields[$i] .= "(".$field_desc['value
'].")";
787 if (preg_match("/^[^\s]/i", $field_desc['attribute
'])) {
788 $sqlfields[$i] .= " ".$field_desc['attribute
'];
790 if (preg_match("/^[^\s]/i", $field_desc['default'])) {
791 if ((preg_match("/null/i", $field_desc['default'])) || (preg_match("/CURRENT_TIMESTAMP/i", $field_desc['default']))) {
792 $sqlfields[$i] .= " default ".$field_desc['default'];
794 $sqlfields[$i] .= " default '".$this->escape($field_desc['default'])."'";
797 if (preg_match("/^[^\s]/i", $field_desc['null'])) {
798 $sqlfields[$i] .= " ".$field_desc['null'];
800 if (preg_match("/^[^\s]/i", $field_desc['extra
'])) {
801 $sqlfields[$i] .= " ".$field_desc['extra
'];
805 if ($primary_key != "") {
806 $pk = "primary key(".$primary_key.")";
809 if (is_array($unique_keys)) {
811 foreach ($unique_keys as $key => $value) {
812 $sqluq[$i] = "UNIQUE KEY '".$key."' ('".$this->escape($value)."')";
816 if (is_array($keys)) {
818 foreach ($keys as $key => $value) {
819 $sqlk[$i] = "KEY ".$key." (".$value.")";
823 $sql .= implode(',
', $sqlfields);
824 if ($primary_key != "") {
827 if ($unique_keys != "") {
828 $sql .= ",".implode(',
', $sqluq);
830 if (is_array($keys)) {
831 $sql .= ",".implode(',
', $sqlk);
833 $sql .= ") engine=".$type;
835 if (!$this->query($sql)) {
842 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
849 public function DDLDropTable($table)
852 $tmptable = preg_replace('/[^a-z0-9\.\-\_]/i
', '', $table);
854 $sql = "DROP TABLE ".$tmptable;
856 if (!$this->query($sql)) {
863 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
871 public function DDLDescTable($table, $field = "")
874 $sql = "DESC ".$table." ".$field;
876 dol_syslog(get_class($this)."::DDLDescTable ".$sql, LOG_DEBUG);
877 $this->_results = $this->query($sql);
878 return $this->_results;
881 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
891 public function DDLAddField($table, $field_name, $field_desc, $field_position = "")
894 // cles recherchees dans le tableau des descriptions (field_desc) : type,value,attribute,null,default,extra
895 // ex. : $field_desc = array('type'=>'int','value
'=>'11
','null'=>'not
null','extra
'=> 'auto_increment
');
896 $sql = "ALTER TABLE ".$table." ADD ".$field_name." ";
897 $sql .= $field_desc['type'];
898 if (preg_match("/^[^\s]/i", $field_desc['value
'])) {
899 if (!in_array($field_desc['type'], array('date
', 'datetime
')) && $field_desc['value
']) {
900 $sql .= "(".$field_desc['value
'].")";
903 if (isset($field_desc['attribute
']) && preg_match("/^[^\s]/i", $field_desc['attribute
'])) {
904 $sql .= " ".$field_desc['attribute
'];
906 if (isset($field_desc['null']) && preg_match("/^[^\s]/i", $field_desc['null'])) {
907 $sql .= " ".$field_desc['null'];
909 if (isset($field_desc['default']) && preg_match("/^[^\s]/i", $field_desc['default'])) {
910 if (preg_match("/null/i", $field_desc['default'])) {
911 $sql .= " default ".$field_desc['default'];
913 $sql .= " default '".$this->escape($field_desc['default'])."'";
916 if (isset($field_desc['extra
']) && preg_match("/^[^\s]/i", $field_desc['extra
'])) {
917 $sql .= " ".$field_desc['extra
'];
919 $sql .= " ".$field_position;
921 dol_syslog(get_class($this)."::DDLAddField ".$sql, LOG_DEBUG);
922 if ($this->query($sql)) {
928 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
937 public function DDLUpdateField($table, $field_name, $field_desc)
940 $sql = "ALTER TABLE ".$table;
941 $sql .= " MODIFY COLUMN ".$field_name." ".$field_desc['type'];
942 if (in_array($field_desc['type'], array('double', 'tinyint
', 'int', 'varchar
')) && $field_desc['value
']) {
943 $sql .= "(".$field_desc['value
'].")";
945 if ($field_desc['null'] == 'not
null' || $field_desc['null'] == 'NOT NULL
') {
946 // We will try to change format of column to NOT NULL. To be sure the ALTER works, we try to update fields that are NULL
947 if ($field_desc['type'] == 'varchar
' || $field_desc['type'] == 'text
') {
948 $sqlbis = "UPDATE ".$table." SET ".$field_name." = '".$this->escape($field_desc['default'] ? $field_desc['default'] : '')."' WHERE ".$field_name." IS NULL";
949 $this->query($sqlbis);
950 } elseif ($field_desc['type'] == 'tinyint
' || $field_desc['type'] == 'int') {
951 $sqlbis = "UPDATE ".$table." SET ".$field_name." = ".((int) $this->escape($field_desc['default'] ? $field_desc['default'] : 0))." WHERE ".$field_name." IS NULL";
952 $this->query($sqlbis);
958 if ($field_desc['default'] != '') {
959 if ($field_desc['type'] == 'double' || $field_desc['type'] == 'tinyint
' || $field_desc['type'] == 'int') {
960 $sql .= " DEFAULT ".$this->escape($field_desc['default']);
961 } elseif ($field_desc['type'] != 'text
') {
962 $sql .= " DEFAULT '".$this->escape($field_desc['default'])."'"; // Default not supported on text fields
966 dol_syslog(get_class($this)."::DDLUpdateField ".$sql, LOG_DEBUG);
967 if (!$this->query($sql)) {
974 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
982 public function DDLDropField($table, $field_name)
985 $tmp_field_name = preg_replace('/[^a-z0-9\.\-\_]/i
', '', $field_name);
987 $sql = "ALTER TABLE ".$table." DROP COLUMN `".$tmp_field_name."`";
988 if ($this->query($sql)) {
991 $this->error = $this->lasterror();
996 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1006 public function DDLCreateUser($dolibarr_main_db_host, $dolibarr_main_db_user, $dolibarr_main_db_pass, $dolibarr_main_db_name)
1009 $sql = "CREATE USER '".$this->escape($dolibarr_main_db_user)."' IDENTIFIED BY '".$this->escape($dolibarr_main_db_pass)."'";
1010 dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG); // No sql to avoid password in log
1011 $resql = $this->query($sql);
1013 if ($this->lasterrno != 'DB_ERROR_USER_ALREADY_EXISTS
') {
1016 // If user already exists, we continue to set permissions
1017 dol_syslog(get_class($this)."::DDLCreateUser sql=".$sql, LOG_WARNING);
1021 // Redo with localhost forced (sometimes user is created on %)
1022 $sql = "CREATE USER '".$this->escape($dolibarr_main_db_user)."'@'localhost
' IDENTIFIED BY '".$this->escape($dolibarr_main_db_pass)."'";
1023 $resql = $this->query($sql);
1025 $sql = "GRANT ALL PRIVILEGES ON ".$this->escape($dolibarr_main_db_name).".* TO '".$this->escape($dolibarr_main_db_user)."'@'".$this->escape($dolibarr_main_db_host)."'";
1026 dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG); // No sql to avoid password in log
1027 $resql = $this->query($sql);
1029 $this->error = "Connected user not allowed to GRANT ALL PRIVILEGES ON ".$this->escape($dolibarr_main_db_name).".* TO '".$this->escape($dolibarr_main_db_user)."'@'".$this->escape($dolibarr_main_db_host)."'";
1033 $sql = "FLUSH Privileges";
1035 dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG);
1036 $resql = $this->query($sql);
1051 public function getDefaultCharacterSetDatabase()
1053 $resql = $this->query('SHOW VARIABLES LIKE \
'character_set_database\'');
1056 return $this->forcecharset;
1059 $tmpval = $liste[
'Value'];
1076 $liste[$i][
'charset'] = $obj->Charset;
1077 $liste[$i][
'description'] = $obj->Description;
1096 $resql = $this->
query(
'SHOW VARIABLES LIKE \'collation_database\'');
1099 return $this->forcecollate;
1102 $tmpval = $liste[
'Value'];
1119 $liste[$i][
'collation'] = $obj->Collation;
1137 $fullpathofdump =
'/pathtomysqldump/mysqldump';
1139 $resql = $this->
query(
'SHOW VARIABLES LIKE \'basedir\'');
1142 $basedir = $liste[
'Value'];
1143 $fullpathofdump = $basedir.(preg_match(
'/\/$/', $basedir) ?
'' :
'/').
'bin/mysqldump';
1145 return $fullpathofdump;
1155 $fullpathofimport =
'/pathtomysql/mysql';
1157 $resql = $this->
query(
'SHOW VARIABLES LIKE \'basedir\'');
1160 $basedir = $liste[
'Value'];
1161 $fullpathofimport = $basedir.(preg_match(
'/\/$/', $basedir) ?
'' :
'/').
'bin/mysql';
1163 return $fullpathofimport;
1176 $sql =
'SHOW VARIABLES';
1178 $sql .=
" LIKE '".$this->escape($filter).
"'";
1183 $result[$obj->Variable_name] = $obj->Value;
1200 $sql =
'SHOW STATUS';
1202 $sql .=
" LIKE '".$this->escape($filter).
"'";
1207 $result[$obj->Variable_name] = $obj->Value;