使用 odbc 数据库驱动程序的 codeigniter 出现问题

发布于 2024-08-30 13:21:46 字数 360 浏览 1 评论 0原文

我在使用 codeigniter 的 odbc 驱动程序时遇到了一个奇怪的问题。 我正在使用 FreeTDS 从 Linux 计算机连接到 MSSQL 2008 计算机。

虽然我知道 'num_rows' 函数总是返回 -1,这完全是数据库/驱动程序问题 - 由于某种原因,当我尝试创建 -> result() 时,整个应用程序崩溃(错误 500,有时只是一个空白页),如果幸运的话,我会收到一条错误消息,通知我应用程序已终止,因为它试图分配 2 TB 内存(!)。

这种情况不定期发生,即:每隔几次刷新。有时它运行良好,有时页面返回错误 500,有时它给出内存分配错误 - 无论如何,它并不是真正可以精确重现的东西,并且查询非常简单。

有人有想法吗?

i’ve run into a curious problem with codeigniter's odbc driver.
i’m connecting from a linux machine to an MSSQL 2008 machine using FreeTDS.

while i get that the ‘num_rows’ function always returns -1, and that is fully a database/driver issue - for some reason when i try to create a ->result(), the whole application crashes (error 500, sometimes just a blank page), if i’m lucky, i get an error message informing me that the application died because it tried to allocated 2 terrabytes of memory(!).

This happens irregularly, ie: every few refreshes. sometimes it runs fine, sometimes the page returns error 500 and sometimes it gives the memory allocation error - in any case it’s not really something that can be reproduced with percision, and the queries are SUPER simple.

ideas anyone?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夜无邪 2024-09-06 13:21:46

哈哈,我也遇到过这种情况! 我已向开发人员投诉,他们忽略了我

当您调用 result() 时,它将循环遍历每个可能的结果,并将记录存储到一个巨大的内部数组中。请参阅 result_object() 和 result_array() 末尾的 system/database/DB_result.php while 循环

有三种修复方法。

简单的方法:

LIMIT(或TOP in MSSQL) SQL 查询中的结果。

SELECT TOP(100) * FROM Table

更新的无缓冲方式:

使用引入的unbuffered_row()函数< /a> 这个问题提出两年后。

$query = $this->db->query($sql);
// not $query->result() because that loads everything into an internal array.
// and not $query->first_row() because it does the same thing (as of 2013-04-02)
while ($record = $query->unbuffered_row('array')) { 
    // code...
}

困难的方法:

使用使用 PHP5 迭代器的正确结果对象(开发人员不喜欢它,因为它排除了 php4)。在 DB_result.php 文件中添加类似这样的内容:

-class CI_DB_result {
+class CI_DB_result implements Iterator {

    var $conn_id        = NULL;
    var $result_id      = NULL;
    var $result_array   = array();
    var $result_object  = array();
-   var $current_row    = 0;
+   var $current_row    = -1;
    var $num_rows       = 0;
    var $row_data       = NULL;
+   var $valid          = FALSE;


    /**
    function _fetch_assoc() { return array(); } 
    function _fetch_object() { return array(); }

+   /**
+    * Iterator implemented functions
+    * http://us2.php.net/manual/en/class.iterator.php
+    */
+   
+   /**
+    * Rewind the database back to the first record
+    *
+    */
+   function rewind()
+   {
+       if ($this->result_id !== FALSE AND $this->num_rows() != 0) {
+           $this->_data_seek(0);
+           $this->valid = TRUE;
+           $this->current_row = -1;
+       }
+   }
+   
+   /**
+    * Return the current row record.
+    *
+    */
+   function current()
+   {
+       if ($this->current_row == -1) {
+           $this->next();
+       }
+       return $this->row_data;
+   }
+   
+   /**
+    * The current row number from the result
+    *
+    */
+   function key()
+   {
+       return $this->current_row;
+   }
+   
+   /**
+    * Go to the next result.
+    *
+    */
+   function next()
+   {
+       $this->row_data = $this->_fetch_object();
+       if ($this->row_data) {
+           $this->current_row++;
+           if (!$this->valid)
+               $this->valid = TRUE;
+           return TRUE;
+       } else {
+           $this->valid = FALSE;
+           return FALSE;
+       }
+   }
+   
+   /**
+    * Is the current_row really a record?
+    *
+    */
+   function valid()
+   {
+       return $this->valid;
+   }
+   
 }
 // END DB_result class

然后使用它,而不是调用 $query->result() 你只使用没有 ->result() 的对象 位于末尾,如 $query。所有内部 CI 内容仍然适用于 result()

$query = $this->db->query($sql);
foreach ($query as $record) { // not $query->result() because that loads everything into an internal array.
    // code...
}

顺便说一句,我的迭代器代码与他们的代码一起使用,整个 -1 事情存在一些逻辑问题,所以不要同时使用 $query->result()$query< /code> 在同一个对象上。如果有人想解决这个问题,那你就太棒了。

Ha ha, this happend to me too! And I've complained to the devs about it, and they ignored me.

When you call result(), it will loop through every single possible result, and store the record into a massive internal array. See system/database/DB_result.php while loop at the end of result_object() and result_array()

There are three ways of fixing it.

The easy way:

LIMIT (or TOP in MSSQL) your results in the SQL query.

SELECT TOP(100) * FROM Table

The UPDATED unbuffered way:

Use the unbuffered_row() function that was introduced 2 years after this question was asked.

$query = $this->db->query($sql);
// not $query->result() because that loads everything into an internal array.
// and not $query->first_row() because it does the same thing (as of 2013-04-02)
while ($record = $query->unbuffered_row('array')) { 
    // code...
}

The hard way:

Use a proper result object that uses PHP5 iterators (that the devs don't like because it excludes php4). Slap something like this in your DB_result.php file:

-class CI_DB_result {
+class CI_DB_result implements Iterator {

    var $conn_id        = NULL;
    var $result_id      = NULL;
    var $result_array   = array();
    var $result_object  = array();
-   var $current_row    = 0;
+   var $current_row    = -1;
    var $num_rows       = 0;
    var $row_data       = NULL;
+   var $valid          = FALSE;


    /**
    function _fetch_assoc() { return array(); } 
    function _fetch_object() { return array(); }

+   /**
+    * Iterator implemented functions
+    * http://us2.php.net/manual/en/class.iterator.php
+    */
+   
+   /**
+    * Rewind the database back to the first record
+    *
+    */
+   function rewind()
+   {
+       if ($this->result_id !== FALSE AND $this->num_rows() != 0) {
+           $this->_data_seek(0);
+           $this->valid = TRUE;
+           $this->current_row = -1;
+       }
+   }
+   
+   /**
+    * Return the current row record.
+    *
+    */
+   function current()
+   {
+       if ($this->current_row == -1) {
+           $this->next();
+       }
+       return $this->row_data;
+   }
+   
+   /**
+    * The current row number from the result
+    *
+    */
+   function key()
+   {
+       return $this->current_row;
+   }
+   
+   /**
+    * Go to the next result.
+    *
+    */
+   function next()
+   {
+       $this->row_data = $this->_fetch_object();
+       if ($this->row_data) {
+           $this->current_row++;
+           if (!$this->valid)
+               $this->valid = TRUE;
+           return TRUE;
+       } else {
+           $this->valid = FALSE;
+           return FALSE;
+       }
+   }
+   
+   /**
+    * Is the current_row really a record?
+    *
+    */
+   function valid()
+   {
+       return $this->valid;
+   }
+   
 }
 // END DB_result class

Then to use it, instead of calling $query->result() you use just the object without the ->result() on the end like $query. And all the internal CI stuff still works with result().

$query = $this->db->query($sql);
foreach ($query as $record) { // not $query->result() because that loads everything into an internal array.
    // code...
}

By the way, my Iterator code working with their code has some logic problems with the whole -1 thing, so don't use both $query->result() and $query on the same object. If someone wants to fix that, you are awesome.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文