Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 2 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
/**
18
 * sqlsrv specific recordset.
19
 *
20
 * @package    core_dml
21
 * @copyright  2009 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v2 or later
23
 */
24
 
25
defined('MOODLE_INTERNAL') || die();
26
 
27
require_once(__DIR__.'/moodle_recordset.php');
28
 
29
class sqlsrv_native_moodle_recordset extends moodle_recordset {
30
 
31
    protected $rsrc;
32
    protected $current;
33
 
34
    /** @var array recordset buffer */
35
    protected $buffer = null;
36
 
37
    /** @var sqlsrv_native_moodle_database */
38
    protected $db;
39
 
40
    public function __construct($rsrc, sqlsrv_native_moodle_database $db) {
41
        $this->rsrc    = $rsrc;
42
        $this->current = $this->fetch_next();
43
        $this->db      = $db;
44
    }
45
 
46
    /**
47
     * Inform existing open recordsets that transaction
48
     * is starting, this works around MARS problem described
49
     * in MDL-37734.
50
     */
51
    public function transaction_starts() {
52
        if ($this->buffer !== null) {
53
            $this->unregister();
54
            return;
55
        }
56
        if (!$this->rsrc) {
57
            $this->unregister();
58
            return;
59
        }
60
        // This might eat memory pretty quickly...
61
        raise_memory_limit('2G');
62
        $this->buffer = array();
63
 
64
        while($next = $this->fetch_next()) {
65
            $this->buffer[] = $next;
66
        }
67
    }
68
 
69
    /**
70
     * Unregister recordset from the global list of open recordsets.
71
     */
72
    private function unregister() {
73
        if ($this->db) {
74
            $this->db->recordset_closed($this);
75
            $this->db = null;
76
        }
77
    }
78
 
79
    public function __destruct() {
80
        $this->close();
81
    }
82
 
83
    private function fetch_next() {
84
        if (!$this->rsrc) {
85
            return false;
86
        }
87
        if (!$row = sqlsrv_fetch_array($this->rsrc, SQLSRV_FETCH_ASSOC)) {
88
            if (is_resource($this->rsrc)) {
89
                // We need to make sure that the statement resource is in the correct type before freeing it.
90
                sqlsrv_free_stmt($this->rsrc);
91
            }
92
            $this->rsrc = null;
93
            $this->unregister();
94
            return false;
95
        }
96
 
97
        unset($row['sqlsrvrownumber']);
98
        $row = array_change_key_case($row, CASE_LOWER);
99
        // Moodle expects everything from DB as strings.
100
        foreach ($row as $k=>$v) {
101
            if (is_null($v)) {
102
                continue;
103
            }
104
            if (!is_string($v)) {
105
                $row[$k] = (string)$v;
106
            }
107
        }
108
        return $row;
109
    }
110
 
111
    public function current(): stdClass {
112
        return (object)$this->current;
113
    }
114
 
115
    #[\ReturnTypeWillChange]
116
    public function key() {
117
        // return first column value as key
118
        if (!$this->current) {
119
            return false;
120
        }
121
        $key = reset($this->current);
122
        return $key;
123
    }
124
 
125
    public function next(): void {
126
        if ($this->buffer === null) {
127
            $this->current = $this->fetch_next();
128
        } else {
129
            $this->current = array_shift($this->buffer);
130
        }
131
    }
132
 
133
    public function valid(): bool {
134
        return !empty($this->current);
135
    }
136
 
137
    public function close() {
138
        if ($this->rsrc) {
139
            if (is_resource($this->rsrc)) {
140
                // We need to make sure that the statement resource is in the correct type before freeing it.
141
                sqlsrv_free_stmt($this->rsrc);
142
            }
143
            $this->rsrc  = null;
144
        }
145
        $this->current = null;
146
        $this->buffer  = null;
147
        $this->unregister();
148
    }
149
}