316 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			316 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
| ODBC support for scsh 0.6.x
 | |
| ===========================
 | |
| 
 | |
| This directory contains bindings to Unix ODBC libraries, which make it
 | |
| possible to call any ODBC functions from scsh directly. At the moment
 | |
| ODBC support is not part of the scsh distribution, since ODBC support
 | |
| is in an early stage of development -- to put it another way, it's for
 | |
| thrill seekers only! The code is complete, but needs testing. So,
 | |
| please let us know if you find a bug. ODBC supports also lacks some
 | |
| documentation. 
 | |
| 
 | |
| 1. Building scsh with ODBC support
 | |
| 
 | |
| I recommend to use the scsh version from CVS. However, it might work
 | |
| with scsh-releases 0.6.1 or newer to. Be sure to have a ODBC
 | |
| implementation for Unix, like unixODBC or iODBC -- both seem to work
 | |
| fine. Apply the following patch:
 | |
| 
 | |
| Index: autogen.sh
 | |
| ===================================================================
 | |
| RCS file: /cvsroot/scsh/scsh-0.6/autogen.sh,v
 | |
| retrieving revision 1.7
 | |
| diff -u -r1.7 autogen.sh
 | |
| --- autogen.sh	12 Feb 2002 16:26:05 -0000	1.7
 | |
| +++ autogen.sh	23 Apr 2003 15:23:43 -0000
 | |
| @@ -2,7 +2,8 @@
 | |
|  
 | |
|  autoheader &&
 | |
|  autoconf &&
 | |
| -./configure &&
 | |
| +./configure --with-iODBC=/afs/wsi/i386_fbsd46 &&
 | |
| +##./configure --with-iODBC=/usr/lib &&
 | |
|  touch scsh/*.c &&
 | |
|  touch build/filenames.scm &&
 | |
|  rm -f scheme48.image cig/cig.image scsh/scsh.image &&
 | |
| @@ -12,5 +13,4 @@
 | |
|  make i-know-what-i-am-doing &&
 | |
|  make c/scheme48.h&&
 | |
|  make linker &&
 | |
| -make build/initial.image &&
 | |
| -make distclean 
 | |
| +make build/initial.image 
 | |
| Index: configure.in
 | |
| ===================================================================
 | |
| RCS file: /cvsroot/scsh/scsh-0.6/configure.in,v
 | |
| retrieving revision 1.28
 | |
| diff -u -r1.28 configure.in
 | |
| --- configure.in	16 Apr 2003 12:41:36 -0000	1.28
 | |
| +++ configure.in	23 Apr 2003 15:23:43 -0000
 | |
| @@ -373,7 +373,30 @@
 | |
|       AC_SUBST(LIBS)
 | |
|       AC_SUBST(TMPDIR)
 | |
|  
 | |
| -    
 | |
| +AC_ARG_WITH(unixODBC,
 | |
| +	[ --with-unixODBC=DIR 		Support for unixODBC ],
 | |
| +	[ with_unixodbc=$withval ],
 | |
| +	[ with_unixodbc=no ]
 | |
| +	)
 | |
| +if test "$with_unixodbc" != no; then
 | |
| +	odbc_includes="-I$with_unixodbc/include"
 | |
| +	odbc_libs="-lodbc -L$with_unixodbc/lib"
 | |
| +	AC_SUBST(odbc_includes)
 | |
| +	AC_SUBST(odbc_libs)
 | |
| +fi	
 | |
| +
 | |
| +AC_ARG_WITH(iODBC,
 | |
| +	[ --with-iODBC=DIR			Support for iODBC ],
 | |
| +	[ with_iodbc=$withval ],
 | |
| +	[ with_iodbc=no ]
 | |
| +	)
 | |
| +if test "$with_iodbc" != no; then
 | |
| +	odbc_includes="-I$withval/include"
 | |
| +	odbc_libs="-liodbc -L$withval/lib"
 | |
| +	AC_SUBST(odbc_includes)
 | |
| +	AC_SUBST(odbc_libs)
 | |
| +fi	
 | |
| +
 | |
|  AC_CONFIG_FILES(Makefile scsh/endian.scm scsh-config)
 | |
|  AC_CONFIG_COMMANDS([scsh-config+x],[chmod +x scsh-config])
 | |
|  AC_OUTPUT
 | |
| Index: Makefile.in
 | |
| ===================================================================
 | |
| RCS file: /cvsroot/scsh/scsh-0.6/Makefile.in,v
 | |
| retrieving revision 1.61
 | |
| diff -u -r1.61 Makefile.in
 | |
| --- Makefile.in	10 Mar 2003 12:13:02 -0000	1.61
 | |
| +++ Makefile.in	23 Apr 2003 15:23:43 -0000
 | |
| @@ -8,8 +8,8 @@
 | |
|  VPATH = @srcdir@
 | |
|  CC = @CC@
 | |
|  DEFS = @DEFS@
 | |
| -LIBS = @LIBS@
 | |
| -CFLAGS = @CFLAGS@
 | |
| +LIBS = @LIBS@ @odbc_libs@
 | |
| +CFLAGS = @CFLAGS@ @odbc_includes@
 | |
|  INSTALL = @INSTALL@
 | |
|  INSTALL_PROGRAM = @INSTALL_PROGRAM@
 | |
|  INSTALL_DATA = @INSTALL_DATA@
 | |
| @@ -47,7 +47,8 @@
 | |
|  # BUILD_RUNNABLE has to be Scheme 48 0.53. This is used for builds directly 
 | |
|  # out of the CVS repository.
 | |
|  # We cannot use Scsh here since -i is not understood.
 | |
| -BUILD_RUNNABLE = /afs/wsi/i386_fbsd32/bin/scheme48
 | |
| +#BUILD_RUNNABLE = /afs/wsi/ppc_macx55/scheme48-0.53/bin/scheme48
 | |
| +BUILD_RUNNABLE = /afs/wsi/i386_fbsd32/scheme48-0.53/bin/scheme48
 | |
|  RUNNABLE = scsh
 | |
|  MANPAGE = $(RUNNABLE).$(manext)
 | |
|  LIB = $(libdir)/$(RUNNABLE)
 | |
| @@ -133,7 +134,7 @@
 | |
|  	scsh/userinfo1.o \
 | |
|  	scsh/sighandlers1.o \
 | |
|  	scsh/libscsh.o \
 | |
| -	scsh/md5.o
 | |
| +	scsh/md5.o 
 | |
|  
 | |
|  SCSH_INITIALIZERS = s48_init_syslog s48_init_posix_regexp \
 | |
|  	s48_init_userinfo s48_init_sighandlers \
 | |
| @@ -169,16 +170,23 @@
 | |
|  # External code to include in the VM
 | |
|  # After changing any of these you should delete `scheme48vm' and remake it.
 | |
|  
 | |
| -EXTERNAL_OBJECTS = $(SOCKET_OBJECTS) $(LOOKUP_OBJECTS)
 | |
| -EXTERNAL_FLAGS = $(SOCKET_FLAGS)
 | |
| +EXTERNAL_OBJECTS = $(SOCKET_OBJECTS) $(LOOKUP_OBJECTS) $(ODBC_OBJECTS)
 | |
| +EXTERNAL_FLAGS = $(SOCKET_FLAGS) $(ODBC_FLAGS)
 | |
| +EXTERNAL_LDFLAGS = $(SOCKET_LD_FLAGS) $(ODBC_LD_FLAGS)
 | |
|  EXTERNAL_INITIALIZERS = $(ADDITIONAL_INITIALIZER) $(SOCKET_INITIALIZERS) 	\
 | |
|  	$(LOOKUP_INITIALIZERS) 							\
 | |
|  	$(SCSH_INITIALIZERS) $(SRFI_INITIALIZERS)				\
 | |
| +	$(ODBC_INITIALIZERS) 							\
 | |
|  	s48_init_cig
 | |
|  
 | |
|  
 | |
|  # Rules for any external code.
 | |
|  
 | |
| +scsh/odbc/odbc.o: scsh/odbc/odbc.h
 | |
| +
 | |
| +ODBC_OBJECTS = scsh/odbc/odbc.o
 | |
| +ODBC_INITIALIZERS = s48_init_odbc
 | |
| +
 | |
|  # Socket rules
 | |
|  
 | |
|  c/unix/socket.o: c/scheme48.h c/fd-io.h c/event.h
 | |
| @@ -837,7 +845,10 @@
 | |
|  	scsh/rx/re-high.scm \
 | |
|  	scsh/rx/regexp.scm \
 | |
|  	scsh/rx/re-low.scm \
 | |
| -	scsh/rx/regress.scm
 | |
| +	scsh/rx/regress.scm \
 | |
| +	scsh/odbc/odbc-interfaces.scm \
 | |
| +	scsh/odbc/odbc-packages.scm \
 | |
| +	scsh/odbc/odbc.scm
 | |
|  #    	scsh/dbm.scm db.scm ndbm.scm
 | |
|  #	jcontrol
 | |
|  
 | |
| @@ -861,7 +872,9 @@
 | |
|  	 $(srcdir)/scsh/rx/packages.scm \
 | |
|  	 $(srcdir)/scsh/scsh-package.scm \
 | |
|  	 $(srcdir)/scsh/lib/ccp-pack.scm \
 | |
| -	 $(srcdir)/scsh/lib/char-package.scm
 | |
| +	 $(srcdir)/scsh/lib/char-package.scm \
 | |
| +	 $(srcdir)/scsh/odbc/odbc-interfaces.scm \
 | |
| +	 $(srcdir)/scsh/odbc/odbc-packages.scm 
 | |
|  
 | |
|  opens = floatnums scsh ccp-lib scsh-top-package scsh-here-string-hax \
 | |
|  	srfi-1 srfi-13 srfi-14 # srfi-14 is also exported by scsh
 | |
| 
 | |
|  
 | |
| This will add some rules to Makefile and add two options to configure:
 | |
| --with-iODBC=PATH and --with-unixODBC=PATH. 
 | |
| 
 | |
| Now it's time to build scsh. Edit the call to configure in autgen.sh to
 | |
| your needs, e.g.:
 | |
| 
 | |
| ./configure --with-iODBC=/usr/local &&
 | |
| 
 | |
| Don't forget the && at the end of line! Now, run autogen.sh to build
 | |
| the VM and all that stuff. Run make to build scsh. If the build
 | |
| suceeds, tap yourself on the shoulder, that's important, it might the
 | |
| last sense of achievement from now on.
 | |
| 
 | |
| 2. Running scsh with ODBC support
 | |
| 
 | |
| Type ./scshvm -i scsh/scsh.image -- that's it!
 | |
| 
 | |
| 3. How do I use ODBC support?
 | |
| 
 | |
| If you installed the odbc-module-patch, simply type ,open odbc. If you
 | |
| have installed dynamic ODBC libraries make sure your system can find
 | |
| them, e.g. put the path in your LD_LIBRARY_PATH. This should look like
 | |
| this:
 | |
| 
 | |
| [knauel@jimi scsh-0.6.cvs] ./scshvm -i scsh/scsh.image 
 | |
| Welcome to scsh 0.6.3 (Health Reform)
 | |
| Type ,? for help.
 | |
| > ,open odbc
 | |
| Load structure odbc (y/n)? y
 | |
| [odbc ./scsh/odbc/odbc-bindcol.scm ./scsh/odbc/odbc.scm]
 | |
| > ,exit
 | |
| 
 | |
| This is an example entry for ~/.odbc.ini:
 | |
| 
 | |
| [test]
 | |
| DSN 	= mysql1
 | |
| Driver	= /afs/informatik.uni-tuebingen.de/pu/src/build/knauel/i386_fbsd43/lib/libmyodbc3.so
 | |
| Server	= localhost
 | |
| Port	= 3306
 | |
| User	= odbc
 | |
| Password= geheim
 | |
| TraceFile= stderr
 | |
| Trace	= on
 | |
| 
 | |
| It may be necessary to help your ODBC driver manager to find that file
 | |
| be setting the environment variable ODBCINI.
 | |
| 
 | |
| Let's see what data sources are known to the system:
 | |
| 
 | |
| (let* ((env-handle (odbc-alloc-environment-handle))
 | |
|        (data-sources (odbc-sql-data-sources env-handle)))
 | |
|   (for-each 
 | |
|    (lambda (pair)
 | |
|      (display "data source: ")
 | |
|      (display (car pair))
 | |
|      (newline)
 | |
|      (display "using driver: ")
 | |
|      (display (cdr pair))
 | |
|      (newline))
 | |
|    data-sources))
 | |
| 
 | |
| Don't worry about freeing handles -- this will happen automatically
 | |
| when the scheme variable gets garbage collected.
 | |
| 
 | |
| This example shows how you can read the information from ODBC's
 | |
| diag-recs in case an error occurs, which is to happen very likely: 
 | |
| 
 | |
| (define (display-errors handle)
 | |
|   (let ((recs (odbc-sql-get-diag-recs handle)))
 | |
|     (if (not (null? recs))
 | |
| 	(for-each (lambda (rec)
 | |
| 		    (newline)
 | |
| 		    (display "state: ")
 | |
| 		    (display (odbc-diag-sql-state rec))
 | |
| 		    (newline)
 | |
| 		    (display "native error: ")
 | |
| 		    (display (odbc-diag-native-error rec))
 | |
| 		    (newline)
 | |
| 		    (display "message: ")
 | |
| 		    (display (odbc-diag-message rec))
 | |
| 		    (newline))
 | |
| 		  recs)
 | |
| 	(begin
 | |
| 	  (display "No error messages (so far ;-)")
 | |
| 	  (newline)))))
 | |
| 
 | |
| Not let's read some stuff from the database! Say we have a database
 | |
| with four columns a through d, where a,b,c are integer columns and d
 | |
| is text. Using the fancy odbc-sql-bindcol functions that's pretty
 | |
| easy:
 | |
| 
 | |
| ,open low-odbc
 | |
| ,open low-odbc-constants
 | |
| 
 | |
| (define (get-env-handle)
 | |
|   (call-with-values
 | |
|     odbc-alloc-environment-handle
 | |
|     (lambda (status-code env-handle)
 | |
|       (if (odbc-call-successful? status-code)
 | |
| 	env-handle
 | |
|         (error "error allocating environment handle")))))
 | |
| 
 | |
| (define (get-conn-handle env-handle)
 | |
|   (call-with-values
 | |
|     (lambda ()
 | |
|       (odbc-alloc-connection-handle env-handle))
 | |
|     (lambda (status-code conn-handle)
 | |
|       (if (odbc-call-successful? status-code)
 | |
|          conn-handle
 | |
|          (error "error allocating connection handle")))))
 | |
| 
 | |
| (define (get-stmt-handle conn-handle)
 | |
|   (call-with-values
 | |
|     (lambda ()
 | |
|       (odbc-alloc-statement-handle conn-handle))
 | |
|     (lambda (status-code stmt-handle)
 | |
|       (if (odbc-call-successful? status-code)
 | |
|         stmt-handle
 | |
|         (error "error allocating statement handle")))))
 | |
| 
 | |
| (define env-handle (get-env-handle))
 | |
| (define conn-handle (get-conn-handle env-handle))
 | |
| 
 | |
| (odbc-sql-connect conn-handle "pgfbsd" "test" "geheim")
 | |
| 
 | |
| (define stmt-handle (get-stmt-handle conn-handle))
 | |
| 
 | |
| (odbc-sql-execute-direct stmt-handle "select * from abcd")
 | |
| 
 | |
| (define col-a (odbc-sql-bindcol stmt-handle 1 sql-c-long 1))
 | |
| (define	col-b (odbc-sql-bindcol stmt-handle 2 sql-c-long 1))
 | |
| (define col-c (odbc-sql-bindcol stmt-handle 3 sql-c-long 1))
 | |
| (define col-d (odbc-sql-bindcol stmt-handle 4 sql-c-char 400))
 | |
| 
 | |
| (let lp ((retcode (odbc-sql-fetch stmt-handle))
 | |
| 	 (result '()))
 | |
|   (if (or (odbc-call-successful? retcode) (equal? retcode sql-no-data))
 | |
|       (if (equal? retcode sql-no-data)
 | |
| 	  result
 | |
| 	  (lp (odbc-sql-fetch stmt-handle)
 | |
| 	      (cons (list (col-a) (col-b) (col-c) (col-d)) result)))
 | |
|       (error "Could not SQLFetch()")))
 | |
| 
 | |
| Please let me know, if you find some bugs. I hereby promise to
 | |
| complete the documentation as soon as possible!
 | |
| 
 | |
| Eric Knauel <knauel@informatik.uni-tuebingen.de> |