ODBC direct connection, find driver name

Share your advanced PureBasic knowledge/code with the community.
gnozal
PureBasic Expert
PureBasic Expert
Posts: 4229
Joined: Sat Apr 26, 2003 8:27 am
Location: Strasbourg / France
Contact:

ODBC direct connection, find driver name

Post by gnozal »

Code updated For 5.20+

ODBC direct connection is nice, but you have to specify the driver name.
The problem is, it can have different names on different machines (for the same database) because of different operating systems or languages.
Example of Oracle ODBC drivers : "Microsoft ODBC pour Oracle", "Oracle73 Ver 2.5", "Microsoft ODBC for Oracle"...

I use the ODBC_FindDriver() function to get the driver name for a database.
Exemple : ODBC_FindDriver("Oracle")

I wonder if there is a better way ?

Code: Select all

;
; Direct ODBC Connection
;
#ODBC_ADD_DSN = 1 ; Add Data source 
#ODBC_REMOVE_DSN = 3 ; Remove Data source 

Procedure.s ODBC_FindDriver(SourceOrBaseName.s) ; Find ODBC driver name for Oracle, SQL Server, Excel, etc ... [ex: ODBC_FindDriver("Oracle")]
  Protected phKey.i, DriverIndex.i, DriverName.s, *Buffer, BufferSize.i, *BufferV, BufferVSize.i, ReturnValue.s
  SourceOrBaseName = UCase(SourceOrBaseName)
  BufferSize = 1024
  BufferVSize = 1024
  *Buffer = AllocateMemory(BufferSize)
  If *Buffer
    *BufferV = AllocateMemory(BufferVSize)
    If *BufferV
      If RegOpenKeyEx_(#HKEY_LOCAL_MACHINE, "SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers", 0, #KEY_READ, @phKey) = #ERROR_SUCCESS
        Result = RegEnumValue_(phKey, DriverIndex, *Buffer, @BufferSize, #NULL, #NULL, *BufferV, @BufferVSize) 
        If Result = #ERROR_SUCCESS
          DriverIndex = DriverIndex + 1 
          DriverName = PeekS(*Buffer)
          If FindString(UCase(DriverName), SourceOrBaseName, 1)
            ReturnValue = DriverName
          Else
            Repeat 
              BufferSize = 1024
              BufferVSize = 1024
              Result = RegEnumValue_(phKey, DriverIndex, *Buffer, @BufferSize, #NULL, #NULL, *BufferV, @BufferVSize) 
              If Result = #ERROR_SUCCESS 
                DriverName = PeekS(*Buffer)
                If FindString(UCase(DriverName), SourceOrBaseName, 1)
                  ReturnValue = DriverName
                  Debug "ODBC_FindDriver = '" + DriverName + "'"
                EndIf 
              EndIf
              DriverIndex = DriverIndex + 1
            Until Result = #ERROR_NO_MORE_ITEMS 
          EndIf
        EndIf 
        RegCloseKey_(phKey)
      EndIf
      FreeMemory(*BufferV)
    EndIf
    FreeMemory(*Buffer)
  EndIf
  ProcedureReturn ReturnValue
EndProcedure

Procedure.i ODBC_ConfigDataSource(Driver.s, ConnectString.s) 
  Protected Result, Base, *mem.Character, *ptr.Character, Len, i
  If Driver And ConnectString
    Len = Len(ConnectString)
    Base = AllocateMemory((Len + 2) << (SizeOf(Character) - 1))
    If Base
      *mem = Base
      *ptr = @ConnectString
      For i = 1 To Len
        If *ptr\c <> ';'
          *mem\c = *ptr\c
        EndIf
        *mem + SizeOf(Character)
        *ptr + SizeOf(Character)
      Next
      Result = SQLConfigDataSource_(0, #ODBC_ADD_DSN, Driver, Base) 
      FreeMemory(Base)
    EndIf
  EndIf
  ProcedureReturn Result
EndProcedure

Procedure.i ODBC_MakeConnection(Driver.s, Server.s, Database.s, Description.s, DSN.s) 
  Protected Library.i, *Memory, Result.i, Attributes.s, AlreadyExists.i
  Static DatabaseInit.i
  If DatabaseInit = #False
    If UseODBCDatabase() = 0 
      MessageRequester("ERREUR", "ODBC version 3 ou supérieure est nécessaire !", #MB_ICONERROR) 
    Else
      DatabaseInit = #True
    EndIf 
  EndIf
  If DatabaseInit
    If ExamineDatabaseDrivers()
      While NextDatabaseDriver()
        If DatabaseDriverName() = DSN
          AlreadyExists = #True
        EndIf
      Wend
    EndIf
    If AlreadyExists
      Result = #True
      Debug "MakeConnection : Already Exists"
    Else
      Attributes = "Server=" + Server + ";Description=" + Description + ";DSN=" + DSN
      If Database
        Attributes = Attributes + ";Database=" + Database
      EndIf
      Result = ODBC_ConfigDataSource(Driver, Attributes) 
      Debug "MakeConnection : ConfigDataSource = " + Str(Result)
    EndIf
  EndIf
  ProcedureReturn Result
EndProcedure 

Procedure.i ODBC_DeleteConnection(Driver.s, DSN.s) 
  Protected Library.i, Result.i
  DSN = "DSN=" + DSN
  Result = SQLConfigDataSource_(0, #ODBC_REMOVE_DSN, @Driver, @DSN) 
  Debug "ODBC_DeleteConnection : SQLConfigDataSource = " + Str(Result)
  ProcedureReturn Result 
EndProcedure 
;
; ---
Driver.s = ODBC_FindDriver("Oracle")
Server.s = "MyORACLEDatabase"
DSN.s = "ORACLE"
Database.s = ""
User.s = "xxxxx"
Password.s = "xxxxxxx"
; ---
; Driver.s = ODBC_FindDriver("SQL Server")
; Server.s = "MySQLServerSERVER"
; DSN.s = "SQLS"
; Database.s = "SQLS"
; User.s = "xxx"
; Password.s = "xxx"
; ---
Description.s = "Purebasic-ODBC"
;
If ODBC_MakeConnection(Driver, Server, Database, Description, DSN)
  If OpenDatabase(0, DSN, User, Password) 
    MessageRequester("OPENDATABASE SUCCESS", "Server : " + Server + Chr(10) + "Driver : " + Driver, #MB_ICONINFORMATION)
    CloseDatabase(0)
  Else
    MessageRequester("OPENDATABASE FAILED", "Server : " + Server + Chr(10) + "Driver : " + Driver, #MB_ICONERROR)
  EndIf  
  ODBC_DeleteConnection(Driver, DSN)
Else
  MessageRequester("MAKECONNECTION FAILED", "Server : " + Server + Chr(10) + "Driver : (" + Driver + ")", #MB_ICONERROR)
EndIf
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
User avatar
Le Soldat Inconnu
Enthusiast
Enthusiast
Posts: 306
Joined: Wed Jul 09, 2003 11:33 am
Location: France

Re: ODBC direct connection, find driver name

Post by Le Soldat Inconnu »

Very nice, thanks,

A small correction for "ODBC_DeleteConnection", you do well to connect, but string are not well formated to delete connection.

Code: Select all

Procedure.i ODBC_DeleteConnection(Driver.s, DSN.s)
	Protected Library.i, Result.i, Base, *mem.Character, *ptr.Character, Len, i
	
	DSN = "DSN="+DSN
	
	Len = Len(DSN)
	Base = AllocateMemory((Len + 2) << (SizeOf(Character) - 1))
	If Base
		*mem = Base
		*ptr = @DSN
		For i = 1 To Len
			If *ptr\c <> ';'
				*mem\c = *ptr\c
			EndIf
			*mem + SizeOf(Character)
			*ptr + SizeOf(Character)
		Next
		Result = SQLConfigDataSource_(0, #ODBC_REMOVE_DSN, Driver, Base)
		FreeMemory(Base)
		
	EndIf
	Debug "ODBC_DeleteConnection : SQLConfigDataSource = " + Str(Result)
	ProcedureReturn Result
EndProcedure
LSI
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4789
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: ODBC direct connection, find driver name

Post by Fangbeast »

Mate, did you ever bother to look at the date of this posting?? He isn't going to answer you as it's from 2005!!!

And Gnozal hasn't been seen in the forums for a long time!!
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
Fred
Administrator
Administrator
Posts: 18162
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: ODBC direct connection, find driver name

Post by Fred »

Still good to have the correction if someone else needs it :)
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4789
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: ODBC direct connection, find driver name

Post by Fangbeast »

Fred wrote:Still good to have the correction if someone else needs it :)
Us old folks get confused easily by posts years apart:):):)
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
Post Reply