Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Comment: | added ODBC support to SynDBExplorer (sounds to work fine, so far - but sower than direct OCI access) |
---|---|
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
f324d469ee1bbe4f0a1f952d83a886a1 |
User & Date: | ab 2012-08-10 14:36:46 |
2012-08-10
| ||
14:59 | updated documentation about the new ODBC direct connection access (SynDBODBC.pas unit) check-in: 0980301f72 user: ab tags: trunk | |
14:36 | added ODBC support to SynDBExplorer (sounds to work fine, so far - but sower than direct OCI access) check-in: f324d469ee user: ab tags: trunk | |
09:59 | void TEXT column export fix check-in: 8044c5ea7c user: ab tags: trunk | |
Changes to SQLite3/Samples/12 - SynDB Explorer/SynDBExplorer.dpr.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
- now direct-to-file fast export feature (into CSV, TXT, SQLite3, Synopse BigTable records or two JSON flavors) - now multi tables direct export into SQLite3 DB files (e.g. for support) - SQLite3 3.7.12.1 including (beta) private encryption methods Version 1.17 - added Jet / MSAccess direct support (via OleDB provider) - added log history of SQL requests (in SynDBExplorer.history file) - SQLite3 engine updated to revision 3.7.13 - changed .config file format from binary to JSON (with Base64+Zip if needed) first line of uses clause must be {$I SynDprUses.inc} to enable FastMM4 conditional define should contain INCLUDE_FTS3 to handle FTS3/FTS4 in SQLite3 |
> |
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
- now direct-to-file fast export feature (into CSV, TXT, SQLite3,
Synopse BigTable records or two JSON flavors)
- now multi tables direct export into SQLite3 DB files (e.g. for support)
- SQLite3 3.7.12.1 including (beta) private encryption methods
Version 1.17
- added Jet / MSAccess direct support (via OleDB provider)
- added ODBC providers direct support
- added log history of SQL requests (in SynDBExplorer.history file)
- SQLite3 engine updated to revision 3.7.13
- changed .config file format from binary to JSON (with Base64+Zip if needed)
first line of uses clause must be {$I SynDprUses.inc} to enable FastMM4
conditional define should contain INCLUDE_FTS3 to handle FTS3/FTS4 in SQLite3
|
Changes to SQLite3/Samples/12 - SynDB Explorer/SynDBExplorerClasses.pas.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
uses SysUtils, Classes, SynCommons, SQLite3Commons; type TExpConnectionType = ( ctOracleDirectOCI, ctOracleOLEDB, ctOracleMSOLEDB, ctMSSQL, ctGenericOLEDB, ctSqlite3, ctJet_mdbOLEDB); TSQLConnection = class(TSQLRecord) private fUserName: RawUTF8; fIdent: RawUTF8; fPassword: RawUTF8; fServer: RawUTF8; |
| |
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
uses
SysUtils, Classes,
SynCommons, SQLite3Commons;
type
TExpConnectionType = (
ctOracleDirectOCI, ctOracleOLEDB, ctOracleMSOLEDB, ctMSSQL, ctGenericOLEDB,
ctSqlite3, ctJet_mdbOLEDB, ctODBC);
TSQLConnection = class(TSQLRecord)
private
fUserName: RawUTF8;
fIdent: RawUTF8;
fPassword: RawUTF8;
fServer: RawUTF8;
|
Changes to SQLite3/Samples/12 - SynDB Explorer/SynDBExplorerMain.pas.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 .. 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 .. 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Grids, ExtCtrls, StdCtrls, Consts, SynCommons, SQLite3Commons, SynSQLite3, SynZip, SQLite3i18n, SQLite3UI, SQLite3UIEdit, SQLite3UILogin, SQLite3ToolBar, SynTaskDialog, SynDB, SynDBOracle, SynOleDB, SynDBSQLite3, SynDBExplorerClasses, SynDBExplorerFrame, ComCtrls; type TDbExplorerMain = class(TForm) procedure FormDestroy(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormShow(Sender: TObject); ................................................................................ resourcestring sSelectAConnection = 'Select a connection'; sNew = 'New connection'; sNewOne = 'New'; sConnectionHints = 'Display name|Database type|Server name '+ '(for "Generic OLEDB", use ADO-like connection string, and ignore other fields; '+ 'for SQLite3 or Jet, specify the full file name)|'+ 'Database name (unneeded for Oracle/SQLite3/Jet)|User login|'+ 'User password (set ? for prompt)'; sSelectOrCreateAConnection = 'Select a connection to be used, or\n'+ 'click on "New connection" to create one.'; sPleaseWaitN = 'Connecting to %s...'; sUpdateConnection = 'Update connection settings'; sPassPromptN = 'Please enter password for %s@%s:'; ................................................................................ procedure TDbExplorerMain.FormCreate(Sender: TObject); var Conns: TSQLRestServerStaticInMemory; function TryConnect(C: TSQLConnection; LoadTableNames: boolean): boolean; const CONN_CLASSES: array[TExpConnectionType] of TSQLDBConnectionPropertiesClass = (TSQLDBOracleConnectionProperties,TOleDBOracleConnectionProperties, TOleDBMSOracleConnectionProperties,TOleDBMSSQLConnectionProperties, TOleDBConnectionProperties,TSQLDBSQLite3ConnectionProperties, TOleDBJetConnectionProperties); var i: integer; Pass: RawUTF8; begin result := false; try Pass := Crypt(C.Password); if Pass='?' then |
| | | |
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 .. 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 .. 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Grids, ExtCtrls, StdCtrls, Consts, SynCommons, SQLite3Commons, SynSQLite3, SynZip, SQLite3i18n, SQLite3UI, SQLite3UIEdit, SQLite3UILogin, SQLite3ToolBar, SynTaskDialog, SynDB, SynDBOracle, SynOleDB, SynDBSQLite3, SynDBODBC, SynDBExplorerClasses, SynDBExplorerFrame, ComCtrls; type TDbExplorerMain = class(TForm) procedure FormDestroy(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormShow(Sender: TObject); ................................................................................ resourcestring sSelectAConnection = 'Select a connection'; sNew = 'New connection'; sNewOne = 'New'; sConnectionHints = 'Display name|Database type|Server name '+ '(for "Generic OLEDB", use ADO-like connection string, and ignore other fields; '+ 'for SQLite3 or Jet, specify the full file name)|'+ 'Database name (unneeded for Oracle/SQLite3/Jet/ODBC)|User login|'+ 'User password (set ? for prompt)'; sSelectOrCreateAConnection = 'Select a connection to be used, or\n'+ 'click on "New connection" to create one.'; sPleaseWaitN = 'Connecting to %s...'; sUpdateConnection = 'Update connection settings'; sPassPromptN = 'Please enter password for %s@%s:'; ................................................................................ procedure TDbExplorerMain.FormCreate(Sender: TObject); var Conns: TSQLRestServerStaticInMemory; function TryConnect(C: TSQLConnection; LoadTableNames: boolean): boolean; const CONN_CLASSES: array[TExpConnectionType] of TSQLDBConnectionPropertiesClass = (TSQLDBOracleConnectionProperties,TOleDBOracleConnectionProperties, TOleDBMSOracleConnectionProperties,TOleDBMSSQLConnectionProperties, TOleDBConnectionProperties,TSQLDBSQLite3ConnectionProperties, TOleDBJetConnectionProperties,TODBCConnectionProperties); var i: integer; Pass: RawUTF8; begin result := false; try Pass := Crypt(C.Password); if Pass='?' then |
Changes to SynDBODBC.pas.
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 ... 279 280 281 282 283 284 285 286 287 288 289 290 291 292 ... 665 666 667 668 669 670 671 672 673 674 675 676 677 678 ... 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 .... 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 .... 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 .... 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 .... 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 |
/// get all table names // - will retrieve the corresponding metadata from ODBC library if SQL // direct access was not defined procedure GetTableNames(var Tables: TRawUTF8DynArray); override; /// retrieve the column/field layout of a specified table // - will retrieve the corresponding metadata from ODBC library if SQL // direct access was not defined // - if GetForeignKey is TRUE, will retrieve ColumnForeignKey* properties, // but will be much slower procedure GetFields(const aTableName: RawUTF8; var Fields: TSQLDBColumnDefineDynArray); override; end; /// implements a direct connection to the ODBC library TODBCConnection = class(TSQLDBConnectionThreadSafe) protected fODBCProperties: TODBCConnectionProperties; fEnv: pointer; ................................................................................ // env attribute SQL_ATTR_ODBC_VERSION = 200; SQL_ATTR_CONNECTION_POOLING = 201; SQL_ATTR_CP_MATCH = 202; SQL_ATTR_OUTPUT_NTS = 10001; SQL_OV_ODBC3 = pointer(3); // connection attributes SQL_ACCESS_MODE = 101; SQL_AUTOCOMMIT = 102; SQL_LOGIN_TIMEOUT = 103; SQL_OPT_TRACE = 104; SQL_OPT_TRACEFILE = 105; ................................................................................ {$ifdef MSWINDOWS} stdcall {$else} cdecl {$endif}; ColumnsW: function(StatementHandle: SqlHStmt; CatalogName: PWideChar; NameLength1: SqlSmallint; SchemaName: PWideChar; NameLength2: SqlSmallint; TableName: PWideChar; NameLength3: SqlSmallint; ColumnName: PWideChar; NameLength4: SqlSmallint): SqlReturn; {$ifdef MSWINDOWS} stdcall {$else} cdecl {$endif}; ConnectA: function(ConnectionHandle: SqlHDbc; ServerName: PAnsiChar; NameLength1: SqlSmallint; UserName: PAnsiChar; NameLength2: SqlSmallint; Authentication: PAnsiChar; NameLength3: SqlSmallint): SqlReturn; {$ifdef MSWINDOWS} stdcall {$else} cdecl {$endif}; ConnectW: function(ConnectionHandle: SqlHDbc; ServerName: PWideChar; NameLength1: SqlSmallint; ................................................................................ {$ifdef MSWINDOWS} stdcall {$else} cdecl {$endif}; TablesW: function(StatementHandle: SqlHStmt; CatalogName: PWideChar; NameLength1: SqlSmallint; SchemaName: PWideChar; NameLength2: SqlSmallint; TableName: PWideChar; NameLength3: SqlSmallint; TableType: PWideChar; NameLength4: SqlSmallint): SqlReturn; {$ifdef MSWINDOWS} stdcall {$else} cdecl {$endif}; public /// load the ODBC library // - and retrieve all SQL*() addresses for ODBC_ENTRIES[] items constructor Create; /// raise an exception on error procedure Check(Status: SqlReturn; HandleType: SqlSmallint; Handle: SqlHandle; InfoRaiseException: Boolean=false; LogLevelNoRaise: TSynLogInfo=sllNone); {$ifdef HASINLINE} inline; {$endif} end; const ODBC_ENTRIES: array[0..56] of PChar = ('SQLAllocEnv','SQLAllocHandle','SQLAllocStmt', 'SQLBindCol','SQLBindParameter','SQLCancel','SQLCloseCursor', 'SQLColAttribute','SQLColAttributeW','SQLColumns','SQLColumnsW', 'SQLConnect','SQLConnectW','SQLCopyDesc','SQLDataSources','SQLDataSourcesW', 'SQLDescribeCol','SQLDescribeColW','SQLDisconnect','SQLEndTran', 'SQLError','SQLErrorW','SQLExecDirect','SQLExecDirectW','SQLExecute', 'SQLFetch','SQLFetchScroll','SQLFreeConnect','SQLFreeEnv','SQLFreeHandle', 'SQLFreeStmt','SQLGetConnectAttr','SQLGetConnectAttrW', 'SQLGetCursorName','SQLGetCursorNameW','SQLGetData', 'SQLGetDescField','SQLGetDescFieldW','SQLGetDescRec','SQLGetDescRecW', 'SQLGetDiagField','SQLGetDiagFieldW','SQLGetDiagRec','SQLGetDiagRecW', 'SQLPrepare','SQLPrepareW','SQLRowCount','SQLNumResultCols', 'SQLGetInfo','SQLGetInfoW','SQLSetStmtAttr','SQLSetStmtAttrW','SQLSetEnvAttr', 'SQLSetConnectAttr','SQLSetConnectAttrW','SQLTables','SQLTablesW'); var ODBC: TODBCLib = nil; { TODBCConnection } ................................................................................ for c := 1 to nCols do begin Check(DescribeColW(fStatement,c,Name,256,NameLength,DataType,ColumnSize, DecimalDigits,Nullable),SQL_HANDLE_STMT,fStatement); with PSQLDBColumnProperty(fColumn.AddAndMakeUniqueName( RawUnicodeToUtf8(Name,NameLength)))^ do begin ColumnValueInlined := true; ColumnValueDBType := DataType; ColumnValueDBSize := ColumnSize; ColumnNonNullable := (Nullable=SQL_NO_NULLS); ColumnType := ODBCColumnToFieldType(DataType,10,DecimalDigits); if ColumnType=ftUTF8 then siz := ColumnSize*2+2 else // guess max size as WideChar buffer siz := ColumnSize; if siz>fColTmpLen then ................................................................................ result := inherited SQLCreate(aTableName,aFields); end; procedure TODBCConnectionProperties.GetFields(const aTableName: RawUTF8; var Fields: TSQLDBColumnDefineDynArray); var Schema, Table: RawUTF8; F: TSQLDBColumnDefine; n: integer; status: SqlReturn; FA: TDynArray; begin inherited; // first try from SQL, if any (faster) if Fields<>nil then exit; // already retrieved directly from engine Split(aTableName,'.',Schema,Table); ................................................................................ if Table='' then begin Table := Schema; Schema := '%'; end; Table := UpperCase(Table); Schema := UpperCase(Schema); try with TODBCStatement.Create(MainConnection) do try AllocStatement; status := ODBC.ColumnsA(fStatement,nil,0,pointer(Schema),SQL_NTS, pointer(Table),SQL_NTS,nil,0); if status<>SQL_SUCCESS then // e.g. driver does not support schema status := ODBC.ColumnsA(fStatement,nil,0,nil,0,pointer(Table),SQL_NTS,nil,0); ODBC.Check(status,SQL_HANDLE_STMT,fStatement); BindColumns; FA.Init(TypeInfo(TSQLDBColumnDefineDynArray),Fields,@n); while Step do begin F.ColumnName := ColumnUTF8(3); F.ColumnLength := ColumnInt(6); F.ColumnPrecision := ColumnInt(9); F.ColumnScale := ColumnInt(8); F.ColumnTypeNative := ColumnUTF8(5); F.ColumnType:= ODBCColumnToFieldType(ColumnInt(4), ................................................................................ F.ColumnPrecision,F.ColumnScale); FA.Add(F); end; SetLength(Fields,n); finally Free; // TODBCStatement release end; except on Exception do SetLength(Fields,0); end; end; procedure TODBCConnectionProperties.GetTableNames(var Tables: TRawUTF8DynArray); var Stmt: TODBCStatement; n: integer; schema, tablename: RawUTF8; begin inherited; // first try from SQL, if any (faster) if Tables<>nil then exit; // already retrieved directly from engine try Stmt := TODBCStatement.Create(MainConnection); with ODBC do try Stmt.AllocStatement; Check(TablesA(Stmt.fStatement,nil,0,nil,0,nil,0,'TABLE',SQL_NTS),SQL_HANDLE_STMT,Stmt.fStatement); Stmt.BindColumns; n := 0; with Stmt do while Step do begin schema := ColumnUTF8(1); tablename := ColumnUTF8(2); if schema<>'' then tablename := schema+'.'+tablename; AddSortedRawUTF8(Tables,n,tablename); end; SetLength(Tables,n); finally Stmt.Free; end; except on Exception do SetLength(Tables,0); end; end; { SQL_TIMESTAMP_STRUCT } function SQL_TIMESTAMP_STRUCT.From(DateTime: TDateTime): SqlSmallint; var Y,MS: word; begin |
< < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > < | | < | | | < | > > > > > > > > > > > > > > > > > > > > > |
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 ... 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 ... 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 ... 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 .... 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 .... 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 .... 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 .... 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 |
/// get all table names // - will retrieve the corresponding metadata from ODBC library if SQL // direct access was not defined procedure GetTableNames(var Tables: TRawUTF8DynArray); override; /// retrieve the column/field layout of a specified table // - will retrieve the corresponding metadata from ODBC library if SQL // direct access was not defined procedure GetFields(const aTableName: RawUTF8; var Fields: TSQLDBColumnDefineDynArray); override; /// initialize fForeignKeys content with all foreign keys of this DB // - used by GetForeignKey method procedure GetForeignKeys; override; end; /// implements a direct connection to the ODBC library TODBCConnection = class(TSQLDBConnectionThreadSafe) protected fODBCProperties: TODBCConnectionProperties; fEnv: pointer; ................................................................................ // env attribute SQL_ATTR_ODBC_VERSION = 200; SQL_ATTR_CONNECTION_POOLING = 201; SQL_ATTR_CP_MATCH = 202; SQL_ATTR_OUTPUT_NTS = 10001; SQL_OV_ODBC3 = pointer(3); // values for SQLStatistics() SQL_INDEX_UNIQUE = 0; SQL_INDEX_ALL = 1; SQL_QUICK = 0; SQL_ENSURE = 1; // connection attributes SQL_ACCESS_MODE = 101; SQL_AUTOCOMMIT = 102; SQL_LOGIN_TIMEOUT = 103; SQL_OPT_TRACE = 104; SQL_OPT_TRACEFILE = 105; ................................................................................ {$ifdef MSWINDOWS} stdcall {$else} cdecl {$endif}; ColumnsW: function(StatementHandle: SqlHStmt; CatalogName: PWideChar; NameLength1: SqlSmallint; SchemaName: PWideChar; NameLength2: SqlSmallint; TableName: PWideChar; NameLength3: SqlSmallint; ColumnName: PWideChar; NameLength4: SqlSmallint): SqlReturn; {$ifdef MSWINDOWS} stdcall {$else} cdecl {$endif}; StatisticsA: function(StatementHandle: SqlHStmt; CatalogName: PAnsiChar; NameLength1: SqlSmallint; SchemaName: PAnsiChar; NameLength2: SqlSmallint; TableName: PAnsiChar; NameLength3: SqlSmallint; Unique, Reserved: SqlUSmallint): SqlReturn; {$ifdef MSWINDOWS} stdcall {$else} cdecl {$endif}; StatisticsW: function(StatementHandle: SqlHStmt; CatalogName: PWideChar; NameLength1: SqlSmallint; SchemaName: PWideChar; NameLength2: SqlSmallint; TableName: PWideChar; NameLength3: SqlSmallint; Unique, Reserved: SqlUSmallint): SqlReturn; {$ifdef MSWINDOWS} stdcall {$else} cdecl {$endif}; ConnectA: function(ConnectionHandle: SqlHDbc; ServerName: PAnsiChar; NameLength1: SqlSmallint; UserName: PAnsiChar; NameLength2: SqlSmallint; Authentication: PAnsiChar; NameLength3: SqlSmallint): SqlReturn; {$ifdef MSWINDOWS} stdcall {$else} cdecl {$endif}; ConnectW: function(ConnectionHandle: SqlHDbc; ServerName: PWideChar; NameLength1: SqlSmallint; ................................................................................ {$ifdef MSWINDOWS} stdcall {$else} cdecl {$endif}; TablesW: function(StatementHandle: SqlHStmt; CatalogName: PWideChar; NameLength1: SqlSmallint; SchemaName: PWideChar; NameLength2: SqlSmallint; TableName: PWideChar; NameLength3: SqlSmallint; TableType: PWideChar; NameLength4: SqlSmallint): SqlReturn; {$ifdef MSWINDOWS} stdcall {$else} cdecl {$endif}; ForeignKeysA: function(StatementHandle: SqlHStmt; PKCatalogName: PAnsiChar; NameLength1: SqlSmallint; PKSchemaName: PAnsiChar; NameLength2: SqlSmallint; PKTableName: PAnsiChar; NameLength3: SqlSmallint; FKCatalogName: PAnsiChar; NameLength4: SqlSmallint; FKSchemaName: PAnsiChar; NameLength5: SqlSmallint; FKTableName: PAnsiChar; NameLength6: SqlSmallint): SqlReturn; {$ifdef MSWINDOWS} stdcall {$else} cdecl {$endif}; ForeignKeysW: function(StatementHandle: SqlHStmt; PKCatalogName: PWideChar; NameLength1: SqlSmallint; PKSchemaName: PWideChar; NameLength2: SqlSmallint; PKTableName: PWideChar; NameLength3: SqlSmallint; FKCatalogName: PWideChar; NameLength4: SqlSmallint; FKSchemaName: PWideChar; NameLength5: SqlSmallint; FKTableName: PWideChar; NameLength6: SqlSmallint): SqlReturn; {$ifdef MSWINDOWS} stdcall {$else} cdecl {$endif}; public /// load the ODBC library // - and retrieve all SQL*() addresses for ODBC_ENTRIES[] items constructor Create; /// raise an exception on error procedure Check(Status: SqlReturn; HandleType: SqlSmallint; Handle: SqlHandle; InfoRaiseException: Boolean=false; LogLevelNoRaise: TSynLogInfo=sllNone); {$ifdef HASINLINE} inline; {$endif} end; const ODBC_ENTRIES: array[0..60] of PChar = ('SQLAllocEnv','SQLAllocHandle','SQLAllocStmt', 'SQLBindCol','SQLBindParameter','SQLCancel','SQLCloseCursor', 'SQLColAttribute','SQLColAttributeW','SQLColumns','SQLColumnsW', 'SQLStatistics','SQLStatisticsW','SQLConnect','SQLConnectW', 'SQLCopyDesc','SQLDataSources','SQLDataSourcesW', 'SQLDescribeCol','SQLDescribeColW','SQLDisconnect','SQLEndTran', 'SQLError','SQLErrorW','SQLExecDirect','SQLExecDirectW','SQLExecute', 'SQLFetch','SQLFetchScroll','SQLFreeConnect','SQLFreeEnv','SQLFreeHandle', 'SQLFreeStmt','SQLGetConnectAttr','SQLGetConnectAttrW', 'SQLGetCursorName','SQLGetCursorNameW','SQLGetData', 'SQLGetDescField','SQLGetDescFieldW','SQLGetDescRec','SQLGetDescRecW', 'SQLGetDiagField','SQLGetDiagFieldW','SQLGetDiagRec','SQLGetDiagRecW', 'SQLPrepare','SQLPrepareW','SQLRowCount','SQLNumResultCols', 'SQLGetInfo','SQLGetInfoW','SQLSetStmtAttr','SQLSetStmtAttrW','SQLSetEnvAttr', 'SQLSetConnectAttr','SQLSetConnectAttrW','SQLTables','SQLTablesW', 'SQLForeignKeys','SQLForeignKeysW'); var ODBC: TODBCLib = nil; { TODBCConnection } ................................................................................ for c := 1 to nCols do begin Check(DescribeColW(fStatement,c,Name,256,NameLength,DataType,ColumnSize, DecimalDigits,Nullable),SQL_HANDLE_STMT,fStatement); with PSQLDBColumnProperty(fColumn.AddAndMakeUniqueName( RawUnicodeToUtf8(Name,NameLength)))^ do begin ColumnValueInlined := true; ColumnValueDBType := DataType; if ColumnSize>65535 then ColumnSize := 0; // avoid out of memory error for BLOBs ColumnValueDBSize := ColumnSize; ColumnNonNullable := (Nullable=SQL_NO_NULLS); ColumnType := ODBCColumnToFieldType(DataType,10,DecimalDigits); if ColumnType=ftUTF8 then siz := ColumnSize*2+2 else // guess max size as WideChar buffer siz := ColumnSize; if siz>fColTmpLen then ................................................................................ result := inherited SQLCreate(aTableName,aFields); end; procedure TODBCConnectionProperties.GetFields(const aTableName: RawUTF8; var Fields: TSQLDBColumnDefineDynArray); var Schema, Table: RawUTF8; F: TSQLDBColumnDefine; i,n: integer; status: SqlReturn; FA: TDynArray; begin inherited; // first try from SQL, if any (faster) if Fields<>nil then exit; // already retrieved directly from engine Split(aTableName,'.',Schema,Table); ................................................................................ if Table='' then begin Table := Schema; Schema := '%'; end; Table := UpperCase(Table); Schema := UpperCase(Schema); try // get column definitions with TODBCStatement.Create(MainConnection) do try AllocStatement; status := ODBC.ColumnsA(fStatement,nil,0,pointer(Schema),SQL_NTS, pointer(Table),SQL_NTS,nil,0); if status<>SQL_SUCCESS then // e.g. driver does not support schema status := ODBC.ColumnsA(fStatement,nil,0,nil,0,pointer(Table),SQL_NTS,nil,0); ODBC.Check(status,SQL_HANDLE_STMT,fStatement); BindColumns; FA.Init(TypeInfo(TSQLDBColumnDefineDynArray),Fields,@n); fillchar(F,sizeof(F),0); while Step do begin F.ColumnName := ColumnUTF8(3); F.ColumnLength := ColumnInt(6); F.ColumnPrecision := ColumnInt(9); F.ColumnScale := ColumnInt(8); F.ColumnTypeNative := ColumnUTF8(5); F.ColumnType:= ODBCColumnToFieldType(ColumnInt(4), ................................................................................ F.ColumnPrecision,F.ColumnScale); FA.Add(F); end; SetLength(Fields,n); finally Free; // TODBCStatement release end; // get indexes with TODBCStatement.Create(MainConnection) do try AllocStatement; ODBC.StatisticsA(fStatement,nil,0,pointer(Schema),SQL_NTS, pointer(Table),SQL_NTS,SQL_INDEX_ALL,SQL_QUICK); if status<>SQL_SUCCESS then // e.g. driver does not support schema ODBC.StatisticsA(fStatement,nil,0,nil,0,pointer(Table),SQL_NTS,SQL_INDEX_ALL,SQL_QUICK); ODBC.Check(status,SQL_HANDLE_STMT,fStatement); BindColumns; while Step do begin F.ColumnName := Trim(ColumnUTF8(8)); if F.ColumnName<>'' then for i := 0 to n-1 do with Fields[i] do if IdemPropNameU(ColumnName,F.ColumnName) then begin ColumnIndexed := true; break; end; end; finally Free; // TODBCStatement release end; except on Exception do SetLength(Fields,0); end; end; procedure TODBCConnectionProperties.GetTableNames(var Tables: TRawUTF8DynArray); var n: integer; schema, tablename: RawUTF8; begin inherited; // first try from SQL, if any (faster) if Tables<>nil then exit; // already retrieved directly from engine try with TODBCStatement.Create(MainConnection) do try AllocStatement; ODBC.Check(ODBC.TablesA(fStatement,nil,0,nil,0,nil,0,'TABLE',SQL_NTS),SQL_HANDLE_STMT,fStatement); BindColumns; n := 0; while Step do begin schema := ColumnUTF8(1); tablename := ColumnUTF8(2); if schema<>'' then tablename := schema+'.'+tablename; AddSortedRawUTF8(Tables,n,tablename); end; SetLength(Tables,n); finally Free; // TODBCStatement release end; except on Exception do SetLength(Tables,0); end; end; procedure TODBCConnectionProperties.GetForeignKeys; begin try with TODBCStatement.Create(MainConnection) do try AllocStatement; ODBC.Check(ODBC.ForeignKeysA(fStatement,nil,0,nil,0,nil,0,nil,0,nil,0,'%',SQL_NTS), SQL_HANDLE_STMT,fStatement); BindColumns; while Step do fForeignKeys.Add( ColumnUTF8(5)+'.'+ColumnUTF8(6)+'.'+ColumnUTF8(7), ColumnUTF8(1)+'.'+ColumnUTF8(2)+'.'+ColumnUTF8(3)); finally Free; // TODBCStatement release end; except on Exception do ; // just ignore errors here end; end; { SQL_TIMESTAMP_STRUCT } function SQL_TIMESTAMP_STRUCT.From(DateTime: TDateTime): SqlSmallint; var Y,MS: word; begin |