Суть: используя стандартный CopyTable.ibeblock
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195. 196. 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. 215. 216. 217. 218. 219. 220. 221. 222. 223. 224. 225. 226. 227. 228. 229. 230. 231. 232. 233. 234. 235. 236. 237. 238. 239. 240. 241. 242. 243. 244. 245. 246. 247. 248. 249. 250. 251. 252. 253. 254. 255. 256. 257. 258. 259. 260. 261. 262. 263. 264. 265. 266. 267. 268. 269. 270. 271. 272. 273. 274. 275. 276. 277. 278. 279. 280. 281. 282. 283. 284. 285. 286. 287. 288. 289. 290. 291. 292. 293. 294. 295. 296. 297. 298. 299. 300. 301. 302. 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. 371. 372. 373. 374. 375. 376. 377. 378. 379. 380. 381. 382. 383. 384. 385. 386. 387. 388. 389. 390. 391. 392. 393. 394. 395. 396. 397. 398. 399. 400. 401. 402. 403. 404. 405. 406. 407. 408. 409. 410. 411. 412. 413. 414. 415. 416. 417. 418. 419. 420. 421. 422. 423. 424. 425. 426. 427. 428. 429. 430. 431. 432. 433. 434. 435. 436. 437. 438. 439. 440. 441. 442. 443. 444. 445. 446. 447. 448. 449. 450. 451. 452. 453. 454. 455. 456. 457. 458. 459. 460. 461. 462. 463. 464. 465. 466. 467. 468. 469. 470. 471. 472. 473. 474. 475. 476. 477. 478. 479. 480. 481. 482. 483. 484. 485. 486. 487. 488. 489. 490. 491. 492. 493. 494. 495. 496. 497. 498. 499. 500. 501. 502. 503. 504. 505. 506. 507. 508. 509. 510. 511. 512. 513. 514. 515. 516. 517. 518. 519. 520. 521. 522. 523. 524. 525. 526. 527. 528. 529. 530. 531. 532. 533. 534. 535. 536. 537. 538. 539. 540. 541. 542. 543. 544. 545. 546. 547. 548. 549. 550. 551. 552. 553. 554. 555. 556. 557. 558. 559. 560. 561. 562. 563. 564. 565. 566. 567. 568. 569. 570. 571. 572. 573. 574. 575. 576. 577. 578. 579. 580. 581. 582. 583. 584. 585. 586. 587. 588. 589. 590. 591. 592. 593. 594. 595. 596. 597. 598. 599. 600. 601. 602. 603. 604. 605. 606. 607. 608. 609. 610. 611. 612. 613. 614. 615. 616. 617. 618. 619. 620. 621. 622. 623. 624. 625. 626. 627. 628. 629. 630. 631. 632. 633. 634. 635. 636. 637. 638. 639. 640. 641. 642. 643. 644. 645. 646. 647. 648. 649. 650. 651. 652. 653. 654. 655. 656. 657. 658. 659. 660. 661. 662. 663. 664. 665. 666. 667. 668. 669. 670. 671. 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. 698. 699. 700. 701. 702. 703. 704. 705. 706. 707. 708. 709. 710. 711. 712. 713. 714. 715. 716. 717. 718. 719. 720. 721. 722. 723. 724. 725. 726. 727. 728. 729. 730. 731. 732. 733. 734. 735. 736. 737. 738. 739. 740. 741. 742. 743. 744. 745. 746. 747. 748. 749. 750. 751. 752. 753. 754. 755. 756. 757. 758. 759. 760. 761. 762. 763. 764. 765. 766. 767. 768. 769. 770. 771. 772. 773.
execute ibeblock (
-- Don't change names of following parameters! -------------------------------------------------
SrcDBConnStr variant comment 'Source DB connection string',
SrcDBUserName variant = 'SYSDBA' comment 'Source DB user name',
SrcDBPassword variant = 'masterkey' comment 'Source DB password',
SrcDBCharset variant = 'NONE' comment 'Source DB connection charset',
SrcDBClientLib variant = 'gds32.dll' comment 'Source DB client library name',
DestDBConnStr variant comment 'Destination DB connection string',
DestDBUserName variant = 'SYSDBA' comment 'Destination DB user name',
DestDBPassword variant = 'masterkey' comment 'Destination DB password',
DestDBCharset variant = 'NONE' comment 'Destination DB connection charset',
DestDBClientLib variant = 'gds32.dll' comment 'Destination DB client library name',
SrcObjectName variant = '' comment 'Table name to be copied',
DestObjectName variant = '' comment 'Destination table name, leave empty if no changes need',
DebugMode boolean = FALSE,
------------------------------------------------------------------------------------------------
CopyDomains boolean = TRUE comment 'Copy domains',
CopyTriggers boolean = TRUE comment 'Copy table triggers',
CopyPrimaryKey boolean = TRUE comment 'Copy primary key',
CopyForeignKeys boolean = TRUE comment 'Copy foreign keys if possible',
CopyData boolean = TRUE comment 'Copy table data',
CopyIndices boolean = TRUE comment 'Copy table indices',
CopyGenerators enum ('Copy generators and set their values', -- 0
'Only set generator values if exist', -- 1
'Don''t process generators' -- 2
) = 0 comment 'Generators',
IfTableExists enum ('Drop existing table', -- 0
'Empty table', -- 1
'Raise an error' -- 2
) = 2 comment 'If table exists in the target database')
as
begin
Time1 = ibec_GetTickCount();
CRLF = ibec_CRLF();
BS = ibec_Chr(8);
Success = BS + ' Successful.';
Failed = BS + ' FAILED!';
IsExternal = FALSE;
if (DebugMode) then
begin
SrcDBConnStr = 'LOCALHOST/3070:D:\DATA\FB25_DATA\TESTUTF8.FBA';
SrcDBCharset = 'UTF8';
SrcDBClientLib = 'C:\Program Files (x86)\Firebird25\bin\fbclient.dll';
DestDBConnStr = 'LOCALHOST/3070:D:\DATA\FB25_DATA\TESTUTF8.FBA';
DestDBCharset = 'UTF8';
DestDBClientLib = 'C:\Program Files (x86)\Firebird25\bin\fbclient.dll';
SrcObjectName = 'TEST';
DestObjectName = 'TEST12';
DropTableIfExists = TRUE;
end;
SrcTableName = SrcObjectName;
DestTableName = DestObjectName;
SrcDBParams = 'DBName=' + SrcDBConnStr + ';' +
'User=' + SrcDBUserName + ';' +
'Password=' + SrcDBPassword + ';' +
'Names=' + SrcDBCharset + ';' +
'ClientLib=' + SrcDBClientLib;
DestDBParams = 'DBName=' + DestDBConnStr + ';' +
'User=' + DestDBUserName + ';' +
'Password=' + DestDBPassword + ';' +
'Names=' + DestDBCharset + ';' +
'ClientLib=' + DestDBClientLib;
try
try
ibec_Progress('Connecting to ' + SrcDBConnStr + '...');
SrcDB = ibec_CreateConnection(__ctFirebird, SrcDBParams);
ibec_Progress(Success);
SrcDBSQLDialect = ibec_GetConnectionProp(SrcDB, 'DBSQLDialect');
except
ibec_Progress(Failed);
raise;
Exit;
end;
try
ibec_Progress('Connecting to ' + DestDBConnStr + '...');
DestDB = ibec_CreateConnection(__ctFirebird, DestDBParams);
ibec_Progress(Success);
DestDBSQLDialect = ibec_GetConnectionProp(DestDB, 'DBSQLDialect');
except
ibec_Progress(Failed);
raise;
Exit;
end;
ibec_UseConnection(SrcDB);
select rdb$relation_name, rdb$system_flag, rdb$external_file, rdb$description
from rdb$relations
where (rdb$relation_name = :SrcTableName) and (rdb$view_blr is null)
into :SrcTableData;
if (SrcTableData['RDB$RELATION_NAME'] is null) then
exception cant_find_table 'There is no such table (' + :SrcTableName + ') in the source database.';
IsSys = SrcTableData['RDB$SYSTEM_FLAG'] = 1;
if (IsSys) then
exception cant_copy_system_table 'Cannot copy a system table.';
IsExternal = (SrcTableData['RDB$EXTERNAL_FILE'] is not null) and (SrcTableData['RDB$EXTERNAL_FILE'] <> '');
if ((DestTableName is null) or (DestTableName = '')) then
DestTableName = SrcTableName;
DestTableNameFmt = ibec_IIF(DestDBSQLDialect = 3, ibec_QuotedStr(:DestTableName, '"'), ibec_AnsiUpperCase(:DestTableName));
SrcTableNameFmt = ibec_IIF(SrcDBSQLDialect = 3, ibec_QuotedStr(:SrcTableName, '"'), ibec_AnsiUpperCase(:SrcTableName));
ibec_UseConnection(DestDB);
TableExists = FALSE;
if (exists(select rdb$relation_name from rdb$relations where rdb$relation_name = :DestTableName)) then
begin
TableExists = TRUE;
if (IfTableExists = 0) then
begin
DropStmt = 'DROP TABLE ' + DestTableNameFmt;
try
ibec_Progress('Dropping table ' + DestTableNameFmt + '...');
execute statement :DropStmt;
commit;
TableExists = FALSE;
ibec_Progress(Success);
except
ibec_Progress(Failed);
rollback;
raise;
end;
end
else if (IfTableExists = 1) then
begin
DeleteStmt = 'DELETE FROM ' + DestTableNameFmt;
try
ibec_Progress('Emptying table ' + DestTableNameFmt + '...');
execute statement :DeleteStmt;
commit;
ibec_Progress(Success);
except
ibec_Progress(Failed);
rollback;
raise;
end;
end
else
exception table_exists_already 'Table "' + DestTableName + '" exists in the destination database already.';
end
ibec_UseConnection(SrcDB);
select rdb$field_name
from rdb$relation_fields
where (rdb$relation_name = 'RDB$FIELDS') and
(rdb$field_name = 'RDB$FIELD_PRECISION')
into :bPrecision;
bPrecision = ibec_IIF(:bPrecision is NULL, FALSE, TRUE);
SelStmt = 'select rf.rdb$field_name as fld_name,' +
'rf.rdb$field_source as fld_domain,' +
'rf.rdb$null_flag as fld_null_flag,' +
'rf.rdb$default_source as fld_default,' +
'rf.rdb$description as fld_description,' +
'f.rdb$field_type as dom_type,' +
'f.rdb$field_length as dom_length,' +
'f.rdb$field_sub_type as dom_subtype,' +
'f.rdb$field_scale as dom_scale,' +
'f.rdb$null_flag as dom_null_flag,' +
'f.rdb$character_length as dom_charlen,' +
'f.rdb$segment_length as dom_seglen,' +
'f.rdb$system_flag as dom_system_flag,' +
'f.rdb$computed_source as dom_computedby,' +
'f.rdb$default_source as dom_default,' +
'f.rdb$dimensions as dom_dims,' +
'f.rdb$description as dom_description,' +
'ch.rdb$character_set_name as dom_charset,' +
'ch.rdb$bytes_per_character as charset_bytes,' +
'dco.rdb$collation_name as dom_collation,' +
'fco.rdb$collation_name as fld_collation';
if (bPrecision) then
SelStmt = SelStmt + ', f.rdb$field_precision as dom_precision';
SelStmt = SelStmt + CRLF +
'from rdb$relation_fields rf ' + CRLF +
'left join rdb$fields f on rf.rdb$field_source = f.rdb$field_name' + CRLF +
'left join rdb$character_sets ch on f.rdb$character_set_id = ch.rdb$character_set_id' + CRLF +
'left join rdb$collations dco on ((f.rdb$collation_id = dco.rdb$collation_id) and (f.rdb$character_set_id = dco.rdb$character_set_id))' + CRLF +
'left join rdb$collations fco on ((rf.rdb$collation_id = fco.rdb$collation_id) and (f.rdb$character_set_id = fco.rdb$character_set_id))' + CRLF +
'where rf.rdb$relation_name = ' + ibec_QuotedStr(:SrcTableName, '''') + CRLF +
'order by rf.rdb$field_position';
ibec_Progress('Collecting fields info...');
i = 0;
iUserDomainCount = 0;
for execute statement SelStmt into :FldData
do
begin
s = ibec_Trim(FldData['FLD_DOMAIN']);
aDomains[i] = ibec_IIF(ibec_Copy(s, 1, 4) = 'RDB$', null, s);
if (aDomains[i] is not null) then
iUserDomainCount = iUserDomainCount + 1;
aFields[i] = ibec_Trim(FldData['FLD_NAME']);
sType = ibec_IBTypeToStr(FldData['DOM_TYPE'],
FldData['DOM_SUBTYPE'],
FldData['DOM_LENGTH'],
FldData['DOM_SCALE'],
FldData['DOM_SEGLEN'],
FldData['DOM_CHARLEN'],
FldData['DOM_PRECISION'],
DestDBSQLDialect);
aTypes[i] = sType;
aFieldsNotNull[i] = ibec_IIF(FldData['FLD_NULL_FLAG'] = 1, ' NOT NULL', '');
aFieldsDefault[i] = ibec_IIF(FldData['FLD_DEFAULT'] is null, '', ' ' + ibec_Trim(FldData['FLD_DEFAULT']));
aFieldsComment[i] = FldData['FLD_DESCRIPTION'];
aFieldsCharset[i] = ibec_IIF(FldData['DOM_CHARSET'] is null, '', ibec_Trim(FldData['DOM_CHARSET']));
aFieldsCollate[i] = ibec_IIF(FldData['FLD_COLLATION'] is null, '', ibec_Trim(FldData['FLD_COLLATION']));
aDomainsComputedBy[i] = FldData['DOM_COMPUTEDBY'];
i = i + 1;
end
ibec_UseConnection(DestDB);
DomainsAreOK = TRUE;
if (CopyDomains and (iUserDomainCount > 0)) then
begin
ibec_Progress('Creating domains...');
foreach (aDomains as Dom key DomIdx skip nulls) do
begin
if (exists(select rdb$field_name from rdb$fields where rdb$field_name = :Dom)) then
Continue;
sType = aTypes[DomIdx];
CreateStmt = 'CREATE DOMAIN ' +
ibec_IIF(DestDBSQLDialect = 3, ibec_QuotedStr(:Dom, '"'), ibec_AnsiUpperCase(:Dom)) +
' AS ' + sType;
try
execute statement :CreateStmt;
commit;
except
DomainsAreOK = FALSE;
rollback;
end;
end;
end
FieldsList = '';
if (not TableExists) then
begin
CreateStmt = 'CREATE TABLE ' + DestTableNameFmt;
if (IsExternal) then
CreateStmt .= CRLF + 'EXTERNAL FILE ' + ibec_QuotedStr(SrcTableData['RDB$EXTERNAL_FILE'], '''');
foreach (aFields as FldName index FldKey skip nulls) do
begin
sType = '';
if (FieldsList <> '') then
FieldsList .= ',' + CRLF;
FldNameFmt = ibec_IIF(DestDBSQLDialect = 3, ibec_QuotedStr(:FldName, '"'), ibec_AnsiUpperCase(:FldName));
if ((aDomains[FldKey] is null) and (aDomainsComputedBy[FldKey] is not null)) then -- Field is computed
FieldsList .= FldNameFmt + ' ' + ' COMPUTED BY ' + aDomainsComputedBy[FldKey];
else
begin
if (DomainsAreOK and (aDomains[FldKey] is not null)) then
FieldsList .= FldNameFmt + ' ' + aDomains[FldKey];
else
FieldsList .= FldNameFmt + ' ' + aTypes[FldKey];
if ((aDomains[FldKey] is null) and (aFieldsCharset[FldKey] <> '')) then
FieldsList .= ' CHARACTER SET ' + aFieldsCharset[FldKey];
FieldsList .= aFieldsDefault[FldKey] + aFieldsNotNull[FldKey];
if (aFieldsCollate[FldKey] <> '') then
FieldsList .= ' COLLATE ' + aFieldsCollate[FldKey];
end;
end
CreateStmt .= ' (' + CRLF + FieldsList + ')';
ibec_UseConnection(DestDB);
try
ibec_Progress('Creating table ' + DestTableNameFmt + '...');
execute statement :CreateStmt;
commit;
ibec_Progress(Success);
TblName = ibec_IIF(DestDBSQLDialect = 3, :DestTableName, ibec_AnsiUpperCase(:DestTableName));
foreach (aFieldsComment as FldComment key FldKey skip nulls) do
begin
FldName = aFields[FldKey];
update rdb$relation_fields set rdb$description = :FldComment
where (rdb$relation_name = :TblName) and (rdb$field_name = :FldName);
end;
commit;
except
ibec_Progress(Failed);
rollback;
end;
end;
-------------------------------------------------------------
-- TRANSFER TABLE DATA --------------------------------------
-------------------------------------------------------------
if (CopyData and (not IsExternal)) then
begin
sFields = '';
sValues = '';
foreach (aFields as FldName key FldKey) do
begin
if (aDomainsComputedBy[FldKey] is null) then
begin
if (sFields <> '') then
begin
sFields .= ', ';
sValues .= ', ';
end;
FldNameFmt = ibec_IIF(DestDBSQLDialect = 3, ibec_QuotedStr(:FldName, '"'), ibec_AnsiUpperCase(:FldName));
sFields .= FldNameFmt;
sValues .= ':' + FldNameFmt;
end;
end;
SelectStmt = 'SELECT ' + sFields + ' FROM ' + SrcTableNameFmt;
InsertStmt = 'INSERT INTO ' + DestTableNameFmt + ' (' + sFields + ') VALUES (' + sValues + ')';
ibec_UseConnection(SrcDB);
i = 0;
ibec_Progress('Copying table data...');
for execute statement :SelectStmt into :Data
do
begin
ibec_UseConnection(DestDB);
execute statement :InsertStmt values :Data;
i = i + 1;
if (ibec_mod(i, 500) = 0) then
begin
commit;
ibec_Progress(' ' + ibec_cast(i, __typeString) + ' records copied...');
end;
end;
ibec_Progress(' Totally ' + ibec_cast(i, __typeString) + ' records copied.');
ibec_UseConnection(DestDB);
commit;
end;
if (CopyTriggers or CopyPrimaryKey or (CopyGenerators in (0,1))) then
begin
ibec_UseConnection(SrcDB);
TblName = ibec_IIF(SrcDBSQLDialect = 3, :SrcTableName, ibec_AnsiUpperCase(:SrcTableName));
i = 0;
ibec_Progress('Collecting triggers info...');
for select T.RDB$TRIGGER_NAME, T.RDB$TRIGGER_TYPE, T.RDB$TRIGGER_SEQUENCE,
T.RDB$TRIGGER_INACTIVE, T.RDB$TRIGGER_SOURCE
from RDB$TRIGGERS T
left join RDB$CHECK_CONSTRAINTS C on C.RDB$TRIGGER_NAME = T.RDB$TRIGGER_NAME
where ((T.RDB$SYSTEM_FLAG = 0) or (T.RDB$SYSTEM_FLAG is null)) and
(C.rdb$trigger_name is null) and (T.RDB$RELATION_NAME = :TblName)
order by T.RDB$TRIGGER_NAME
into :TrgData
do
begin
aTriggerNames[i] = ibec_Trim(TrgData['RDB$TRIGGER_NAME']);
aTriggerTypes[i] = ibec_IBTriggerTypeToStr(TrgData['RDB$TRIGGER_TYPE']);
aTriggerPositions[i] = TrgData['RDB$TRIGGER_SEQUENCE'];
aTriggerInactives[i] = ibec_IIF(TrgData['RDB$TRIGGER_INACTIVE'] = 1, 'INACTIVE', 'ACTIVE');
aTriggerSources[i] = TrgData['RDB$TRIGGER_SOURCE'];
i = i + 1;
end;
-----------------------------------------------------
-- COLLECTING GENERATOR NAMES USED WITHIN TRIGGERS
-----------------------------------------------------
i = 0;
ibec_Progress('Analyzing trigger bodies for used generators...');
foreach (aTriggerNames as TrgName key TrgKey skip nulls) do
begin
TrgSrc = aTriggerSources[TrgKey];
TrgNameFmt = ibec_IIF(SrcDBSQLDialect = 3, ibec_QuotedStr(:TrgName, '"'), ibec_AnsiUpperCase(:TrgName));
TrgDDL = 'CREATE TRIGGER ' + TrgNameFmt + ' FOR ' + SrcTableNameFmt + CRLF +
aTriggerTypes[TrgKey] + ' POSITION ' + ibec_Cast(aTriggerPositions[TrgKey], __typeString) + CRLF + TrgSrc;
PSQLParser = ibec_psql_Parse(TrgDDL, SrcDBSqlDialect, __svUnknown);
try
if (ibec_psql_ErrorCount(PSQLParser) = 0) then
begin
iCount = ibec_psql_UsedObjects(PSQLParser, ObjNames, ObjTypes);
if (iCount > 0) then
begin
foreach (ObjNames as ObjName key ObjKey skip nulls) do
if (ObjTypes[ObjKey] = __dboGenerator) then
if (ibec_IndexOfValue(Generators, ObjName) is null) then
begin
Generators[i] = ObjName;
i = i + 1;
end;
end;
end;
finally
ibec_psql_Free(PSQLParser);
end;
end;
-------------------------------------------------------
-- CREATING GENERATORS AND/OR SETTING THEIR VALUES
-------------------------------------------------------
if (CopyGenerators in (0,1)) then
begin
ibec_Progress('Creating or/and initting generators...');
foreach (Generators as GenName key GenKey skip nulls) do
begin
ibec_UseConnection(DestDB);
GeneratorExists = FALSE;
if (exists(select rdb$generator_name from rdb$generators where rdb$generator_name = :GenName)) then
GeneratorExists = TRUE;
-- If generator exists in the target database and "Copy generators..." option is selected
if (GeneratorExists and (CopyGenerators = 0)) then
Continue;
-- If generator doesn't exists in the target database and "Set generator values" option is selected
if ((not GeneratorExists) and (CopyGenerators = 1)) then
Continue;
ibec_UseConnection(SrcDB);
GenNameFmt = ibec_IIF(SrcDBSQLDialect = 3, ibec_QuotedStr(:GenName, '"'), ibec_AnsiUpperCase(:GenName));
GetGenValueStmt = 'SELECT GEN_ID(' + GenNameFmt + ', 0) FROM RDB$DATABASE';
execute statement GetGenValueStmt into :GenValue;
GenNameFmt = ibec_IIF(DestDBSQLDialect = 3, ibec_QuotedStr(:GenName, '"'), ibec_AnsiUpperCase(:GenName));
CreateGenStmt = 'CREATE GENERATOR ' + GenNameFmt;
SetGenStmt = 'SET GENERATOR ' + GenNameFmt + ' TO ' + ibec_Cast(:GenValue, __typeString);
ibec_UseConnection(DestDB);
try
ibec_Progress(' ' + GenNameFmt + '...');
if (CopyGenerators = 0) then
begin
execute statement CreateGenStmt;
commit;
end;
execute statement SetGenStmt;
commit;
ibec_Progress(Success);
except
ibec_Progress(Failed);
rollback;
end;
end;
end;
end;
if (CopyTriggers) then
begin
ibec_UseConnection(DestDb);
ibec_Progress('Creating triggers...');
foreach (aTriggerNames as TrgName key TrgKey skip nulls) do
begin
if (SrcTableName <> DestTableName) then
TrgName = ibec_preg_Replace('(?i)' + SrcTableName, DestTableName, TrgName);
TrgNameFmt = ibec_IIF(DestDBSQLDialect = 3, ibec_QuotedStr(:TrgName, '"'), ibec_AnsiUpperCase(:TrgName));
CreateTrgStmt = 'CREATE TRIGGER ' + TrgNameFmt + ' FOR ' + DestTableNameFmt + CRLF +
aTriggerInactives[TrgKey] + ' ' + aTriggerTypes[TrgKey] + ' POSITION ' + ibec_Cast(aTriggerPositions[TrgKey], __typeString) + CRLF +
aTriggerSources[TrgKey];
WasError = FALSE;
try
ibec_Progress(' ' + TrgNameFmt + '...');
execute statement :CreateTrgStmt;
commit;
ibec_Progress(:Success);
except
ibec_Progress(:Failed);
WasError = TRUE;
rollback;
end;
if (WasError) then
begin
ibec_Progress(' Attempt to create trigger ' + TrgNameFmt + ' with commented body...');
PSQLParser = ibec_psql_Parse(CreateTrgStmt, DestDBSqlDialect, __svUnknown);
try
CreateTrgStmt = ibec_psql_CommentBody(PSQLParser);
finally
ibec_psql_Free(PSQLParser);
end;
try
execute statement :CreateTrgStmt;
ibec_Progress(:Success);
commit;
except
ibec_Progress(:Failed);
rollback;
end;
end;
end;
end;
-------------------------------------------------------
-- PROCESSING PRIMARY KEY
-------------------------------------------------------
if (CopyPrimaryKey) then
begin
ibec_UseConnection(SrcDB);
select rc.rdb$constraint_name, rc.rdb$index_name
from rdb$relation_constraints rc
where (rc.rdb$constraint_type = 'PRIMARY KEY') and (rc.rdb$relation_name = :SrcTableName)
into :PKData;
if (PKData is not null) then
begin
PKIdxName = ibec_Trim(PKData[1]);
sFields = '';
for select rdb$field_name
from rdb$index_segments
where rdb$index_name = :PKIdxName
order by rdb$field_position
into :PKFields
do
begin
if (sFields <> '') then
sFields .= ', ';
FldName = ibec_Trim(PKFields[0]);
FldNameFmt = ibec_IIF(DestDBSQLDialect = 3, ibec_QuotedStr(FldName, '"'), ibec_AnsiUpperCase(FldName));
sFields .= FldNameFmt;
end;
PKName = ibec_Trim(PKData[0]);
ibec_UseConnection(DestDB);
PKNameBase = 'PK_' + DestTableName + '_';
PKNameSuff = 0;
PKExists = 1;
while (PKExists is not null) do
begin
PKNameSuff = PKNameSuff + 1;
PKName = PKNameBase + ibec_Cast(PKNameSuff, __typeString);
PKExists = null;
select 1 from rdb$relation_constraints rc
where (rc.rdb$constraint_type = 'PRIMARY KEY') and (rc.rdb$constraint_name = :PKName)
into :PKExists;
end;
PKNameFmt = ibec_IIF(DestDBSQLDialect = 3, ibec_QuotedStr(PKName, '"'), ibec_AnsiUpperCase(PKName));
AlterStmt = 'ALTER TABLE ' + DestTableNameFmt + ' ADD CONSTRAINT ' + PKNameFmt + ' PRIMARY KEY (' + sFields + ')';
ibec_UseConnection(DestDB);
try
ibec_Progress('Creating primary key ' + PKNameFmt + '...');
execute statement :AlterStmt;
commit;
ibec_Progress(:Success);
except
ibec_Progress(:Failed);
rollback;
end;
end;
end;
-------------------------------------------------------
-- PROCESSING FOREIGN KEYS
-------------------------------------------------------
if (CopyForeignKeys) then
begin
NeedProgressMessage = TRUE;
ibec_UseConnection(SrcDB);
for select rc1.rdb$constraint_name as fk_constraint_name,
rc1.rdb$index_name as fk_index_name,
refc.rdb$update_rule as fk_update_rule,
refc.rdb$delete_rule as fk_delete_rule,
rc2.rdb$constraint_name as ref_constraint_name,
rc2.rdb$relation_name as ref_table_name,
rc2.rdb$index_name as ref_index_name,
i.rdb$index_type as fk_index_type
from rdb$relation_constraints rc1
left join rdb$ref_constraints refc on rc1.rdb$constraint_name = refc.rdb$constraint_name
left join rdb$relation_constraints rc2 on rc2.rdb$constraint_name = refc.rdb$const_name_uq
left join rdb$indices i on rc1.rdb$index_name = i.rdb$index_name
where (rc1.rdb$constraint_type = 'FOREIGN KEY') and (rc1.rdb$relation_name = :TblName)
into :FKData
do
begin
if (NeedProgressMessage) then
begin
ibec_Progress('Creating foreign keys...');
NeedProgressMessage = FALSE;
end;
RefTableName = ibec_Trim(FKData['REF_TABLE_NAME']);
ibec_UseConnection(DestDB);
if (not exists(select rdb$relation_name from rdb$relations where rdb$relation_name = :RefTableName)) then
begin
ibec_Progress(' Cannot create foreign key: referenced table ' || ibec_FormatIdent(RefTableName) || ' doesn''t exist in the target database.');
Continue;
end;
RefTableNameFmt = ibec_IIF(DestDBSQLDialect = 3, ibec_QuotedStr(RefTableName, '"'), ibec_AnsiUpperCase(RefTableName));
ibec_UseConnection(SrcDB);
FKIdxName = ibec_Trim(FKData['FK_INDEX_NAME']);
FKFieldsList = '';
for select rdb$field_name
from rdb$index_segments
where rdb$index_name = :FKIdxName
order by rdb$field_position
into :FKFields
do
begin
if (FKFieldsList <> '') then
FKFieldsList .= ', ';
FldName = ibec_Trim(FKFields[0]);
FldNameFmt = ibec_IIF(DestDBSQLDialect = 3, ibec_QuotedStr(FldName, '"'), ibec_AnsiUpperCase(FldName));
FKFieldsList .= FldNameFmt;
end;
FKName = ibec_Trim(FKData[0]);
RefIdxName = ibec_Trim(FKData['REF_INDEX_NAME']);
RefFieldsList = '';
for select rdb$field_name
from rdb$index_segments
where rdb$index_name = :RefIdxName
order by rdb$field_position
into :RefFields
do
begin
if (RefFieldsList <> '') then
RefFieldsList .= ', ';
FldName = ibec_Trim(RefFields[0]);
FldNameFmt = ibec_IIF(DestDBSQLDialect = 3, ibec_QuotedStr(FldName, '"'), ibec_AnsiUpperCase(FldName));
RefFieldsList .= FldNameFmt;
end;
ConstraintName = ibec_Trim(FKData['FK_CONSTRAINT_NAME']);
CreateFKStmt = 'ALTER TABLE ' + DestTableNameFmt + ' ADD';
if (not ibec_preg_Match('^INTEG\_[0-9]+', ConstraintName)) then
CreateFKStmt .= ' CONSTRAINT ' + ibec_IIF(DestDBSQLDialect = 3, ibec_QuotedStr(ConstraintName, '"'), ibec_AnsiUpperCase(ConstraintName));
CreateFKStmt .= ' FOREIGN KEY (' + FKFieldsList + ') REFERENCES ' + RefTableNameFmt + ' (' + RefFieldsList + ')';
if (ibec_Trim(FKData['FK_UPDATE_RULE']) <> 'RESTRICT') then
CreateFKStmt .= ' ON UPDATE ' + ibec_Trim(FKData['FK_UPDATE_RULE']);
if (ibec_Trim(FKData['FK_DELETE_RULE']) <> 'RESTRICT') then
CreateFKStmt .= ' ON DELETE ' + ibec_Trim(FKData['FK_DELETE_RULE']);
if (ibec_Copy(FKIdxName, 1, 4) <> 'RDB$') then
begin
CreateFKStmt .= ' USING';
if (FKData['FK_INDEX_TYPE'] = 1) then
CreateFKStmt .= ' DESCENDING';
CreateFKStmt .= ' INDEX ' + ibec_IIF(DestDBSQLDialect = 3, ibec_QuotedStr(FKIdxName, '"'), ibec_AnsiUpperCase(FKIdxName));
end;
ibec_UseConnection(DestDB);
try
ibec_Progress(' Reference (foreign key) to ' + ibec_FormatIdent(RefTableName) + '...');
execute statement :CreateFKStmt;
commit;
ibec_Progress(Success);
except
ibec_Progress(Failed);
rollback;
end;
ibec_UseConnection(SrcDB);
end;
end;
if (CopyIndices) then
begin
ibec_Progress('Creating indices...');
ibec_UseConnection(SrcDB);
for select i.rdb$index_name, i.rdb$unique_flag, i.rdb$index_inactive, i.rdb$index_type,
i.rdb$expression_source, i.rdb$description
from rdb$indices i
left join rdb$relation_constraints rc on i.rdb$index_name = rc.rdb$index_name
where ((i.rdb$system_flag = 0) or (i.rdb$system_flag is null)) and (rc.rdb$constraint_name is null)
and i.rdb$relation_name = :SrcTableName
into :IdxData
do
begin
IdxName = ibec_Trim(IdxData[0]);
IdxNameFmt = ibec_IIF(DestDBSQLDialect = 3, ibec_QuotedStr(IdxName, '"'), ibec_AnsiUpperCase(IdxName));
IdxUnique = ibec_IIF((IdxData[1] is null) or (IdxData[1] = 0), '', 'UNIQUE ');
IdxActive = ibec_IIF((IdxData[2] is null) or (IdxData[1] = 0), '', 'INACTIVE ');
IdxType = ibec_IIF((IdxData[3] is null) or (IdxData[1] = 0), '', 'DESCENDING ');
IdxExpression = IdxData[4];
IdxDescription = IdxData[5];
sFields = '';
for select rdb$field_name
from rdb$index_segments
where rdb$index_name = :IdxName
order by rdb$field_position
into :IdxFields
do
begin
if (sFields <> '') then
sFields .= ', ';
FldName = ibec_Trim(IdxFields[0]);
FldNameFmt = ibec_IIF(DestDBSQLDialect = 3, ibec_QuotedStr(FldName, '"'), ibec_AnsiUpperCase(FldName));
sFields .= FldNameFmt;
end;
ibec_UseConnection(DestDB);
IDXExists = null;
select 1 from rdb$indices where rdb$index_name = :IdxName into :IDXExists;
if (IDXExists is not null) then
begin
IDXNameBase = 'IDX_' + DestTableName + '_';
IDXNameSuff = 0;
IDXExists = 1;
while (IDXExists is not null) do
begin
IDXNameSuff = IDXNameSuff + 1;
IdxName = IDXNameBase + ibec_Cast(IDXNameSuff, __typeString);
IDXExists = null;
select 1 from rdb$indices where rdb$index_name = :IdxName into :IDXExists;
end;
IdxNameFmt = ibec_IIF(DestDBSQLDialect = 3, ibec_QuotedStr(IdxName, '"'), ibec_AnsiUpperCase(IdxName));
end;
CreateIndexStmt = 'CREATE ' + IdxUnique + IdxType + 'INDEX ' + IdxNameFmt + ' ON ' +
DestTableNameFmt;
if (IdxExpression is not null) then
CreateIndexStmt .= ' COMPUTED BY (' + IdxExpression + ')';
else
CreateIndexStmt .= ' (' + sFields + ')';
ibec_UseConnection(DestDB);
try
ibec_Progress(' ' + IdxNameFmt + '...');
execute statement :CreateIndexStmt;
commit;
if (IdxActive <> '') then
begin
ibec_Progress(BS + ' Making inactive...');
execute statement 'ALTER INDEX ' || IdxNameFmt || ' INACTIVE';
commit;
end;
ibec_Progress(:Success);
except
ibec_Progress(:Failed);
rollback;
end;
ibec_UseConnection(SrcDB);
end;
end;
finally
if (SrcDB is not null) then
begin
ibec_Progress('Closing connection to ' + SrcDBConnStr + '...');
ibec_CloseConnection(SrcDB);
end;
if (DestDB is not null) then
begin
ibec_Progress('Closing connection to ' + DestDBConnStr + '...');
ibec_CloseConnection(DestDB);
end;
Time2 = ibec_GetTickCount();
sTime = ibec_div((Time2 - Time1), 1000) || '.' ||ibec_mod((Time2 - Time1), 1000);
ibec_Progress('Finished.');
ibec_Progress('Total time spent: ' || sTime || ' seconds');
ibec_Progress('That''s all, folks!');
end;
end
вызываю его в цикле
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13.
execute ibeblock
as
begin
CopyTable = ibec_LoadFromFile('D:\Program Files (x86)\IBExpert\Blocks\DefaultBlocks\CopyTable.ibeblock');
ATABLES = ibec_Array('ACCOUNT_TYPE');
ScrDB = 'LOCALHOST:E:\DB\DB.gdb';
DestDB = 'LOCALHOST:E:\DB\DB_NEW.gdb';
TT = 'ACCOUNT_TYPE';
for id = 0 to ibec_High(ATABLES ) do
begin
execute ibeblock CopyTable (ScrDB, 'SYSDBA', 'masterkey', 'WIN1251', 'gds32.dll', DestDB, 'SYSDBA', 'masterkey', 'WIN1251', 'gds32.dll', ATABLES[id], ATABLES[id], FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0, 2);
end;
end
Скрипт выполняется без ошибок, но в новой БД ничего не создается.
Если же вызывать CopyTable с "ручным" указанием таблицы, то нормально копируется.
1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
execute ibeblock
as
begin
CopyTable = ibec_LoadFromFile('D:\Program Files (x86)\IBExpert\Blocks\DefaultBlocks\CopyTable.ibeblock');
ATABLES = ibec_Array('ACCOUNT_TYPE');
ScrDB = 'LOCALHOST:E:\DB\DB.gdb';
DestDB = 'LOCALHOST:E:\DB\DB_NEW.gdb';
TT = 'ACCOUNT_TYPE';
execute ibeblock CopyTable (ScrDB, 'SYSDBA', 'masterkey', 'WIN1251', 'gds32.dll', DestDB, 'SYSDBA', 'masterkey', 'WIN1251', 'gds32.dll', TT, TT, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0, 2);
end
Пятница, вечер.... Ничего на ум, кроме некорректной передачи в блок параметра типа variant не приходит.
|