1<?php
2
3namespace Safe;
4
5use Safe\Exceptions\MssqlException;
6
7/**
8 * Binds a parameter to a stored procedure or a remote stored procedure.
9 *
10 * @param resource $stmt Statement resource, obtained with mssql_init.
11 * @param string $param_name The parameter name, as a string.
12 *
13 * You have to include the @ character, like in the
14 * T-SQL syntax. See the explanation included in
15 * mssql_execute.
16 * @param mixed $var The PHP variable you'll bind the MSSQL parameter to. It is passed by
17 * reference, to retrieve OUTPUT and RETVAL values after
18 * the procedure execution.
19 * @param int $type One of: SQLTEXT,
20 * SQLVARCHAR, SQLCHAR,
21 * SQLINT1, SQLINT2,
22 * SQLINT4, SQLBIT,
23 * SQLFLT4, SQLFLT8,
24 * SQLFLTN.
25 * @param bool $is_output Whether the value is an OUTPUT parameter or not. If it's an OUTPUT
26 * parameter and you don't mention it, it will be treated as a normal
27 * input parameter and no error will be thrown.
28 * @param bool $is_null Whether the parameter is NULL or not. Passing the NULL value as
29 * var will not do the job.
30 * @param int $maxlen Used with char/varchar values. You have to indicate the length of the
31 * data so if the parameter is a varchar(50), the type must be
32 * SQLVARCHAR and this value 50.
33 * @throws MssqlException
34 *
35 */
36function mssql_bind($stmt, string $param_name, &$var, int $type, bool $is_output = false, bool $is_null = false, int $maxlen = -1): void
37{
38    error_clear_last();
39    $result = \mssql_bind($stmt, $param_name, $var, $type, $is_output, $is_null, $maxlen);
40    if ($result === false) {
41        throw MssqlException::createFromPhpError();
42    }
43}
44
45
46/**
47 * Closes the link to a MS SQL Server database that's associated with the
48 * specified link identifier.  If the link identifier isn't specified, the
49 * last opened link is assumed.
50 *
51 * Note that this isn't usually necessary, as non-persistent open
52 * links are automatically closed at the end of the script's
53 * execution.
54 *
55 * @param resource $link_identifier A MS SQL link identifier, returned by
56 * mssql_connect.
57 *
58 * This function will not close persistent links generated by
59 * mssql_pconnect.
60 * @throws MssqlException
61 *
62 */
63function mssql_close($link_identifier = null): void
64{
65    error_clear_last();
66    if ($link_identifier !== null) {
67        $result = \mssql_close($link_identifier);
68    } else {
69        $result = \mssql_close();
70    }
71    if ($result === false) {
72        throw MssqlException::createFromPhpError();
73    }
74}
75
76
77/**
78 * mssql_connect establishes a connection to a
79 * MS SQL server.
80 *
81 * The link to the server will be closed as soon as the execution of
82 * the script ends, unless it's closed earlier by explicitly calling
83 * mssql_close.
84 *
85 * @param string $servername The MS SQL server. It can also include a port number, e.g.
86 * hostname:port (Linux), or
87 * hostname,port (Windows).
88 * @param string $username The username.
89 * @param string $password The password.
90 * @param bool $new_link If a second call is made to mssql_connect with the
91 * same arguments, no new link will be established, but instead, the link
92 * identifier of the already opened link will be returned. This parameter
93 * modifies this behavior and makes mssql_connect
94 * always open a new link, even if mssql_connect was
95 * called before with the same parameters.
96 * @return resource Returns a MS SQL link identifier on success.
97 * @throws MssqlException
98 *
99 */
100function mssql_connect(string $servername = null, string $username = null, string $password = null, bool $new_link = false)
101{
102    error_clear_last();
103    if ($new_link !== false) {
104        $result = \mssql_connect($servername, $username, $password, $new_link);
105    } elseif ($password !== null) {
106        $result = \mssql_connect($servername, $username, $password);
107    } elseif ($username !== null) {
108        $result = \mssql_connect($servername, $username);
109    } elseif ($servername !== null) {
110        $result = \mssql_connect($servername);
111    } else {
112        $result = \mssql_connect();
113    }
114    if ($result === false) {
115        throw MssqlException::createFromPhpError();
116    }
117    return $result;
118}
119
120
121/**
122 * mssql_data_seek moves the internal row
123 * pointer of the MS SQL result associated with the specified result
124 * identifier to point to the specified row number, first row being
125 * number 0. The next call to mssql_fetch_row
126 * would return that row.
127 *
128 * @param resource $result_identifier The result resource that is being evaluated.
129 * @param int $row_number The desired row number of the new result pointer.
130 * @throws MssqlException
131 *
132 */
133function mssql_data_seek($result_identifier, int $row_number): void
134{
135    error_clear_last();
136    $result = \mssql_data_seek($result_identifier, $row_number);
137    if ($result === false) {
138        throw MssqlException::createFromPhpError();
139    }
140}
141
142
143/**
144 * Returns the length of field no. offset in
145 * result.
146 *
147 * @param resource $result The result resource that is being evaluated. This result comes from a
148 * call to mssql_query.
149 * @param int $offset The field offset, starts at 0. If omitted, the current field is used.
150 * @return int The length of the specified field index on success.
151 * @throws MssqlException
152 *
153 */
154function mssql_field_length($result, int $offset = -1): int
155{
156    error_clear_last();
157    $result = \mssql_field_length($result, $offset);
158    if ($result === false) {
159        throw MssqlException::createFromPhpError();
160    }
161    return $result;
162}
163
164
165/**
166 * Returns the name of field no. offset in
167 * result.
168 *
169 * @param resource $result The result resource that is being evaluated. This result comes from a
170 * call to mssql_query.
171 * @param int $offset The field offset, starts at 0. If omitted, the current field is used.
172 * @return string The name of the specified field index on success.
173 * @throws MssqlException
174 *
175 */
176function mssql_field_name($result, int $offset = -1): string
177{
178    error_clear_last();
179    $result = \mssql_field_name($result, $offset);
180    if ($result === false) {
181        throw MssqlException::createFromPhpError();
182    }
183    return $result;
184}
185
186
187/**
188 * Seeks to the specified field offset.  If the next call to
189 * mssql_fetch_field won't include a field
190 * offset, this field would be returned.
191 *
192 * @param resource $result The result resource that is being evaluated. This result comes from a
193 * call to mssql_query.
194 * @param int $field_offset The field offset, starts at 0.
195 * @throws MssqlException
196 *
197 */
198function mssql_field_seek($result, int $field_offset): void
199{
200    error_clear_last();
201    $result = \mssql_field_seek($result, $field_offset);
202    if ($result === false) {
203        throw MssqlException::createFromPhpError();
204    }
205}
206
207
208/**
209 * Returns the type of field no. offset in
210 * result.
211 *
212 * @param resource $result The result resource that is being evaluated. This result comes from a
213 * call to mssql_query.
214 * @param int $offset The field offset, starts at 0. If omitted, the current field is used.
215 * @return string The type of the specified field index on success.
216 * @throws MssqlException
217 *
218 */
219function mssql_field_type($result, int $offset = -1): string
220{
221    error_clear_last();
222    $result = \mssql_field_type($result, $offset);
223    if ($result === false) {
224        throw MssqlException::createFromPhpError();
225    }
226    return $result;
227}
228
229
230/**
231 * mssql_free_result only needs to be called
232 * if you are worried about using too much memory while your script
233 * is running. All result memory will automatically be freed when
234 * the script ends. You may call mssql_free_result
235 * with the result identifier as an argument and the associated
236 * result memory will be freed.
237 *
238 * @param resource $result The result resource that is being freed. This result comes from a
239 * call to mssql_query.
240 * @throws MssqlException
241 *
242 */
243function mssql_free_result($result): void
244{
245    error_clear_last();
246    $result = \mssql_free_result($result);
247    if ($result === false) {
248        throw MssqlException::createFromPhpError();
249    }
250}
251
252
253/**
254 * mssql_free_statement only needs to be called
255 * if you are worried about using too much memory while your script
256 * is running. All statement memory will automatically be freed when
257 * the script ends. You may call mssql_free_statement
258 * with the statement identifier as an argument and the associated
259 * statement memory will be freed.
260 *
261 * @param resource $stmt Statement resource, obtained with mssql_init.
262 * @throws MssqlException
263 *
264 */
265function mssql_free_statement($stmt): void
266{
267    error_clear_last();
268    $result = \mssql_free_statement($stmt);
269    if ($result === false) {
270        throw MssqlException::createFromPhpError();
271    }
272}
273
274
275/**
276 * Initializes a stored procedure or a remote stored procedure.
277 *
278 * @param string $sp_name Stored procedure name, like ownew.sp_name or
279 * otherdb.owner.sp_name.
280 * @param resource $link_identifier A MS SQL link identifier, returned by
281 * mssql_connect.
282 * @return resource Returns a resource identifier "statement", used in subsequent calls to
283 * mssql_bind and mssql_executes.
284 * @throws MssqlException
285 *
286 */
287function mssql_init(string $sp_name, $link_identifier = null)
288{
289    error_clear_last();
290    if ($link_identifier !== null) {
291        $result = \mssql_init($sp_name, $link_identifier);
292    } else {
293        $result = \mssql_init($sp_name);
294    }
295    if ($result === false) {
296        throw MssqlException::createFromPhpError();
297    }
298    return $result;
299}
300
301
302/**
303 * mssql_pconnect acts very much like
304 * mssql_connect with two major differences.
305 *
306 * First, when connecting, the function would first try to find a
307 * (persistent) link that's already open with the same host,
308 * username and password.  If one is found, an identifier for it
309 * will be returned instead of opening a new connection.
310 *
311 * Second, the connection to the SQL server will not be closed when
312 * the execution of the script ends.  Instead, the link will remain
313 * open for future use (mssql_close will not
314 * close links established by mssql_pconnect).
315 *
316 * This type of links is therefore called 'persistent'.
317 *
318 * @param string $servername The MS SQL server. It can also include a port number. e.g.
319 * hostname:port.
320 * @param string $username The username.
321 * @param string $password The password.
322 * @param bool $new_link If a second call is made to mssql_pconnect with
323 * the same arguments, no new link will be established, but instead, the
324 * link identifier of the already opened link will be returned. This
325 * parameter modifies this behavior and makes
326 * mssql_pconnect always open a new link, even if
327 * mssql_pconnect was called before with the same
328 * parameters.
329 * @return resource Returns a positive MS SQL persistent link identifier on success.
330 * @throws MssqlException
331 *
332 */
333function mssql_pconnect(string $servername = null, string $username = null, string $password = null, bool $new_link = false)
334{
335    error_clear_last();
336    if ($new_link !== false) {
337        $result = \mssql_pconnect($servername, $username, $password, $new_link);
338    } elseif ($password !== null) {
339        $result = \mssql_pconnect($servername, $username, $password);
340    } elseif ($username !== null) {
341        $result = \mssql_pconnect($servername, $username);
342    } elseif ($servername !== null) {
343        $result = \mssql_pconnect($servername);
344    } else {
345        $result = \mssql_pconnect();
346    }
347    if ($result === false) {
348        throw MssqlException::createFromPhpError();
349    }
350    return $result;
351}
352
353
354/**
355 * mssql_query sends a query to the currently active
356 * database on the server that's associated with the specified link
357 * identifier.
358 *
359 * @param string $query An SQL query.
360 * @param resource $link_identifier A MS SQL link identifier, returned by
361 * mssql_connect or
362 * mssql_pconnect.
363 *
364 * If the link identifier isn't specified, the last opened link is
365 * assumed.  If no link is open, the function tries to establish a link
366 * as if mssql_connect was called, and use it.
367 * @param int $batch_size The number of records to batch in the buffer.
368 * @return mixed Returns a MS SQL result resource on success, TRUE if no rows were
369 * returned.
370 * @throws MssqlException
371 *
372 */
373function mssql_query(string $query, $link_identifier = null, int $batch_size = 0)
374{
375    error_clear_last();
376    if ($batch_size !== 0) {
377        $result = \mssql_query($query, $link_identifier, $batch_size);
378    } elseif ($link_identifier !== null) {
379        $result = \mssql_query($query, $link_identifier);
380    } else {
381        $result = \mssql_query($query);
382    }
383    if ($result === false) {
384        throw MssqlException::createFromPhpError();
385    }
386    return $result;
387}
388
389
390/**
391 * mssql_select_db sets the current active
392 * database on the server that's associated with the specified link
393 * identifier.
394 *
395 * Every subsequent call to mssql_query will be
396 * made on the active database.
397 *
398 * @param string $database_name The database name.
399 *
400 * To escape the name of a database that contains spaces, hyphens ("-"),
401 * or any other exceptional characters, the database name must be
402 * enclosed in brackets, as is shown in the example, below. This
403 * technique must also be applied when selecting a database name that is
404 * also a reserved word (such as primary).
405 * @param resource $link_identifier A MS SQL link identifier, returned by
406 * mssql_connect or
407 * mssql_pconnect.
408 *
409 * If no link identifier is specified, the last opened link is assumed.
410 * If no link is open, the function will try to establish a link as if
411 * mssql_connect was called, and use it.
412 * @throws MssqlException
413 *
414 */
415function mssql_select_db(string $database_name, $link_identifier = null): void
416{
417    error_clear_last();
418    if ($link_identifier !== null) {
419        $result = \mssql_select_db($database_name, $link_identifier);
420    } else {
421        $result = \mssql_select_db($database_name);
422    }
423    if ($result === false) {
424        throw MssqlException::createFromPhpError();
425    }
426}
427