Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Comment: | added TSQLDBConnection.NewTableFromRows() method to dump a SQL statement result into a new table of any database (may be used for replication) |
---|---|
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
71278eef2063846be3bb7216d080d956 |
User & Date: | abouchez 2013-01-24 14:34:38 |
2013-01-25
| ||
18:54 | fixed ticket [231cce565d] about incorrect JSON object returned when an error is raised check-in: 3b91fe0a32 user: abouchez tags: trunk | |
2013-01-24
| ||
14:34 | added TSQLDBConnection.NewTableFromRows() method to dump a SQL statement result into a new table of any database (may be used for replication) check-in: 71278eef20 user: abouchez tags: trunk | |
12:14 |
SynDBFireBird enhancements:
| |
Changes to SQLite3/Samples/12 - SynDB Explorer/SynDBExplorerExportTables.pas.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
if SQL<>'' then
SQL := ' where '+SQL;
SQL := aProps.SQLSelectAll(Table,Fields,ExcludeTypes)+SQL;
Rows := aProps.NewThreadSafeStatement;
try
Rows.Execute(SQL,true);
Table := StringReplaceAll(StringReplaceAll(Table,' ',''),'-','');
inc(result,RowsToSQLite3(Conn,Table,Rows,true));
finally
Rows.Free;
end;
end;
except
on E: Exception do
ShowMessage(E.Message,true);
|
| |
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
if SQL<>'' then
SQL := ' where '+SQL;
SQL := aProps.SQLSelectAll(Table,Fields,ExcludeTypes)+SQL;
Rows := aProps.NewThreadSafeStatement;
try
Rows.Execute(SQL,true);
Table := StringReplaceAll(StringReplaceAll(Table,' ',''),'-','');
inc(result,Conn.NewTableFromRows(Table,Rows,true));
finally
Rows.Free;
end;
end;
except
on E: Exception do
ShowMessage(E.Message,true);
|
Changes to SynDB.pas.
154 155 156 157 158 159 160 161 162 163 164 165 166 167 .... 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 .... 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 .... 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 .... 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 |
to retrieve advanced information about database indexes (e.g. for indexes created after multiple columns) - added TSQLDBConnectionProperties.SQLTableName() method - added TSQLDBConnectionPropertiesThreadSafe.ForceOnlyOneSharedConnection property to by-pass internal thread-pool (e.g. for embedded engines) - added dFirebird kind of database in TSQLDBDefinition enumerate, and added associated SQL requests to retrieve metadata - TSQLDBConnectionProperties.SQLSelectAll() now handles spaces in table names - TSQLDBStatement.GetParamValueAsText() will truncate to a given number of chars the returned text - added missing ColumnToVarData() method to ISQLDBRows interface - now trim any spaces when retrieving database schema text values - fixed ticket [4c68975022] about broken SQL statement when logging active ................................................................................ // - this default implementation will call the NewStatement method, and // implement handle statement caching is UseCache=true - in this case, // the TSQLDBStatement.Reset method shall have been overriden to allow // binding and execution of the very same prepared statement // - this method should return nil in case of error, or a prepared statement // instance in case of success function NewStatementPrepared(const aSQL: RawUTF8; ExpectResults: Boolean): ISQLDBStatement; virtual; /// begin a Transaction for this connection // - this default implementation will check and set TransactionCount procedure StartTransaction; virtual; /// commit changes of a Transaction for this connection // - StartTransaction method must have been called before // - this default implementation will check and set TransactionCount procedure Commit; virtual; /// discard changes of a Transaction for this connection // - StartTransaction method must have been called before // - this default implementation will check and set TransactionCount procedure Rollback; virtual; /// number of nested StartTransaction calls // - equals 0 if no transaction is active property TransactionCount: integer read fTransactionCount; /// TRUE if StartTransaction has been called // - check if TransactionCount>0 property InTransaction: boolean read GetInTransaction; /// the current Date and Time, as retrieved from the server ................................................................................ finally Disconnect; end; except on E: Exception do SynDBLog.Add.Log(sllError,E); end; end; function TSQLDBConnection.GetInTransaction: boolean; begin result := TransactionCount>0; end; ................................................................................ procedure TSQLDBConnection.StartTransaction; begin CheckConnection; inc(fTransactionCount); end; { TSQLDBConnectionProperties } constructor TSQLDBConnectionProperties.Create(const aServerName, aDatabaseName, aUserID, aPassWord: RawUTF8); var aDBMS: TSQLDBDefinition; begin ................................................................................ function TSQLDBConnectionProperties.Execute(const aSQL: RawUTF8; const Params: array of const {$ifndef LVCL}{$ifndef DELPHI5OROLDER}; RowsVariant: PVariant=nil{$endif}{$endif}): ISQLDBRows; var Query: TSQLDBStatement; begin Query := NewThreadSafeStatement; Query.Execute(aSQL,true,Params); {$ifndef LVCL} {$ifndef DELPHI5OROLDER} if RowsVariant<>nil then RowsVariant^ := Query.RowData; {$endif} {$endif} result := Query; end; function TSQLDBConnectionProperties.ExecuteNoResult(const aSQL: RawUTF8; const Params: array of const): integer; begin with NewThreadSafeStatement do try |
> > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | | | | > > > > > > |
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 .... 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 .... 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 .... 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 .... 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 |
to retrieve advanced information about database indexes (e.g. for indexes created after multiple columns) - added TSQLDBConnectionProperties.SQLTableName() method - added TSQLDBConnectionPropertiesThreadSafe.ForceOnlyOneSharedConnection property to by-pass internal thread-pool (e.g. for embedded engines) - added dFirebird kind of database in TSQLDBDefinition enumerate, and added associated SQL requests to retrieve metadata - added TSQLDBConnection.NewTableFromRows() method to dump a SQL statement result into a new table of any database (may be used for replication) - TSQLDBConnectionProperties.SQLSelectAll() now handles spaces in table names - TSQLDBStatement.GetParamValueAsText() will truncate to a given number of chars the returned text - added missing ColumnToVarData() method to ISQLDBRows interface - now trim any spaces when retrieving database schema text values - fixed ticket [4c68975022] about broken SQL statement when logging active ................................................................................ // - this default implementation will call the NewStatement method, and // implement handle statement caching is UseCache=true - in this case, // the TSQLDBStatement.Reset method shall have been overriden to allow // binding and execution of the very same prepared statement // - this method should return nil in case of error, or a prepared statement // instance in case of success function NewStatementPrepared(const aSQL: RawUTF8; ExpectResults: Boolean): ISQLDBStatement; virtual; /// begin a Transaction for this connection // - this default implementation will check and set TransactionCount procedure StartTransaction; virtual; /// commit changes of a Transaction for this connection // - StartTransaction method must have been called before // - this default implementation will check and set TransactionCount procedure Commit; virtual; /// discard changes of a Transaction for this connection // - StartTransaction method must have been called before // - this default implementation will check and set TransactionCount procedure Rollback; virtual; /// direct export of a DB statement rows into a new table of this database // - the corresponding table will be created within the current connection, // if it does not exist // - INSERTs will be nested within a transaction if WithinTransaction is TRUE function NewTableFromRows(const TableName: RawUTF8; Rows: TSQLDBStatement; WithinTransaction: boolean): integer; /// number of nested StartTransaction calls // - equals 0 if no transaction is active property TransactionCount: integer read fTransactionCount; /// TRUE if StartTransaction has been called // - check if TransactionCount>0 property InTransaction: boolean read GetInTransaction; /// the current Date and Time, as retrieved from the server ................................................................................ finally Disconnect; end; except on E: Exception do SynDBLog.Add.Log(sllError,E); end; inherited; end; function TSQLDBConnection.GetInTransaction: boolean; begin result := TransactionCount>0; end; ................................................................................ procedure TSQLDBConnection.StartTransaction; begin CheckConnection; inc(fTransactionCount); end; function TSQLDBConnection.NewTableFromRows(const TableName: RawUTF8; Rows: TSQLDBStatement; WithinTransaction: boolean): integer; var Fields: TSQLDBColumnPropertyDynArray; aTableName, SQL: RawUTF8; Tables: TRawUTF8DynArray; Ins: TSQLDBStatement; begin result := 0; if (self=nil) or (Rows=nil) or (Rows.ColumnCount=0) then exit; if (PosEx('.',TableName)=0) and (PosEx(' ',TableName)=0) then aTablename := TableName else aTableName := '`'+TableName+'`'; if WithinTransaction then StartTransaction; // MUCH faster within a transaction try Ins := nil; try while Rows.Step do begin // init when first row of data is available if Ins=nil then begin SQL := Rows.ColumnsToSQLInsert(aTableName,Fields); Properties.GetTableNames(Tables); if FindRawUTF8(Tables,TableName,false)<0 then with Properties do ExecuteNoResult(SQLCreate(aTableName,Fields),[]); Ins := NewStatement; Ins.Prepare(SQL,false); end; // write row data Ins.BindFromRows(Fields,Rows); Ins.ExecutePrepared; Ins.Reset; inc(result); end; if WithinTransaction then Commit; finally Ins.Free; end; except on Exception do begin if WithinTransaction then Rollback; raise; end; end; end; { TSQLDBConnectionProperties } constructor TSQLDBConnectionProperties.Create(const aServerName, aDatabaseName, aUserID, aPassWord: RawUTF8); var aDBMS: TSQLDBDefinition; begin ................................................................................ function TSQLDBConnectionProperties.Execute(const aSQL: RawUTF8; const Params: array of const {$ifndef LVCL}{$ifndef DELPHI5OROLDER}; RowsVariant: PVariant=nil{$endif}{$endif}): ISQLDBRows; var Query: TSQLDBStatement; begin Query := NewThreadSafeStatement; try Query.Execute(aSQL,true,Params); {$ifndef LVCL} {$ifndef DELPHI5OROLDER} if RowsVariant<>nil then RowsVariant^ := Query.RowData; {$endif} {$endif} result := Query; except on Exception do begin Query.Free; raise; end; end; end; function TSQLDBConnectionProperties.ExecuteNoResult(const aSQL: RawUTF8; const Params: array of const): integer; begin with NewThreadSafeStatement do try |
Changes to SynDBSQLite3.pas.
66 67 68 69 70 71 72 73 74 75 76 77 78 79 ... 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 ... 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 |
- added TSQLDBSQLite3Connection.Synchronous property - code refactoring, especially about error handling and ODBC integration Version 1.18 - statement cache refactoring: cache logic is now at SynDB unit level - fixed ticket [4c68975022] about broken SQL statement when logging active - added TSQLDBSQLite3ConnectionProperties.SQLTableName() overriden method } {$I Synopse.inc} // define HASINLINE USETYPEINFO CPU32 CPU64 OWNNORMTOUPPER interface ................................................................................ - will use WR.Expand to guess the expected output format - fast overriden implementation with no temporary variable - BLOB field value is saved as Base64, in the '"\uFFF0base64encodedbinary" format and contains true BLOB data } procedure ColumnsToJSON(WR: TJSONWriter); override; end; /// direct export of a DB statement rows into a SQLite3 database // - the corresponding table will be created within the specified DB connection // - transaction will be created if WithinTransaction is set to TRUE function RowsToSQLite3(Connection: TSQLDBSQLite3Connection; const TableName: RawUTF8; Rows: TSQLDBStatement; WithinTransaction: boolean=true): integer; overload; /// direct export of a DB statement rows into a SQLite3 database // - the corresponding table will be created within the specified DB file function RowsToSQLite3(const Dest: TFileName; const TableName: RawUTF8; Rows: TSQLDBStatement; UseMormotCollations: boolean): integer; overload; implementation function RowsToSQLite3(Connection: TSQLDBSQLite3Connection; const TableName: RawUTF8; Rows: TSQLDBStatement; WithinTransaction: boolean): integer; var Fields: TSQLDBColumnPropertyDynArray; aTableName, SQL: RawUTF8; Ins: TSQLDBStatement; begin result := 0; if (Connection=nil) or (Rows=nil) or (Rows.ColumnCount=0) then exit; if (PosEx('.',TableName)=0) and (PosEx(' ',TableName)=0) then aTablename := TableName else aTableName := '`'+TableName+'`'; if WithinTransaction then Connection.StartTransaction; // MUCH faster within a transaction try Ins := nil; while Rows.Step do begin // init when first row of data is available if Ins=nil then begin SQL := Rows.ColumnsToSQLInsert(aTableName,Fields); // get layout Connection.DB.Execute(Connection.Properties.SQLCreate(aTableName,Fields)); // create table Ins := Connection.NewStatement; Ins.Prepare(SQL,false); // prepare INSERT end; // write row data Ins.BindFromRows(Fields,Rows); Ins.ExecutePrepared; Ins.Reset; inc(result); end; if WithinTransaction then Connection.Commit; except on Exception do begin if WithinTransaction then Connection.Rollback; raise; end; end; end; function RowsToSQLite3(const Dest: TFileName; const TableName: RawUTF8; Rows: TSQLDBStatement; UseMormotCollations: boolean): integer; overload; var DB: TSQLDBSQLite3ConnectionProperties; Conn: TSQLDBSQLite3Connection; begin result := 0; ................................................................................ exit; // we do not call DeleteFile(Dest) since DB may be completed on purpose DB := TSQLDBSQLite3ConnectionProperties.Create(StringToUTF8(Dest),'','',''); try DB.UseMormotCollations := UseMormotCollations; Conn := DB.MainConnection as TSQLDBSQLite3Connection; Conn.Connect; result := RowsToSQLite3(Conn,TableName,Rows,true); finally DB.Free; end; end; { TSQLDBSQLite3ConnectionProperties } |
> > < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | > |
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 ... 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 ... 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
- added TSQLDBSQLite3Connection.Synchronous property - code refactoring, especially about error handling and ODBC integration Version 1.18 - statement cache refactoring: cache logic is now at SynDB unit level - fixed ticket [4c68975022] about broken SQL statement when logging active - added TSQLDBSQLite3ConnectionProperties.SQLTableName() overriden method - overloaded function RowsToSQLite3() is now moved as generic TSQLDBConnection.NewTableFromRows() method } {$I Synopse.inc} // define HASINLINE USETYPEINFO CPU32 CPU64 OWNNORMTOUPPER interface ................................................................................ - will use WR.Expand to guess the expected output format - fast overriden implementation with no temporary variable - BLOB field value is saved as Base64, in the '"\uFFF0base64encodedbinary" format and contains true BLOB data } procedure ColumnsToJSON(WR: TJSONWriter); override; end; /// direct export of a DB statement rows into a SQLite3 database // - the corresponding table will be created within the specified DB file function RowsToSQLite3(const Dest: TFileName; const TableName: RawUTF8; Rows: TSQLDBStatement; UseMormotCollations: boolean): integer; implementation function RowsToSQLite3(const Dest: TFileName; const TableName: RawUTF8; Rows: TSQLDBStatement; UseMormotCollations: boolean): integer; overload; var DB: TSQLDBSQLite3ConnectionProperties; Conn: TSQLDBSQLite3Connection; begin result := 0; ................................................................................ exit; // we do not call DeleteFile(Dest) since DB may be completed on purpose DB := TSQLDBSQLite3ConnectionProperties.Create(StringToUTF8(Dest),'','',''); try DB.UseMormotCollations := UseMormotCollations; Conn := DB.MainConnection as TSQLDBSQLite3Connection; Conn.Connect; result := Conn.NewTableFromRows(TableName,Rows,true); Conn.Disconnect; finally DB.Free; end; end; { TSQLDBSQLite3ConnectionProperties } |