1 ;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
2 ;;;; *************************************************************************
3 ;;;; FILE IDENTIFICATION
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 ;;;; $Id: mysql-api.lisp,v 1.1 2002/09/30 10:19:23 kevin Exp $
13 ;;;; This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg
14 ;;;; and Copyright (c) 1999-2001 by Pierre R. Mai
16 ;;;; CLSQL users are granted the rights to distribute and use this software
17 ;;;; as governed by the terms of the Lisp Lesser GNU Public License
18 ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
19 ;;;; *************************************************************************
21 (declaim (optimize (debug 3) (speed 3) (safety 1) (compilation-speed 0)))
25 ;;;; Modifications from original code
26 ;;;; - Updated C-structures to conform to structures in MySQL 3.23.46
27 ;;;; - Changed from CMUCL interface to UFFI
28 ;;;; - Added and call a C-helper file to support 64-bit integers
29 ;;;; that are used in a few routines.
30 ;;;; - Removed all references to interiors of C-structions, this will
31 ;;;; increase robustness when MySQL's internal structures change.
37 (uffi:def-foreign-type mysql-socket :int)
38 (uffi:def-foreign-type mysql-bool :char)
39 (uffi:def-foreign-type mysql-byte :unsigned-char)
41 (uffi:def-enum mysql-net-type
46 (uffi:def-struct mysql-net
50 (buff (* :unsigned-char))
51 (buff-end (* :unsigned-char))
52 (write-pos (* :unsigned-char))
53 (read-pos (* :unsigned-char))
54 (last-error (:array :char 200))
55 (last-errno :unsigned-int)
56 (max-packet :unsigned-int)
57 (timeout :unsigned-int)
58 (pkt-nr :unsigned-int)
60 (return-errno mysql-bool)
62 (no-send-ok mysql-bool)
63 (remain-in-buf :unsigned-long)
64 (length :unsigned-long)
65 (buf-length :unsigned-long)
66 (where-b :unsigned-long)
67 (return-status (* :unsigned-int))
68 (reading-or-writing :unsigned-char)
72 (uffi:def-struct mysql-used-mem
77 (uffi:def-struct mysql-mem-root
78 (free (:struct-pointer mysql-used-mem))
79 (used (:struct-pointer mysql-used-mem))
80 (pre-alloc (:struct-pointer mysql-used-mem))
81 (min-alloc :unsigned-int)
82 (block-size :unsigned-int)
83 (error-handler :pointer-void))
86 (uffi:def-enum mysql-field-types
111 (uffi:def-struct mysql-field
115 (type mysql-field-types)
116 (length :unsigned-int)
117 (max-length :unsigned-int)
118 (flags :unsigned-int)
119 (decimals :unsigned-int))
123 (uffi:def-array-pointer mysql-row (* :unsigned-char))
125 (uffi:def-array-pointer mysql-field-vector (* mysql-field))
127 (uffi:def-foreign-type mysql-field-offset :unsigned-int)
129 (uffi:def-struct mysql-rows
133 (uffi:def-foreign-type mysql-row-offset (:struct-pointer mysql-rows))
135 (uffi:def-struct mysql-data
136 (rows-high32 :unsigned-long)
137 (rows-low32 :unsigned-long)
138 (fields :unsigned-int)
139 (data (:struct-pointer mysql-rows))
140 (alloc (:struct mysql-mem-root)))
143 (uffi:def-struct mysql-options
144 (connect-timeout :unsigned-int)
145 (client-flag :unsigned-int)
146 (compress mysql-bool)
147 (named-pipe mysql-bool)
150 (init-command (* :char))
153 (unix-socket (* :char))
155 (my-cnf-file (* :char))
156 (my-cnf-group (* :char))
157 (charset-dir (* :char))
158 (charset-name (* :char))
163 (ssl-capath (* :char)))
165 (uffi:def-enum mysql-option
171 :read-default-group))
173 (uffi:def-enum mysql-status
178 (uffi:def-struct mysql-mysql
179 (net (:struct mysql-net))
180 (connected-fd (* :char))
184 (unix-socket (* :char))
185 (server-version (* :char))
186 (host-info (* :char))
190 (client-flag :unsigned-int)
191 (server-capabilities :unsigned-int)
192 (protocol-version :unsigned-int)
193 (field-count :unsigned-int)
194 (server-status :unsigned-int)
195 (thread-id :unsigned-long)
196 (affected-rows-high32 :unsigned-long)
197 (affected-rows-low32 :unsigned-long)
198 (insert-id-high32 :unsigned-long)
199 (insert-id-low32 :unsigned-long)
200 (extra-info-high32 :unsigned-long)
201 (extra-info-low32 :unsigned-long)
202 (packet-length :unsigned-long)
203 (status mysql-status)
204 (fields (:struct-pointer mysql-field))
205 (field-alloc (:struct mysql-mem-root))
207 (reconnect mysql-bool)
208 (options (:struct mysql-options))
209 (scramble-buff (:array :char 9))
210 (charset :pointer-void)
211 (server-language :unsigned-int))
215 (uffi:def-struct mysql-mysql-res
216 (row-count-high32 :unsigned-long)
217 (row-count-low32 :unsigned-long)
218 (field-count :unsigned-int)
219 (current-field :unsigned-int)
220 (fields (:struct-pointer mysql-field))
221 (data (:struct-pointer mysql-data))
222 (data-cursor (:struct-pointer mysql-rows))
223 (field-alloc (:struct mysql-mem-root))
225 (current-row mysql-row)
226 (lengths (* :unsigned-long))
227 (handle (:struct-pointer mysql-mysql))
230 ;;;; The Foreign C routines
231 (declaim (inline mysql-init))
232 (uffi:def-function "mysql_init"
233 ((mysql (* mysql-mysql)))
235 :returning (* mysql-mysql))
237 (declaim (inline mysql-connect))
238 (uffi:def-function "mysql_connect"
239 ((mysql (* mysql-mysql))
244 :returning (* mysql-mysql))
246 ;; Need to comment this out for LW 4.2.6
247 ;; ? bug in LW version
248 ;;(declaim (inline mysql-real-connect))
249 (uffi:def-function "mysql_real_connect"
250 ((mysql (* mysql-mysql))
256 (unix-socket :cstring)
257 (clientflag :unsigned-int))
259 :returning (* mysql-mysql))
261 (declaim (inline mysql-close))
262 (uffi:def-function "mysql_close"
263 ((sock (* mysql-mysql)))
267 (declaim (inline mysql-select-db))
268 (uffi:def-function "mysql_select_db"
269 ((mysql (* mysql-mysql))
274 (declaim (inline mysql-query))
275 (uffi:def-function "mysql_query"
276 ((mysql (* mysql-mysql))
281 ;;; I doubt that this function is really useful for direct Lisp usage,
282 ;;; but it is here for completeness...
284 (declaim (inline mysql-real-query))
285 (uffi:def-function "mysql_real_query"
286 ((mysql (* mysql-mysql))
288 (length :unsigned-int))
292 (declaim (inline mysql-create-db))
293 (uffi:def-function "mysql_create_db"
294 ((mysql (* mysql-mysql))
299 (declaim (inline mysql-drop-db))
300 (uffi:def-function "mysql_drop_db"
301 ((mysql (* mysql-mysql))
306 (declaim (inline mysql-shutdown))
307 (uffi:def-function "mysql_shutdown"
308 ((mysql (* mysql-mysql)))
312 (declaim (inline mysql-dump-debug-info))
313 (uffi:def-function "mysql_dump_debug_info"
314 ((mysql (* mysql-mysql)))
318 (declaim (inline mysql-refresh))
319 (uffi:def-function "mysql_refresh"
320 ((mysql (* mysql-mysql))
321 (refresh-options :unsigned-int))
325 (declaim (inline mysql-kill))
326 (uffi:def-function "mysql_kill"
327 ((mysql (* mysql-mysql))
328 (pid :unsigned-long))
332 (declaim (inline mysql-ping))
333 (uffi:def-function "mysql_ping"
334 ((mysql (* mysql-mysql)))
338 (declaim (inline mysql-stat))
339 (uffi:def-function "mysql_stat"
340 ((mysql (* mysql-mysql)))
344 (declaim (inline mysql-get-server-info))
345 (uffi:def-function "mysql_get_server_info"
346 ((mysql (* mysql-mysql)))
350 (declaim (inline mysql-get-client-info))
351 (uffi:def-function "mysql_get_client_info"
356 (declaim (inline mysql-get-host-info))
357 (uffi:def-function "mysql_get_host_info"
358 ((mysql (* mysql-mysql)))
362 (declaim (inline mysql-get-proto-info))
363 (uffi:def-function "mysql_get_proto_info"
364 ((mysql (* mysql-mysql)))
366 :returning :unsigned-int)
368 (declaim (inline mysql-list-dbs))
369 (uffi:def-function "mysql_list_dbs"
370 ((mysql (* mysql-mysql))
373 :returning (* mysql-mysql-res))
375 (declaim (inline mysql-list-tables))
376 (uffi:def-function "mysql_list_tables"
377 ((mysql (* mysql-mysql))
380 :returning (* mysql-mysql-res))
382 (declaim (inline mysql-list-fields))
383 (uffi:def-function "mysql_list_fields"
384 ((mysql (* mysql-mysql))
388 :returning (* mysql-mysql-res))
390 (declaim (inline mysql-list-processes))
391 (uffi:def-function "mysql_list_processes"
392 ((mysql (* mysql-mysql)))
394 :returning (* mysql-mysql-res))
396 (declaim (inline mysql-store-result))
397 (uffi:def-function "mysql_store_result"
398 ((mysql (* mysql-mysql)))
400 :returning (* mysql-mysql-res))
402 (declaim (inline mysql-use-result))
403 (uffi:def-function "mysql_use_result"
404 ((mysql (* mysql-mysql)))
406 :returning (* mysql-mysql-res))
408 (declaim (inline mysql-options))
409 (uffi:def-function "mysql_options"
410 ((mysql (* mysql-mysql))
411 (option mysql-option)
416 (declaim (inline mysql-free-result))
417 (uffi:def-function "mysql_free_result"
418 ((res (* mysql-mysql-res)))
422 (declaim (inline mysql-row-seek))
423 (uffi:def-function "mysql_row_seek"
424 ((res (* mysql-mysql-res))
425 (offset mysql-row-offset))
427 :returning mysql-row-offset)
429 (declaim (inline mysql-field-seek))
430 (uffi:def-function "mysql_field_seek"
431 ((res (* mysql-mysql-res))
432 (offset mysql-field-offset))
434 :returning mysql-field-offset)
436 (declaim (inline mysql-fetch-row))
437 (uffi:def-function "mysql_fetch_row"
438 ((res (* mysql-mysql-res)))
440 :returning (* (* :unsigned-char)))
442 (declaim (inline mysql-fetch-lengths))
443 (uffi:def-function "mysql_fetch_lengths"
444 ((res (* mysql-mysql-res)))
446 :returning (* :unsigned-long))
448 (declaim (inline mysql-fetch-field))
449 (uffi:def-function "mysql_fetch_field"
450 ((res (* mysql-mysql-res)))
452 :returning (* mysql-field))
454 (declaim (inline mysql-fetch-fields))
455 (uffi:def-function "mysql_fetch_fields"
456 ((res (* mysql-mysql-res)))
458 :returning (* mysql-field))
460 (declaim (inline mysql-fetch-field-direct))
461 (uffi:def-function "mysql_fetch_field_direct"
462 ((res (* mysql-mysql-res))
463 (field-num :unsigned-int))
465 :returning (* mysql-field))
467 (declaim (inline mysql-escape-string))
468 (uffi:def-function "mysql_escape_string"
471 (length :unsigned-int))
473 :returning :unsigned-int)
475 (declaim (inline mysql-debug))
476 (uffi:def-function "mysql_debug"
481 (declaim (inline clsql-mysql-num-rows))
482 (uffi:def-function "clsql_mysql_num_rows"
483 ((res (* mysql-mysql-res))
484 (p-high32 (* :unsigned-int)))
485 :module "clsql-mysql"
486 :returning :unsigned-int)
489 ;;;; Equivalents of C Macro definitions for accessing various fields
490 ;;;; in the internal MySQL Datastructures
493 (declaim (inline mysql-num-rows))
494 (defun mysql-num-rows (res)
495 (uffi:with-foreign-object (p-high32 :unsigned-int)
496 (let ((low32 (clsql-mysql-num-rows res p-high32))
497 (high32 (uffi:deref-pointer p-high32 :unsigned-int)))
500 (make-64-bit-integer high32 low32)))))
502 (uffi:def-function "clsql_mysql_affected_rows"
503 ((mysql (* mysql-mysql))
504 (p-high32 (* :unsigned-int)))
505 :returning :unsigned-int
506 :module "clsql-mysql")
508 (defun mysql-affected-rows (mysql)
509 (uffi:with-foreign-object (p-high32 :unsigned-int)
510 (let ((low32 (clsql-mysql-affected-rows mysql p-high32))
511 (high32 (uffi:deref-pointer p-high32 :unsigned-int)))
514 (make-64-bit-integer high32 low32)))))
516 (uffi:def-function "clsql_mysql_insert_id"
517 ((res (* mysql-mysql))
518 (p-high32 (* :unsigned-int)))
519 :returning :unsigned-int
520 :module "clsql-mysql")
522 (defun mysql-insert-id (mysql)
523 (uffi:with-foreign-object (p-high32 :unsigned-int)
524 (let ((low32 (clsql-mysql-insert-id mysql p-high32))
525 (high32 (uffi:deref-pointer p-high32 :unsigned-int)))
528 (make-64-bit-integer high32 low32)))))
531 (declaim (inline mysql-num-fields))
532 (uffi:def-function "mysql_num_fields"
533 ((res (* mysql-mysql-res)))
534 :returning :unsigned-int
537 (declaim (inline clsql-mysql-eof))
538 (uffi:def-function ("mysql_eof" clsql-mysql-eof)
539 ((res (* mysql-mysql-res)))
543 (declaim (inline mysql-eof))
544 (defun mysql-eof (res)
545 (if (zerop (clsql-mysql-eof res))
549 (declaim (inline mysql-error))
550 (uffi:def-function ("mysql_error" mysql-error)
551 ((mysql (* mysql-mysql)))
555 (declaim (inline mysql-error-string))
556 (defun mysql-error-string (mysql)
557 (uffi:convert-from-cstring (mysql-error mysql)))
559 (declaim (inline mysql-errno))
560 (uffi:def-function "mysql_errno"
561 ((mysql (* mysql-mysql)))
562 :returning :unsigned-int
565 (declaim (inline mysql-info))
566 (uffi:def-function ("mysql_info" mysql-info)
567 ((mysql (* mysql-mysql)))
571 (declaim (inline mysql-info-string))
572 (defun mysql-info-string (mysql)
573 (uffi:convert-from-cstring (mysql-info mysql)))
575 (declaim (inline clsql-mysql-data-seek))
576 (uffi:def-function "clsql_mysql_data_seek"
577 ((res (* mysql-mysql-res))
578 (offset-high32 :unsigned-int)
579 (offset-low32 :unsigned-int))
580 :module "clsql-mysql"
584 (defun mysql-data-seek (res offset)
585 (multiple-value-bind (high32 low32) (split-64-bit-integer offset)
586 (clsql-mysql-data-seek res high32 low32)))