1 ;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
2 ;;;; *************************************************************************
3 ;;;; FILE IDENTIFICATION
5 ;;;; Name: mysql-api.lisp
6 ;;;; Purpose: Low-level MySQL interface using UFFI
7 ;;;; Programmers: Kevin M. Rosenberg based on
8 ;;;; Original code by Pierre R. Mai
9 ;;;; Date Started: Feb 2002
11 ;;;; This file, part of CLSQL, is Copyright (c) 2002-2009 by Kevin M. Rosenberg
12 ;;;; and Copyright (c) 1999-2001 by Pierre R. Mai
14 ;;;; CLSQL users are granted the rights to distribute and use this software
15 ;;;; as governed by the terms of the Lisp Lesser GNU Public License
16 ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
17 ;;;; *************************************************************************
21 ;;;; Modifications from original code
22 ;;;; - Updated C-structures to conform to structures in MySQL 3.23.46
23 ;;;; - Changed from CMUCL interface to UFFI
24 ;;;; - Added and call a C-helper file to support 64-bit integers
25 ;;;; that are used in a few routines.
26 ;;;; - Removed all references to interiors of C-structions, this will
27 ;;;; increase robustness when MySQL's internal structures change.
33 (uffi:def-foreign-type mysql-socket
:int
)
34 (uffi:def-foreign-type mysql-bool
:byte
)
35 (uffi:def-foreign-type mysql-byte
:unsigned-char
)
37 (uffi:def-enum mysql-net-type
42 (uffi:def-array-pointer mysql-row
(* :unsigned-char
))
45 (uffi:def-enum mysql-field-types
71 (uffi:def-enum mysql-option
79 (uffi:def-enum mysql-status
84 #+(or mysql-client-v4.1 mysql-client-v5
)
85 (uffi:def-enum mysql-field-types
90 ;;; Opaque pointers to mysql C-defined structures
91 (uffi:def-foreign-type mysql-mysql
(* :void
))
92 (uffi:def-foreign-type mysql-mysql-res
(* :void
))
93 (uffi:def-foreign-type mysql-field
(* :void
))
94 (uffi:def-foreign-type mysql-bind
(* :void
))
96 ;;;; The Foreign C routines
97 (declaim (inline mysql-init
))
98 (uffi:def-function
"mysql_init"
101 :returning mysql-mysql
)
103 ;; Need to comment this out for LW 4.2.6
104 ;; ? bug in LW version
105 #-lispworks
(declaim (inline mysql-real-connect
))
106 (uffi:def-function
"mysql_real_connect"
113 (unix-socket :cstring
)
114 (clientflag :unsigned-long
))
116 :returning mysql-mysql
)
118 (declaim (inline mysql-close
))
119 (uffi:def-function
"mysql_close"
124 (declaim (inline mysql-select-db
))
125 (uffi:def-function
"mysql_select_db"
131 (declaim (inline mysql-query
))
132 (uffi:def-function
"mysql_query"
138 ;;; I doubt that this function is really useful for direct Lisp usage,
139 ;;; but it is here for completeness...
141 (declaim (inline mysql-real-query
))
142 (uffi:def-function
"mysql_real_query"
145 (length :unsigned-int
))
149 (declaim (inline mysql-shutdown
))
150 (uffi:def-function
"mysql_shutdown"
151 ((mysql mysql-mysql
))
155 (declaim (inline mysql-dump-debug-info
))
156 (uffi:def-function
"mysql_dump_debug_info"
157 ((mysql mysql-mysql
))
161 (declaim (inline mysql-refresh
))
162 (uffi:def-function
"mysql_refresh"
164 (refresh-options :unsigned-int
))
168 (declaim (inline mysql-kill
))
169 (uffi:def-function
"mysql_kill"
171 (pid :unsigned-long
))
175 (declaim (inline mysql-ping
))
176 (uffi:def-function
"mysql_ping"
177 ((mysql mysql-mysql
))
181 (declaim (inline mysql-stat
))
182 (uffi:def-function
"mysql_stat"
183 ((mysql mysql-mysql
))
187 (declaim (inline mysql-get-server-info
))
188 (uffi:def-function
"mysql_get_server_info"
189 ((mysql mysql-mysql
))
193 (declaim (inline mysql-get-host-info
))
194 (uffi:def-function
"mysql_get_host_info"
195 ((mysql mysql-mysql
))
199 (declaim (inline mysql-get-proto-info
))
200 (uffi:def-function
"mysql_get_proto_info"
201 ((mysql mysql-mysql
))
203 :returning
:unsigned-int
)
205 (declaim (inline mysql-list-dbs
))
206 (uffi:def-function
"mysql_list_dbs"
210 :returning mysql-mysql-res
)
212 (declaim (inline mysql-list-tables
))
213 (uffi:def-function
"mysql_list_tables"
217 :returning mysql-mysql-res
)
219 (declaim (inline mysql-list-fields
))
220 (uffi:def-function
"mysql_list_fields"
225 :returning mysql-mysql-res
)
227 (declaim (inline mysql-list-processes
))
228 (uffi:def-function
"mysql_list_processes"
229 ((mysql mysql-mysql
))
231 :returning mysql-mysql-res
)
233 (declaim (inline mysql-store-result
))
234 (uffi:def-function
"mysql_store_result"
235 ((mysql mysql-mysql
))
237 :returning mysql-mysql-res
)
239 (declaim (inline mysql-use-result
))
240 (uffi:def-function
"mysql_use_result"
241 ((mysql mysql-mysql
))
243 :returning mysql-mysql-res
)
245 (declaim (inline mysql-options
))
246 (uffi:def-function
"mysql_options"
248 (option mysql-option
)
253 (declaim (inline mysql-free-result
))
254 (uffi:def-function
"mysql_free_result"
255 ((res mysql-mysql-res
))
259 (declaim (inline mysql-fetch-row
))
260 (uffi:def-function
"mysql_fetch_row"
261 ((res mysql-mysql-res
))
263 :returning
(* (* :unsigned-char
)))
265 (declaim (inline mysql-fetch-lengths
))
266 (uffi:def-function
"mysql_fetch_lengths"
267 ((res mysql-mysql-res
))
269 :returning
(* :unsigned-long
))
271 (declaim (inline mysql-fetch-field
))
272 (uffi:def-function
"mysql_fetch_field"
273 ((res mysql-mysql-res
))
275 :returning mysql-field
)
277 (declaim (inline mysql-field-seek
))
278 (uffi:def-function
"mysql_field_seek"
279 ((res mysql-mysql-res
)
280 (offset :unsigned-int
))
282 :returning
:unsigned-int
)
284 (declaim (inline mysql-fetch-fields
))
285 (uffi:def-function
"mysql_fetch_fields"
286 ((res mysql-mysql-res
))
288 :returning mysql-field
)
290 (declaim (inline mysql-fetch-field-direct
))
291 (uffi:def-function
"mysql_fetch_field_direct"
292 ((res mysql-mysql-res
)
293 (field-num :unsigned-int
))
295 :returning mysql-field
)
297 (declaim (inline mysql-escape-string
))
298 (uffi:def-function
"mysql_escape_string"
299 ((to (* :unsigned-char
))
300 (from (* :unsigned-char
))
301 (length :unsigned-int
))
303 :returning
:unsigned-int
)
305 (declaim (inline mysql-debug
))
306 (uffi:def-function
"mysql_debug"
311 (declaim (inline clsql-mysql-num-rows
))
312 (uffi:def-function
"clsql_mysql_num_rows"
313 ((res mysql-mysql-res
)
314 (p-high32 (* :unsigned-int
)))
315 :module
"clsql-mysql"
316 :returning
:unsigned-int
)
318 #+(or mysql-client-v4.1 mysql-client-v5
)
319 (uffi:def-foreign-type mysql-stmt-ptr
:pointer-void
)
321 #+(or mysql-client-v4.1 mysql-client-v5
)
322 (uffi:def-function
"mysql_stmt_init"
323 ((res mysql-mysql-res
))
324 :module
"clsql-mysql"
325 :returning mysql-stmt-ptr
)
327 #+(or mysql-client-v4.1 mysql-client-v5
)
328 (uffi:def-function
"mysql_stmt_prepare"
329 ((stmt mysql-stmt-ptr
)
331 (length :unsigned-long
))
332 :module
"clsql-mysql"
335 #+(or mysql-client-v4.1 mysql-client-v5
)
336 (uffi:def-function
"mysql_stmt_param_count"
337 ((stmt mysql-stmt-ptr
))
338 :module
"clsql-mysql"
339 :returning
:unsigned-int
)
341 #+(or mysql-client-v4.1 mysql-client-v5
)
342 (uffi:def-function
"mysql_stmt_bind_param"
343 ((stmt mysql-stmt-ptr
)
345 :module
"clsql-mysql"
348 #+(or mysql-client-v4.1 mysql-client-v5
)
349 (uffi:def-function
"mysql_stmt_bind_result"
350 ((stmt mysql-stmt-ptr
)
352 :module
"clsql-mysql"
355 #+(or mysql-client-v4.1 mysql-client-v5
)
356 (uffi:def-function
"mysql_stmt_result_metadata"
357 ((stmt mysql-stmt-ptr
))
358 :module
"clsql-mysql"
359 :returning mysql-mysql-res
)
362 #+(or mysql-client-v4.1 mysql-client-v5
)
363 (uffi:def-function
"mysql_stmt_execute"
364 ((stmt mysql-stmt-ptr
))
365 :module
"clsql-mysql"
368 #+(or mysql-client-v4.1 mysql-client-v5
)
369 (uffi:def-function
"mysql_stmt_store_result"
370 ((stmt mysql-stmt-ptr
))
371 :module
"clsql-mysql"
374 #+(or mysql-client-v4.1 mysql-client-v5
)
375 (uffi:def-function
"mysql_stmt_fetch"
376 ((stmt mysql-stmt-ptr
))
377 :module
"clsql-mysql"
380 #+(or mysql-client-v4.1 mysql-client-v5
)
381 (uffi:def-function
"mysql_stmt_free_result"
382 ((stmt mysql-stmt-ptr
))
383 :module
"clsql-mysql"
386 #+(or mysql-client-v4.1 mysql-client-v5
)
387 (uffi:def-function
"mysql_stmt_close"
388 ((stmt mysql-stmt-ptr
))
389 :module
"clsql-mysql"
392 #+(or mysql-client-v4.1 mysql-client-v5
)
393 (uffi:def-function
"mysql_stmt_errno"
394 ((stmt mysql-stmt-ptr
))
395 :module
"clsql-mysql"
396 :returning
:unsigned-int
)
398 #+(or mysql-client-v4.1 mysql-client-v5
)
399 (uffi:def-function
"mysql_stmt_error"
400 ((stmt mysql-stmt-ptr
))
401 :module
"clsql-mysql"
405 ;;;; Equivalents of C Macro definitions for accessing various fields
406 ;;;; in the internal MySQL Datastructures
409 (declaim (inline mysql-num-rows
))
410 (defun mysql-num-rows (res)
411 (uffi:with-foreign-object
(p-high32 :unsigned-int
)
412 (let ((low32 (clsql-mysql-num-rows res p-high32
))
413 (high32 (uffi:deref-pointer p-high32
:unsigned-int
)))
416 (make-64-bit-integer high32 low32
)))))
418 (uffi:def-function
"clsql_mysql_affected_rows"
420 (p-high32 (* :unsigned-int
)))
421 :returning
:unsigned-int
422 :module
"clsql-mysql")
424 (defun mysql-affected-rows (mysql)
425 (uffi:with-foreign-object
(p-high32 :unsigned-int
)
426 (let ((low32 (clsql-mysql-affected-rows mysql p-high32
))
427 (high32 (uffi:deref-pointer p-high32
:unsigned-int
)))
430 (make-64-bit-integer high32 low32
)))))
432 (uffi:def-function
"clsql_mysql_insert_id"
434 (p-high32 (* :unsigned-int
)))
435 :returning
:unsigned-int
436 :module
"clsql-mysql")
438 (defun mysql-insert-id (mysql)
439 (uffi:with-foreign-object
(p-high32 :unsigned-int
)
440 (let ((low32 (clsql-mysql-insert-id mysql p-high32
))
441 (high32 (uffi:deref-pointer p-high32
:unsigned-int
)))
444 (make-64-bit-integer high32 low32
)))))
447 (declaim (inline mysql-num-fields
))
448 (uffi:def-function
"mysql_num_fields"
449 ((res mysql-mysql-res
))
450 :returning
:unsigned-int
453 (declaim (inline clsql-mysql-eof
))
454 (uffi:def-function
("mysql_eof" clsql-mysql-eof
)
455 ((res mysql-mysql-res
))
459 (declaim (inline mysql-eof
))
460 (defun mysql-eof (res)
461 (if (zerop (clsql-mysql-eof res
))
465 (declaim (inline mysql-error
))
466 (uffi:def-function
("mysql_error" mysql-error
)
467 ((mysql mysql-mysql
))
471 (declaim (inline mysql-error-string
))
472 (defun mysql-error-string (mysql)
473 (uffi:convert-from-cstring
(mysql-error mysql
)))
475 (declaim (inline mysql-errno
))
476 (uffi:def-function
"mysql_errno"
477 ((mysql mysql-mysql
))
478 :returning
:unsigned-int
481 (declaim (inline mysql-info
))
482 (uffi:def-function
("mysql_info" mysql-info
)
483 ((mysql mysql-mysql
))
487 (declaim (inline mysql-info-string
))
488 (defun mysql-info-string (mysql)
489 (uffi:convert-from-cstring
(mysql-info mysql
)))
491 (declaim (inline clsql-mysql-data-seek
))
492 (uffi:def-function
"clsql_mysql_data_seek"
493 ((res mysql-mysql-res
)
494 (offset-high32 :unsigned-int
)
495 (offset-low32 :unsigned-int
))
496 :module
"clsql-mysql"
499 (declaim (inline clsql-mysql-field-name
))
500 (uffi:def-function
"clsql_mysql_field_name"
502 :module
"clsql-mysql"
505 (declaim (inline clsql-mysql-field-flags
))
506 (uffi:def-function
"clsql_mysql_field_flags"
508 :module
"clsql-mysql"
509 :returning
:unsigned-int
)
511 (declaim (inline clsql-mysql-field-type
))
512 (uffi:def-function
"clsql_mysql_field_type"
514 :module
"clsql-mysql"
515 :returning
:unsigned-int
)
517 (defun mysql-data-seek (res offset
)
518 (multiple-value-bind (high32 low32
) (split-64-bit-integer offset
)
519 (clsql-mysql-data-seek res high32 low32
)))