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)))