Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

Open odbc & Delphi2010

Michele P
2009-12-16
2013-05-01
  • Michele P
    Michele P
    2009-12-16

    Exist a release for Delphi 2010
    Thanks

     
  • Inaccessible all source texts new dbx, no example of dbx driver.
    Old example is found In file sources for dbx3 ({Delphi2007}\source\database\src\pas\dbx\).
    Very unfriended attitude to independent developer.

     
  • >We have a chance to get dbxoodbc for Delphi2010 ?
    Only if embarcadero will give example to realization of the new driver.

    At this moment they give very outdated example
    $(BDS)\Demos\database\projects\dbx\driver\as400\

     
  • zmars
    zmars
    2010-07-14

    After some patch, DbxOpenOdbc (dbx3 for Sybase ASA) works in delphi2010 (no full test)
    Thank you.

     
  • The Good news. You are divided with us these corrections?

     
  • zmars
    zmars
    2010-07-14

    1. recompile  …\7.0\source\database\SqlExpr.pas (wtf?)
    //old
      DataTypeMap: array of TFieldType = (
        ftUnknown, ftString, ftDate, ftBlob, ftBoolean, ftSmallint,
        ftInteger, ftFloat, ftFMTBCD, ftBytes, ftTime, ftDateTime,
        ftWord, ftInteger, ftUnknown, ftVarBytes, ftUnknown, ftCursor,
        ftLargeInt, ftLargeInt, ftADT, ftArray, ftReference, ftDataSet,
        ftTimeStamp, ftBCD, ftWideString, ftSingle, ftShortint, ftByte, ftUnknown,
        ftUnknown, ftUnknown, ftUnknown, ftUnknown, ftVariant, ftTimeStampOffset, ftObject,
        ftObject);

    //new (ftBCD, ftFMTBCD)
      DataTypeMap: array of TFieldType = (
        ftUnknown, ftString, ftDate, ftBlob, ftBoolean, ftSmallint,
        ftInteger, ftFloat, ftBCD, ftBytes, ftTime, ftDateTime,
        ftWord, ftInteger, ftUnknown, ftVarBytes, ftUnknown, ftCursor,
        ftLargeInt, ftLargeInt, ftADT, ftArray, ftReference, ftDataSet,
        ftTimeStamp, ftFMTBCD, ftWideString, ftSingle, ftShortint, ftByte, ftUnknown,
        ftUnknown, ftUnknown, ftUnknown, ftUnknown, ftVariant, ftTimeStampOffset, ftObject,
        ftObject);

    2. DbxOpenOdbcDbx3Types.pas
      FldTypeMap: TFieldMap = (
        fldUNKNOWN, fldZSTRING, fldINT16, fldINT32, fldUINT16, fldBOOL, // 0..5
        fldFLOAT, fldFLOAT, fldBCD, fldDATE, fldTIME, fldTIMESTAMP, fldBYTES, // 6..12
        fldVARBYTES, fldINT32, fldBLOB, fldBLOB, fldBLOB, fldBLOB, fldBLOB, // 13..19
        fldBLOB, fldBLOB, fldCURSOR, fldZSTRING, fldWIDESTRING, fldINT64, fldADT, // 20..26
        fldArray, fldREF, fldTABLE, fldBLOB, fldBLOB, fldUNKNOWN, fldUNKNOWN, // 27..33
        //fldUNKNOWN, fldZSTRING, fldDATETIME, {$IFDEF _D12UP_}fldFMTBCD{$ELSE}fldBCD{$ENDIF}, // 33..37
        fldUNKNOWN, fldZSTRING, fldDATETIME, fldBCD, // 33..37
        fldWIDESTRING, fldBLOB, fldDATETIME, fldZSTRING // 38..41
        {$IFDEF _D12UP_}
        ,fldINT32, fldUNKNOWN, fldUNKNOWN, fldFLOAT, fldUnknown, fldUnknown, fldUnknown //42..48
        ,fldUNKNOWN, fldUNKNOWN, fldUNKNOWN //new
        {$ENDIF}
        );

      FldSubTypeMap: array of Word = (
        0, 0, 0, 0, 0, 0, 0, fldstMONEY, 0, 0, 0, 0, 0, 0, fldstAUTOINC, // 0..14
        fldstBINARY, fldstMEMO, fldstGRAPHIC, fldstFMTMEMO, fldstOLEOBJ, // 15..19
        fldstDBSOLEOBJ, fldstTYPEDBINARY, 0, fldstFIXED, 0, // 20..24
        0, 0, 0, 0, 0, fldstHBINARY, fldstHMEMO, 0, 0, 0, {$IFDEF _D12UP_}fldstGUID{$ELSE}0{$ENDIF}, {$IFDEF _D12UP_}{fldstGUID}0{$ELSE}0{$ENDIF}, 0, // 24..37
        fldstFIXED, fldstWIDEMEMO, fldstORATIMESTAMP, fldstORAINTERVAL // 38 ..41
        {$IFDEF _D12UP_}
        ,0, 0, 0, 0, 0, 0, 0 //42..48
        ,0, 0, 0 //new
        {$ENDIF}
      );
     
    3. DbxOpenOdbcFuncs.pas
    function AnsiToOEM;//(const S: AnsiString): AnsiString;
    begin
      SetLength(Result, Length(S));
      if Length(S) > 0 then
        //CharToOem(PAnsiChar(S), PAnsiChar(Result));
        CharToOemA(PAnsiChar(S), PAnsiChar(Result)); //new
    end;

    function OemToAnsi;//(const S: AnsiString): AnsiString;
    begin
      SetLength(Result, Length(S));
      if Length(S) > 0 then
        //OemToChar(PAnsiChar(S), PAnsiChar(Result));
        OemToCharA(PAnsiChar(S), PAnsiChar(Result)); //new
    end;

    4. new unit Dbx4.pas
       from
       http://chee-yang.blogspot.com/2008/09/delphi-2009-using-dbx4-framework.html
      

     
  • zmars
    zmars
    2010-07-14

    unit Dbx4;

    interface

    uses Windows, SysUtils, DBXDynalinkNative, DBXCommon, DBXDynalink, DBXPlatform;

    type
      TDBXAppDriver = class(TDBXDynalinkDriverNative)
      public
        constructor Create(DriverDef: TDBXDriverDef); override;
        procedure LoadDriverWithConnectionBuilder(ConnectionBuilder:
          TDBXConnectionBuilder);
        function CreateConnection(ConnectionBuilder:
          TDBXConnectionBuilder): TDBXConnection; override;
      end;

      TDBXAppProperties = class(TDBXProperties)
      public
        constructor Create(DBXContext: TDBXContext); override;
      end;

      TDBXDynalinkDriverLoader_Enhance = class(TDBXDynalinkDriverLoader)
      private
        procedure FreeOldLibrary;
        procedure LoadDriverLibraryAndMethodTable(DBXContext: TDBXContext; Properties:
            TDBXProperties);
      end;

    implementation

    const
      sDbxOpenOdbc = 'DbxOpenOdbc';

    var
      AppConnectionFactory: TDBXMemoryConnectionFactory;

    { TDBXAppDriver }

    constructor TDBXAppDriver.Create(DriverDef: TDBXDriverDef);
    begin
      inherited Create(DriverDef, TDBXDynalinkDriverLoader);
      InitDriverProperties(TDBXAppProperties.Create(DriverDef.FDBXContext));
    end;

    function TDBXAppDriver.CreateConnection(ConnectionBuilder:
        TDBXConnectionBuilder): TDBXConnection;
    var
      ConnectionHandle: TDBXConnectionHandle;
      ErrorResult:  TDBXErrorCode;
    begin
      LoadDriverWithConnectionBuilder(ConnectionBuilder);
      ErrorResult := FMethodTable.FDBXDriver_CreateConnection(FDriverHandle, ConnectionHandle);
      CheckResult(ErrorResult);
      Result := TDBXDynalinkConnection.Create(ConnectionBuilder, ConnectionHandle, FMethodTable);
    end;

    procedure TDBXAppDriver.LoadDriverWithConnectionBuilder(ConnectionBuilder:
        TDBXConnectionBuilder);
    var
      Loader: TDBXDynalinkDriverLoader_Enhance;
    begin
      if not Assigned(FMethodTable) then
      begin
        Loader := TDBXDynalinkDriverLoader_Enhance(FDriverLoaderClass.Create); // as TDBXDynalinkDriverLoader_Enhance;
        try
          Loader.LoadDriverLibraryAndMethodTable(ConnectionBuilder.DbxContext, ConnectionBuilder.ConnectionProperties);
          FMethodTable := Loader.FMethodTable;
          Loader.FMethodTable := nil;
          FDriverHandle := Loader.FDriverHandle;
          Loader.FreeOldLibrary;
        finally
          FreeAndNil(Loader.FMethodTable);
          Loader.Free;
        end;
      end;
    end;

    { TDBXAppProperties }

    constructor TDBXAppProperties.Create(DBXContext: TDBXContext);
    begin
      inherited Create(DBXContext);
      Values := '';
      //Values := 'TDBXDynalinkDriverLoader,DBXCommonDriver120.bpl';
      //Values := 'TDBXOracleMetaDataCommandFactory,DBXOracleDriver120.bpl';

      Values := 'getSQLDriverODBCW'; //'getSQLDriverODBCWA';
      Values := 'dbxoodbc.dll';
      Values := 'dbodbc9.dll';

      Values := 'test';
      Values := 'dba';
      Values := 'sql';

      Values := '-1';
      Values := '';
      //Values := '0000';
      ////////Values := 'ReadCommited';
    end;

    procedure TDBXDynalinkDriverLoader_Enhance.LoadDriverLibraryAndMethodTable(
      DBXContext: TDBXContext; Properties: TDBXProperties);
    var
      ErrorResult:          TDBXErrorCode;
      ErrorMessageBuilder:  TDBXWideStringBuilder;
      Count:                TInt32;
      Names:                TWideStringArray;
      Values:               TWideStringArray;
      ErrorMessage:         UnicodeString;
    begin
      if Properties <> '' then
      begin
        LoadDriverLibrary(Properties, DBXContext);
        FMethodTable   := CreateMethodTable;
        try
          FMethodTable.LoadMethods;
        except
          on EDBXError: TDBXError do
            begin
              DBXContext.OnError(EDBXError);
              raise;
            end;
        end;
        Count := Properties.Properties.Count;
        Properties.GetLists(Names, Values);

        ErrorMessageBuilder := TDBXPlatform.CreateWideStringBuilder(256);
        try
          ErrorResult := FMethodTable.FDBXLoader_GetDriver(Count, Names, Values,
                                                           TDBXWideStringBuilder(ErrorMessageBuilder),
                                                           FDriverHandle);

          if ErrorResult <> TDBXErrorCodes.None then
          begin
            TDBXPlatform.CopyWideStringBuilder(ErrorMessageBuilder, ErrorMessage);

            DBXContext.Error(ErrorResult, ErrorMessage);
          end;
        finally
           TDBXPlatform.FreeAndNilWideStringBuilder(ErrorMessageBuilder);
        end;

      end;

    end;

    procedure TDBXDynalinkDriverLoader_Enhance.FreeOldLibrary;
    begin
        if FOldLibraryHandle <> 0 then
        begin
          FreeLibrary(FOldLibraryHandle);
          FOldLibraryHandle := 0;
        end;
    end;

    initialization
      TDBXDriverRegistry.RegisterDriverClass(sDbxOpenOdbc, TDBXAppDriver);
      AppConnectionFactory := TDBXMemoryConnectionFactory.Create;
      AppConnectionFactory.Open;
      TDBXConnectionFactory.SetConnectionFactory(AppConnectionFactory);

    finalization
      TDBXDriverRegistry.UnregisterDriverClass(sDbxOpenOdbc);

    end.

     
  • Thank you ! ! !
    In the near future I shall contribute your changes to project.

     
  • > 1. recompile  …\7.0\source\database\SqlExpr.pas

    correct bad determination of DataTypeMap in "SqlExpr.pas":

    in any your pas module:

    uses
        …, DB, DSIntf, SqlExpr;

    initialization
      {$WRITEABLECONST ON}
      DataTypeMap := ftBCD;
      DataTypeMap := ftFMTBCD;
    end.

     
  • zmars
    zmars
    2010-07-21

    Delphi2010, Sybase ASA9, DbxOpenODBC 3.206 + fix

    select id, col1, col2 from TestTable where id in (655431, 655433)
    //id   integer
    //col1 long varchar
    //col2 long binary

    Event log:

    Debug Output: :(    0) ->:TSqlCursorOdbc.next; Process Project1.exe (368)
    Debug Output: :(    0) ~-:TSqlCursorOdbc.next; Process Project1.exe (368)
    Module Load: midas.dll. No Debug Info. Base Address: $4DAE0000. Process Project1.exe (368)
    Debug Output: :(    0) ->:TSqlCursorOdbc.getLong,  Params: ColumnNumber = "1"; Process Project1.exe (368)
    Debug Output: :(    0) ~-:TSqlCursorOdbc.getLong,  ExitInfo: Value = "655431" IsBlank = "False"; Process Project1.exe (368)
    Debug Output: :(    0) ->:TSqlCursorOdbc.next; Process Project1.exe (368)
    Debug Output: :(    0) ~-:TSqlCursorOdbc.next; Process Project1.exe (368)
    Debug Output: :(    0) ->:TSqlCursorOdbc.getLong,  Params: ColumnNumber = "1"; Process Project1.exe (368)
    Debug Output: :(    0) ~-:TSqlCursorOdbc.getLong,  ExitInfo: Value = "655433" IsBlank = "False"; Process Project1.exe (368)
    Debug Output: :(    0) ->:TSqlCursorOdbc.next; Process Project1.exe (368)
    Debug Output: :(    0) ~-:TSqlCursorOdbc.next; Process Project1.exe (368)
    Debug Output: :(    0) ->:TSqlCursorOdbc3.Destroy; Process Project1.exe (368)

    Why I don't get values for col1 and col2?
    Thank you in advance!

     
  • These field are seen in FieldsEditor ?

     
  • Is out  new version "Version 3.210, 2010-07-27_ Beta "

    Changed: "demos\connections\dbx_sybase_connect.pas"

    Added query based metadata reader:

      with SQLConnection.Params do
      begin …
        if SybaseServerType in  then
          Values :=
            TDBXOpenODBCMetaDataCommandFactorySybaseASA.ClassName
        else
          Values :=
            TDBXOpenODBCMetaDataCommandFactorySybaseASE.ClassName;

    see "dbxoodbx\packages\source\Dbx34DrvDbms.pas"
    but I did not test it since have not sybase

    other changes:

    + fixed (DbxOpenOdbc*.pas):
          - fetch BLOB/MEMO for Delphi 2009 Up
          - read metadata WideString (buffer overflow)
          - set parameters for WideString (loss symbols when editing)

    + critical: new modules:
                DbxDrv.pas - new module for your applications. This module uses(tightens)
                  other critical modules:

                DbxDBFix.pas      - fixed many QC critical bugs { !!! critical !!! }
                Dbx34Drv.pas      - implementation driver loader and metadata reader stub.
                                    // todo: implement stub to usage dbx3 interfaces for read metadata
                Dbx34DrvDbms.pas  - implements metadata reader for sql based dbms (oracle,
                  mssql, mysql sybase, db2, informix, firebird, interbase, datastorage)
                Dbx23Fix.pas      - it modules fixed some problem for usage driver in
                  Delphi 2005 Down (old name SqlExprFix.pas)

    + All "Demos" is updated for usage in Delphi 6 .. 2010
    + Connection Examples: "demos\connections"

    ! critical: must use DbxXXDrv.pas in your applications for dbxoodbc work correctly.

    ! critical for Delphi 2007:
         // must use connection option "DriverPackageLoader":
         SQLConnection.Params.Values := // 'TDBXDynalinkDriverLoaderOpenOdbc'
          TDBXDynalinkDriverLoaderOpenOdbc.ClassName;

    ! critical for Delphi 2009 Up:
         // must use connection option "MetaDataPackageLoader":
         SQLConnection.Params.Values := // == 'TDBXOpenODBCMetaDataCommandFactory'
           TDBXOpenODBCMetaDataCommandFactory.ClassName;
         or

         Values := //  == 'TDBXOpenODBCMetaDataCommandFactory%DBMS-NAME%'
            TDBXOpenODBCMetaDataCommandFactory%DBMS-NAME%.ClassName;

         %DBMS-NAME% can take following values (Dbx34DrvDbms.pas):
           ORACLE, MSSQL, MySQL, SybaseASA, SybaseASE, DB2, Informix, DataStorage, Firebird, Interbase

         Example:
           // SybaseASE
         Values := //  == 'TDBXOpenODBCMetaDataCommandFactorySybaseASE'
            TDBXOpenODBCMetaDataCommandFactorySybaseASE.ClassName;
           // DBF, MSACCESS, XLS
         SQLConnection.Params.Values :=
           TDBXOpenODBCMetaDataCommandFactory.ClassName;

         TDBXOpenODBCMetaDataCommandFactory in persisting time realizes only stub for exception
           errors (opening of the table TSqlTable.Open)
         In following version this will is corrected.

    ! critical for IDE: "packages\binary"
          packages for access to dbxoodbc driver loader from IDE

            PkgDbxXXDrv2010.dpk - for RAD Studio 2010
            PkgDbxXXDrv2009.dpk - for RAD Studio 2009
            PkgDbxXXDrv2007.dpk - for RAD Studio 2007

    + also changes "driver\binary" (dbxdrivers.ini, dbxconnections.ini):
          dbx2:
              dbx2-drivers.ini
              dbx2-connections.ini
          dbx3: requires "dbxadapter30.dll"
              dbx3-drivers.ini
              dbx3-connections.ini
          dbx4: requires "dbxadapter.dll"
              dbx4-drivers.ini
              dbx4-connections.ini

     
  • > Delphi2010, Sybase ASA9, DbxOpenODBC 3.206 + fix
    > select id, col1, col2 from TestTable where id in (655431, 655433)

    need retest on new version (must added to your project DbxDrv.pas)

     
  • zmars
    zmars
    2010-08-03

    >>need retest on new version (must added to your project DbxDrv.pas)

    Thank you!
    Everything works fine, except one problem:

    select col1 from TestTable where length(col1)=100
    //col1 varchar(100)

    -------------FastMM log:------------------
    FastMM обнаружил ошибку во время FreeMem операция. Нижняя часть блока повреждена.

    Размер блока: 108

    This block was allocated by thread 0xDA0, and the stack trace (return addresses) at the time was:
    404759
    409618
    5769EE
    4096EE
    59C08A
    53E31E
    53E87A
    54193E
    5444A4
    542CDF
    54411B

    Блок в настоящее время используется для объекта класса: Unknown

    Выделенный номер стал: 10114

    The block was previously freed by thread 0xDA0, and the stack trace (return addresses) at the time was:
    404706
    406B59
    407C5A
    40836E
    444F52
    571FE2
    57222F
    57235B
    5717B2
    57184E
    5718DC

    The current thread ID is 0xDA0, and the stack trace (return addresses) leading to this error is:
    404706
    40983C
    409549
    409580
    539C3D
    4096EE
    59B6CD
    59B45F
    5119CC
    59B37A
    511895


    ps: D2010, Sybase ASA9, DbxOpenODBC 3.212

     
  • I was able to reproduce this situation for D2007..D2011:

      example:        dbf
      query:             select t.* from   `таблица_пример`

    For D6-D2006 such memleak not.
    It is bug of dbx library.
    Need search it in QC or or by itself debug…

    As soon as will appear time - I shall look this subjects…

     
  • Version 3.214, 2010-08-04:

    + fixed: buffer overflow when reading AnsiString (DbxOpenOdbc.pas)
    ^^^^^^^^^^^
    + added sqlite demo (demos\dbms\sqlite\sql) and include sqlite
         odbc driver dll (demos\dbms\sqlite\odbc-driver)

     
  • zmars
    zmars
    2010-08-04

    With v3.214 i get the same error.
    FastMM 4.94

     
  • Version 3.215, 2010-08-05:

    + fixed: buffer overflow when reading string values (DbxOpenOdbc*.pas)
              new logic for methods: ".getColumnPrecision", ".getColumnLength"
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    + added SQLite metadata reader class "TDBXOpenODBCMetaDataCommandFactorySQLite"
    + Fast Memory Manager updated to 4.94