Ver Fonte

fixed sql syntax for postgres

Dmitriev Roman há 3 meses atrás
pai
commit
6dccb06854
5 ficheiros alterados com 114 adições e 49 exclusões
  1. 27 7
      html/inc/common.php
  2. 30 23
      html/inc/sql.php
  3. 2 2
      install-eye.sh
  4. 51 13
      scripts/eyelib/common.pm
  5. 4 4
      scripts/hmonitor.pl

+ 27 - 7
html/inc/common.php

@@ -2837,22 +2837,42 @@ function apply_device_lock($db, $device_id, $iteration = 0)
     if ($iteration > 2) {
         return false;
     }
-    $dev = get_record_sql($db, 'SELECT discovery_locked,UNIX_TIMESTAMP(locked_timestamp) as u_locked_timestamp FROM devices WHERE id=' . $device_id . ' AND discovery_locked > 0');
-    if (empty($dev) or empty($dev['u_locked_timestamp'])) {
+
+    // Извлекаем исходную временную метку (без UNIX_TIMESTAMP)
+    $dev = get_record_sql($db, 'SELECT discovery_locked, locked_timestamp FROM devices WHERE id = ? AND discovery_locked > 0', [$device_id]);
+
+    // Проверяем, есть ли запись и валидна ли временная метка
+    if (empty($dev) || empty($dev['locked_timestamp']) || $dev['locked_timestamp'] === '0000-00-00 00:00:00') {
         LOG_DEBUG($db, "Snmp discovery lock not found. Set and discovery.");
         return set_lock_discovery($db, $device_id);
     }
-    //wait for discovery
+
+    // Преобразуем строку даты в Unix timestamp
+    try {
+        // Удаляем микросекунды (если есть, как в PostgreSQL)
+        $ts_str = preg_replace('/\.\d+$/', '', $dev['locked_timestamp']);
+        $dt = new DateTime($ts_str);
+        $u_locked_timestamp = $dt->getTimestamp();
+    } catch (Exception $e) {
+        // Если парсинг не удался — считаем блокировку недействительной
+        LOG_DEBUG($db, "Invalid lock timestamp format. Resetting lock.");
+        return set_lock_discovery($db, $device_id);
+    }
+
     $now = time();
-    $wait_time = ($dev['u_locked_timestamp'] + SNMP_LOCK_TIMEOUT) - $now;
-    LOG_DEBUG($db, "Check snmp lock for device id: " . $device_id . ". Lock timestamp: " . $dev['u_locked_timestamp'] . ", now: " . $now);
-    if ($wait_time < 0) {
+    $wait_time = ($u_locked_timestamp + SNMP_LOCK_TIMEOUT) - $now;
+
+    LOG_DEBUG($db, "Check snmp lock for device id: " . $device_id . ". Lock timestamp: " . $u_locked_timestamp . ", now: " . $now);
+
+    if ($wait_time <= 0) {
         LOG_DEBUG($db, "The lock is already expired. Set new lock.");
         return set_lock_discovery($db, $device_id);
     }
+
     LOG_VERBOSE($db, "Snmp discovery lock for device id: $device_id found! Need wait " . $wait_time . " sec.");
     sleep($wait_time);
-    LOG_VERBOSE($db, "Try set new lock and continue discovery for device id:" . $device_id);
+    LOG_VERBOSE($db, "Try set new lock and continue discovery for device id: " . $device_id);
+
     return apply_device_lock($db, $device_id, $iteration);
 }
 

+ 30 - 23
html/inc/sql.php

@@ -518,55 +518,62 @@ function get_records($db, $table, $filter = '') {
 
 /**
  * Получить одну запись по произвольному SQL-запросу
+ *
+ * @param PDO $db
+ * @param string $sql
+ * @param array|null $params
+ * @return array|null
  */
-function get_record_sql($db, $sql) {
+function get_record_sql($db, $sql, $params = null) {
     if (empty($sql)) {
         return null;
     }
-    
-    // Добавляем LIMIT 1, если его нет
-    if (!preg_match('/\bLIMIT\s+\d+$/i', $sql)) {
+
+    // Добавляем LIMIT 1, если его нет (только если нет параметризованных запросов!)
+    // Важно: не трогаем запрос, если он уже содержит LIMIT с placeholder'ом
+    if (!preg_match('/\bLIMIT\s+(\?|\d+)/i', $sql) && !preg_match('/\bLIMIT\s+\d+\s*(?:OFFSET\s+\d+)?\s*$/i', $sql)) {
         $sql .= " LIMIT 1";
     }
-    
-    $result = get_records_sql($db, $sql);
-    
-    // Возвращаем первую запись или null
+
+    $result = get_records_sql($db, $sql, $params);
+
     return !empty($result) ? $result[0] : null;
 }
 
 /**
  * Получить несколько записей по произвольному SQL-запросу
+ *
+ * @param PDO $db
+ * @param string $sql
+ * @param array|null $params
+ * @return array
  */
-function get_records_sql($db, $sql) {
-    $result = [];
-    
+function get_records_sql($db, $sql, $params = null) {
     if (empty($sql)) {
-        return $result;
+        return [];
     }
-    
+
     try {
-        $stmt = $db->query($sql);
+        $stmt = $db->prepare($sql);
+        $stmt->execute($params ?: []);
         $records = $stmt->fetchAll(PDO::FETCH_ASSOC);
-        
+
         if (!empty($records)) {
-            $result = normalize_records($records);
+            return normalize_records($records);
         }
-        
-        return $result;
-        
+
+        return [];
     } catch (PDOException $e) {
         LOG_ERROR($db, "SQL: $sql : " . $e->getMessage());
-        return $result;
+        return [];
     }
 }
 
-
 /**
  * Получить одно значение поля по SQL-запросу
  */
-function get_single_field($db, $sql) {
-    $record = get_record_sql($db, $sql);
+function get_single_field($db, $sql, $params = null) {
+    $record = get_record_sql($db, $sql, $params);
     
     if (!empty($record) && is_array($record)) {
         // Получаем первое значение из записи

+ 2 - 2
install-eye.sh

@@ -280,7 +280,7 @@ install_deps_altlinux() {
             perl-Net-Netmask perl-Text-Iconv perl-Net-SNMP \
             perl-Net-Telnet perl-DBI \
             perl-Parallel-ForkManager perl-Proc-Daemon \
-            perl-DateTime-Format-DateParse \
+            perl-DateTime-Format-DateParse perl-DateTime-Format-Strptime \
             perl-Net-OpenSSH perl-File-Tail \
             perl-Crypt-Rijndael perl-Crypt-CBC perl-CryptX perl-Crypt-DES \
             perl-File-Path-Tiny perl-Expect perl-Proc-ProcessTable
@@ -344,7 +344,7 @@ install_deps_debian() {
             libtext-iconv-perl libnet-snmp-perl libnet-telnet-perl \
             libdbi-perl libparallel-forkmanager-perl libproc-daemon-perl \
             libdatetime-format-dateparse-perl libnetwork-ipv4addr-perl \
-            libnet-openssh-perl libfile-tail-perl \
+            libnet-openssh-perl libfile-tail-perl libdatetime-format-strptime-perl \
             libcrypt-rijndael-perl libcrypt-cbc-perl libcryptx-perl \
             libcrypt-des-perl libfile-path-tiny-perl libexpect-perl
 

+ 51 - 13
scripts/eyelib/common.pm

@@ -699,22 +699,60 @@ if ($fqdn ne '' and !$dynamic_ok) {
 
 #------------------------------------------------------------------------------------------------------------
 
+use DateTime::Format::Strptime;
+
 sub apply_device_lock {
     my $db = shift;
     my $device_id = shift;
     my $iteration = shift || 0;
     $iteration++;
-    if ($iteration>2) { return 0; }
-    my $dev = get_record_sql($db,"SELECT discovery_locked, locked_timestamp, UNIX_TIMESTAMP(locked_timestamp) as u_locked_timestamp  FROM devices WHERE id=".$device_id);
+    if ($iteration > 2) { return 0; }
+
+    my $dev = get_record_sql($db, "SELECT discovery_locked, locked_timestamp FROM devices WHERE id = " . int($device_id));
+
     if (!$dev) { return 0; }
-    if (!$dev->{'discovery_locked'}) { return set_lock_discovery($db,$device_id); }
-    #if timestamp undefined, set and return
-    if (!$dev->{'locked_timestamp'}) { return set_lock_discovery($db,$device_id); }
-    #wait for discovery
-    my $wait_time = $dev->{'locked_timestamp'} + 30 - time();
-    if ($wait_time<0) { return set_lock_discovery($db,$device_id); }
+
+    if (!$dev->{'discovery_locked'}) {
+        return set_lock_discovery($db, $device_id);
+    }
+
+    my $ts_str = $dev->{'locked_timestamp'};
+
+    # Если locked_timestamp NULL или пустой — устанавливаем блокировку
+    if (!defined $ts_str || $ts_str eq '' || $ts_str eq '0000-00-00 00:00:00') {
+        return set_lock_discovery($db, $device_id);
+    }
+
+    # Удаляем микросекунды (PostgreSQL) для совместимости с форматом
+    $ts_str =~ s/\.\d+$//;
+
+    # Парсим строку в DateTime
+    my $parser = DateTime::Format::Strptime->new(
+        pattern   => '%Y-%m-%d %H:%M:%S',
+        on_error  => 'croak',
+    );
+
+    my $dt;
+    eval {
+        $dt = $parser->parse_datetime($ts_str);
+    };
+
+    if ($@ || !$dt) {
+        # Ошибка парсинга — считаем блокировку недействительной
+        return set_lock_discovery($db, $device_id);
+    }
+
+    # Получаем Unix timestamp
+    my $u_locked_timestamp = $dt->epoch;
+
+    # Ждём окончания блокировки (30 секунд)
+    my $wait_time = ($u_locked_timestamp + 30) - time();
+    if ($wait_time <= 0) {
+        return set_lock_discovery($db, $device_id);
+    }
+
     sleep($wait_time);
-    return apply_device_lock($db,$device_id,$iteration);
+    return apply_device_lock($db, $device_id, $iteration);
 }
 
 #------------------------------------------------------------------------------------------------------------
@@ -1098,7 +1136,7 @@ my $ip_aton=$ip_record->{ip_aton};
 
 my $timestamp=GetNowTime();
 
-my $record=get_record_sql($db,'SELECT * FROM user_auth WHERE deleted=0 AND ip_int='.$ip_aton.' AND mac="'.$mac.'"');
+my $record=get_record_sql($db,'SELECT * FROM user_auth WHERE deleted=0 AND ip_int='.$ip_aton." AND mac='".$mac."'");
 
 my $new_record;
 $new_record->{last_found}=$timestamp;
@@ -1361,9 +1399,9 @@ return $list_ref;
 sub get_device_by_ip {
 my $db = shift;
 my $ip = shift;
-my $netdev=get_record_sql($db,'SELECT * FROM devices WHERE ip="'.$ip.'"');
+my $netdev=get_record_sql($db,"SELECT * FROM devices WHERE ip='".$ip."'");
 if ($netdev and $netdev->{id}>0) { return $netdev; }
-my $auth_rec=get_record_sql($db,'SELECT user_id FROM user_auth WHERE ip="'.$ip.'" and deleted=0');
+my $auth_rec=get_record_sql($db,"SELECT user_id FROM user_auth WHERE ip='".$ip."' and deleted=0");
 if ($auth_rec and $auth_rec->{user_id}>0) {
     $netdev=get_record_sql($db,'SELECT * FROM devices WHERE user_id='.$auth_rec->{user_id});
     return $netdev;
@@ -1519,7 +1557,7 @@ $dhcp_record->{'remote_id'} = $remote_id;
 $dhcp_record->{'hotspot'}=is_hotspot($dbh,$dhcp_record->{ip});
 
 #search actual record
-my $auth_record = get_record_sql($db,'SELECT * FROM user_auth WHERE ip="'.$dhcp_record->{ip}.'" and mac="'.$mac.'" and deleted=0 ORDER BY last_found DESC');
+my $auth_record = get_record_sql($db,"SELECT * FROM user_auth WHERE ip='".$dhcp_record->{ip}."' and mac='".$mac."' and deleted=0 ORDER BY last_found DESC");
 
 #if record not found and type del => next event
 if (!$auth_record and $type eq 'del') { return; }

+ 4 - 4
scripts/hmonitor.pl

@@ -121,7 +121,7 @@ my $login;
 my $nagios_handler;
 
 if (!$hostid or $hostid !~ /^[0-9]/) {
-    $auth = get_record_sql($hdb,'SELECT * FROM user_auth WHERE deleted=0 AND ip="'.$hostip.'"');
+    $auth = get_record_sql($hdb,"SELECT * FROM user_auth WHERE deleted=0 AND ip='".$hostip."'");
     next if (!$auth);
     $hostid = $auth->{id};
     $login = get_record_sql($hdb,'SELECT * FROM user_list WHERE id='.$auth->{user_id});
@@ -132,7 +132,7 @@ if (!$hostid or $hostid !~ /^[0-9]/) {
     if ($hosttype=~/device/i) {
         $device = get_record_sql($hdb,'SELECT * FROM devices WHERE id='.$hostid);
         $login = get_record_sql($hdb,'SELECT * FROM user_list WHERE id='.$device->{user_id});
-        $auth = get_record_sql($hdb,'SELECT * FROM user_auth WHERE user_id='.$device->{user_id}.' AND deleted=0 AND ip="'.$hostip.'"');
+        $auth = get_record_sql($hdb,'SELECT * FROM user_auth WHERE user_id='.$device->{user_id}." AND deleted=0 AND ip='".$hostip."'");
         if ($device->{nagios_status}) { $old_state = $device->{nagios_status}; }
         } else {
         $auth = get_record_sql($hdb,'SELECT * FROM user_auth WHERE id='.$hostid);
@@ -154,8 +154,8 @@ if ($hoststate ne $old_state) {
     #Change device state
     db_log_verbose($hdb,"Host changed! $hostname [$hostip] => $hoststate, old: $old_state");
     my $ip_aton=StrToIp($hostip);
-    if ($device->{id}) { do_sql($hdb,'UPDATE devices SET nagios_status="'.$hoststate.'" WHERE id='.$device->{id}); }
-    if ($auth->{id}) { do_sql($hdb,'UPDATE user_auth SET nagios_status="'.$hoststate.'" WHERE id='.$auth->{id}); }
+    if ($device->{id}) { do_sql($hdb,"UPDATE devices SET nagios_status='".$hoststate."' WHERE id=".$device->{id}); }
+    if ($auth->{id}) { do_sql($hdb,"UPDATE user_auth SET nagios_status='".$hoststate."' WHERE id=".$auth->{id}); }
     if ($hoststate=~/UP/i) {
         nagios_host_svc_enable($hostname,1);
         db_log_debug($hdb,"Enable notifications for host $hostname [$hostip] id: $hostid services");