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.cl,v 1.4 2002/05/25 15:57:28 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 (* mysql-used-mem))
79 (used (* mysql-used-mem))
80 (pre-alloc (* 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))
124 (uffi:def-array-pointer mysql-field-vector (* mysql-field))
126 (uffi:def-foreign-type mysql-field-offset :unsigned-int)
128 (uffi:def-struct mysql-rows
132 (uffi:def-foreign-type mysql-row-offset (* mysql-rows))
134 (uffi:def-struct mysql-data
135 (rows-high32 :unsigned-long)
136 (rows-low32 :unsigned-long)
137 (fields :unsigned-int)
138 (data (* mysql-rows))
139 (alloc mysql-mem-root))
142 (uffi:def-struct mysql-options
143 (connect-timeout :unsigned-int)
144 (client-flag :unsigned-int)
145 (compress mysql-bool)
146 (named-pipe mysql-bool)
149 (init-command (* :char))
152 (unix-socket (* :char))
154 (my-cnf-file (* :char))
155 (my-cnf-group (* :char))
156 (charset-dir (* :char))
157 (charset-name (* :char))
162 (ssl-capath (* :char)))
164 (uffi:def-enum mysql-option
170 :read-default-group))
172 (uffi:def-enum mysql-status
177 (uffi:def-struct mysql-mysql
179 (connected-fd (* :char))
183 (unix-socket (* :char))
184 (server-version (* :char))
185 (host-info (* :char))
189 (client-flag :unsigned-int)
190 (server-capabilities :unsigned-int)
191 (protocol-version :unsigned-int)
192 (field-count :unsigned-int)
193 (server-status :unsigned-int)
194 (thread-id :unsigned-long)
195 (affected-rows-high32 :unsigned-long)
196 (affected-rows-low32 :unsigned-long)
197 (insert-id-high32 :unsigned-long)
198 (insert-id-low32 :unsigned-long)
199 (extra-info-high32 :unsigned-long)
200 (extra-info-low32 :unsigned-long)
201 (packet-length :unsigned-long)
202 (status mysql-status)
203 (fields (* mysql-field))
204 (field-alloc mysql-mem-root)
206 (reconnect mysql-bool)
207 (options mysql-options)
208 (scramble-buff (:array :char 9))
209 (charset :pointer-void)
210 (server-language :unsigned-int))
214 (uffi:def-struct mysql-mysql-res
215 (row-count-high32 :unsigned-long)
216 (row-count-low32 :unsigned-long)
217 (field-count :unsigned-int)
218 (current-field :unsigned-int)
219 (fields (* mysql-field))
220 (data (* mysql-data))
221 (data-cursor (* mysql-rows))
222 (field-alloc mysql-mem-root)
224 (current-row mysql-row)
225 (lengths (* :unsigned-long))
226 (handle (* mysql-mysql))
229 ;;;; The Foreign C routines
230 (declaim (inline mysql-init))
231 (uffi:def-function "mysql_init"
232 ((mysql (* mysql-mysql)))
234 :returning (* mysql-mysql))
236 (declaim (inline mysql-connect))
237 (uffi:def-function "mysql_connect"
238 ((mysql (* mysql-mysql))
243 :returning (* mysql-mysql))
245 ;; Need to comment this out for LW 4.2.6
246 ;; ? bug in LW version
247 ;;(declaim (inline mysql-real-connect))
248 (uffi:def-function "mysql_real_connect"
249 ((mysql (* mysql-mysql))
255 (unix-socket :cstring)
256 (clientflag :unsigned-int))
258 :returning (* mysql-mysql))
260 (declaim (inline mysql-close))
261 (uffi:def-function "mysql_close"
262 ((sock (* mysql-mysql)))
266 (declaim (inline mysql-select-db))
267 (uffi:def-function "mysql_select_db"
268 ((mysql (* mysql-mysql))
273 (declaim (inline mysql-query))
274 (uffi:def-function "mysql_query"
275 ((mysql (* mysql-mysql))
280 ;;; I doubt that this function is really useful for direct Lisp usage,
281 ;;; but it is here for completeness...
283 (declaim (inline mysql-real-query))
284 (uffi:def-function "mysql_real_query"
285 ((mysql (* mysql-mysql))
287 (length :unsigned-int))
291 (declaim (inline mysql-create-db))
292 (uffi:def-function "mysql_create_db"
293 ((mysql (* mysql-mysql))
298 (declaim (inline mysql-drop-db))
299 (uffi:def-function "mysql_drop_db"
300 ((mysql (* mysql-mysql))
305 (declaim (inline mysql-shutdown))
306 (uffi:def-function "mysql_shutdown"
307 ((mysql (* mysql-mysql)))
311 (declaim (inline mysql-dump-debug-info))
312 (uffi:def-function "mysql_dump_debug_info"
313 ((mysql (* mysql-mysql)))
317 (declaim (inline mysql-refresh))
318 (uffi:def-function "mysql_refresh"
319 ((mysql (* mysql-mysql))
320 (refresh-options :unsigned-int))
324 (declaim (inline mysql-kill))
325 (uffi:def-function "mysql_kill"
326 ((mysql (* mysql-mysql))
327 (pid :unsigned-long))
331 (declaim (inline mysql-ping))
332 (uffi:def-function "mysql_ping"
333 ((mysql (* mysql-mysql)))
337 (declaim (inline mysql-stat))
338 (uffi:def-function "mysql_stat"
339 ((mysql (* mysql-mysql)))
343 (declaim (inline mysql-get-server-info))
344 (uffi:def-function "mysql_get_server_info"
345 ((mysql (* mysql-mysql)))
349 (declaim (inline mysql-get-client-info))
350 (uffi:def-function "mysql_get_client_info"
355 (declaim (inline mysql-get-host-info))
356 (uffi:def-function "mysql_get_host_info"
357 ((mysql (* mysql-mysql)))
361 (declaim (inline mysql-get-proto-info))
362 (uffi:def-function "mysql_get_proto_info"
363 ((mysql (* mysql-mysql)))
365 :returning :unsigned-int)
367 (declaim (inline mysql-list-dbs))
368 (uffi:def-function "mysql_list_dbs"
369 ((mysql (* mysql-mysql))
372 :returning (* mysql-mysql-res))
374 (declaim (inline mysql-list-tables))
375 (uffi:def-function "mysql_list_tables"
376 ((mysql (* mysql-mysql))
379 :returning (* mysql-mysql-res))
381 (declaim (inline mysql-list-fields))
382 (uffi:def-function "mysql_list_fields"
383 ((mysql (* mysql-mysql))
387 :returning (* mysql-mysql-res))
389 (declaim (inline mysql-list-processes))
390 (uffi:def-function "mysql_list_processes"
391 ((mysql (* mysql-mysql)))
393 :returning (* mysql-mysql-res))
395 (declaim (inline mysql-store-result))
396 (uffi:def-function "mysql_store_result"
397 ((mysql (* mysql-mysql)))
399 :returning (* mysql-mysql-res))
401 (declaim (inline mysql-use-result))
402 (uffi:def-function "mysql_use_result"
403 ((mysql (* mysql-mysql)))
405 :returning (* mysql-mysql-res))
407 (declaim (inline mysql-options))
408 (uffi:def-function "mysql_options"
409 ((mysql (* mysql-mysql))
410 (option mysql-option)
415 (declaim (inline mysql-free-result))
416 (uffi:def-function "mysql_free_result"
417 ((res (* mysql-mysql-res)))
421 (declaim (inline mysql-row-seek))
422 (uffi:def-function "mysql_row_seek"
423 ((res (* mysql-mysql-res))
424 (offset mysql-row-offset))
426 :returning mysql-row-offset)
428 (declaim (inline mysql-field-seek))
429 (uffi:def-function "mysql_field_seek"
430 ((res (* mysql-mysql-res))
431 (offset mysql-field-offset))
433 :returning mysql-field-offset)
435 (declaim (inline mysql-fetch-row))
436 (uffi:def-function "mysql_fetch_row"
437 ((res (* mysql-mysql-res)))
439 :returning mysql-row)
441 (declaim (inline mysql-fetch-lengths))
442 (uffi:def-function "mysql_fetch_lengths"
443 ((res (* mysql-mysql-res)))
445 :returning (* :unsigned-long))
447 (declaim (inline mysql-fetch-field))
448 (uffi:def-function "mysql_fetch_field"
449 ((res (* mysql-mysql-res)))
451 :returning (* mysql-field))
453 (declaim (inline mysql-fetch-fields))
454 (uffi:def-function "mysql_fetch_fields"
455 ((res (* mysql-mysql-res)))
457 :returning mysql-field-vector)
459 (declaim (inline mysql-fetch-field-direct))
460 (uffi:def-function "mysql_fetch_field_direct"
461 ((res (* mysql-mysql-res))
462 (field-num :unsigned-int))
464 :returning (* mysql-field))
466 (declaim (inline mysql-escape-string))
467 (uffi:def-function "mysql_escape_string"
470 (length :unsigned-int))
472 :returning :unsigned-int)
474 (declaim (inline mysql-debug))
475 (uffi:def-function "mysql_debug"
480 (declaim (inline clsql-mysql-num-rows))
481 (uffi:def-function "clsql_mysql_num_rows"
482 ((res (* mysql-mysql-res))
483 (p-high32 (* :unsigned-int)))
484 :module "clsql-mysql"
485 :returning :unsigned-int)
488 ;;;; Equivalents of C Macro definitions for accessing various fields
489 ;;;; in the internal MySQL Datastructures
492 (declaim (inline mysql-num-rows))
493 (defun mysql-num-rows (res)
494 (uffi:with-foreign-object (p-high32 :unsigned-int)
495 (let ((low32 (clsql-mysql-num-rows res p-high32))
496 (high32 (uffi:deref-pointer p-high32 :unsigned-int)))
499 (make-64-bit-integer high32 low32)))))
501 (uffi:def-function "clsql_mysql_affected_rows"
502 ((mysql (* mysql-mysql))
503 (p-high32 (* :unsigned-int)))
504 :returning :unsigned-int
505 :module "clsql-mysql")
507 (defun mysql-affected-rows (mysql)
508 (uffi:with-foreign-object (p-high32 :unsigned-int)
509 (let ((low32 (clsql-mysql-affected-rows mysql p-high32))
510 (high32 (uffi:deref-pointer p-high32 :unsigned-int)))
513 (make-64-bit-integer high32 low32)))))
515 (uffi:def-function "clsql_mysql_insert_id"
516 ((res (* mysql-mysql))
517 (p-high32 (* :unsigned-int)))
518 :returning :unsigned-int
519 :module "clsql-mysql")
521 (defun mysql-insert-id (mysql)
522 (uffi:with-foreign-object (p-high32 :unsigned-int)
523 (let ((low32 (clsql-mysql-insert-id mysql p-high32))
524 (high32 (uffi:deref-pointer p-high32 :unsigned-int)))
527 (make-64-bit-integer high32 low32)))))
530 (declaim (inline mysql-num-fields))
531 (uffi:def-function "mysql_num_fields"
532 ((res (* mysql-mysql-res)))
533 :returning :unsigned-int
536 (declaim (inline clsql-mysql-eof))
537 (uffi:def-function ("mysql_eof" clsql-mysql-eof)
538 ((res (* mysql-mysql-res)))
542 (declaim (inline mysql-eof))
543 (defun mysql-eof (res)
544 (if (zerop (clsql-mysql-eof res))
548 (declaim (inline mysql-error))
549 (uffi:def-function ("mysql_error" mysql-error)
550 ((mysql (* mysql-mysql)))
554 (declaim (inline mysql-error-string))
555 (defun mysql-error-string (mysql)
556 (uffi:convert-from-cstring (mysql-error mysql)))
558 (declaim (inline mysql-errno))
559 (uffi:def-function "mysql_errno"
560 ((mysql (* mysql-mysql)))
561 :returning :unsigned-int
564 (declaim (inline mysql-info))
565 (uffi:def-function ("mysql_info" mysql-info)
566 ((mysql (* mysql-mysql)))
570 (declaim (inline mysql-info-string))
571 (defun mysql-info-string (mysql)
572 (uffi:convert-from-cstring (mysql-info mysql)))
574 (declaim (inline clsql-mysql-data-seek))
575 (uffi:def-function "clsql_mysql_data_seek"
576 ((res (* mysql-mysql-res))
577 (offset-high32 :unsigned-int)
578 (offset-low32 :unsigned-int))
579 :module "clsql-mysql"
583 (defun mysql-data-seek (res offset)
584 (multiple-value-bind (high32 low32) (split-64-bit-integer offset)
585 (clsql-mysql-data-seek res high32 low32)))