3 define(
'ADODB_REPLICATE',1.2);
5 include_once(ADODB_DIR.
'/adodb-datadict.inc.php');
103 if (strpos(
$connSrc->databaseType,
'odbtp') !==
false) {
104 $connSrc->_bindInputArray =
false; # bug in odbtp, binding fails
107 if (strpos(
$connDest->databaseType,
'odbtp') !==
false) {
108 $connDest->_bindInputArray =
false; # bug in odbtp, binding fails
117 $this->ddSrc = NewDataDictionary(
$connSrc);
118 $this->ddDest = NewDataDictionary(
$connDest);
119 $this->htmlSpecialChars = isset($_SERVER[
'HTTP_HOST']);
124 if (!is_array($sql)) $sql[] = $sql;
128 if (!$this->
execute) echo
"<pre>",$s.
";\n</pre>";
130 $ok = $this->connDest->Execute($s);
132 if ($this->neverAbort) $ret =
false;
148 if (empty($sql))
return false;
156 return $fn($fld, $mode);
163 if ($this->updateFilter) {
165 return $fn($table, $fld, $val);
172 if ($this->insertFilter) {
174 return $fn($table, $fld, $val);
186 function RunUpdateSrcFn($srcdb, $table, $fldoffsets, $row, $where, $mode, $dest_insertid=null, $lastUpdateFld=
'')
188 if (!$this->updateSrcFn)
return;
191 foreach($fldoffsets as $k) {
192 $bindarr[$k] = $row[$k];
194 $last =
sizeof($row);
196 if ($lastUpdateFld && $row[$last-1]) {
198 if (strpos($ds,
':') !==
false) $s = $srcdb->DBTimeStamp($ds);
199 else $s = $srcdb->qstr($ds);
200 $where =
"WHERE $lastUpdateFld = $s and $where";
202 $where =
"WHERE $where";
205 if (
sizeof($fn) == 1) $set = reset($fn);
206 else $set = @$fn[$mode];
209 if (strlen($dest_insertid) == 0) $dest_insertid =
'null';
210 $set = str_replace(
'$INSERT_ID',$dest_insertid,$set);
212 $sql =
"UPDATE $table SET $set $where ";
213 $ok = $srcdb->Execute($sql,$bindarr);
215 echo $srcdb->ErrorMsg(),
"<br>\n";
219 }
else $fn($srcdb, $table, $row, $where, $bindarr, $mode, $dest_insertid);
229 $prefixidx = $desttable;
232 $types = $conn->MetaColumns($table);
234 echo
"$table does not exist in source db<br>\n";
237 if (!$dropdest && $this->connDest->MetaColumns($desttable)) {
238 echo
"$desttable already exists in dest db<br>\n";
241 if ($this->debug) var_dump($types);
245 foreach($types as $name => $t) {
247 $mt = $this->ddSrc->MetaType($t->type);
248 $len = $t->max_length;
250 if (!$fldname)
continue;
252 $s .= $fldname .
' '.$mt;
253 if (isset($t->scale)) $precision =
'.'.$t->scale;
254 else $precision =
'';
255 if ($mt ==
'C' or $mt ==
'X') $s .=
"($len)";
256 else if ($mt ==
'N' && $precision) $s .=
"($len$precision)";
258 if ($mt ==
'R') $idxcols[] = $fldname;
260 if ($this->copyTableDefaults) {
261 if (isset($t->default_value)) {
262 $v = $t->default_value;
263 if ($mt ==
'C' or $mt ==
'X') $v = $this->connDest->qstr($v);
264 $s .=
' DEFAULT '.$v;
271 $s = implode(
",\n",$sa);
274 if ($this->debug) echo
'<pre>'.$s.
'</pre>';
276 $sqla = $this->ddDest->CreateTableSQL($desttable,$s);
285 $idxs = $conn->MetaIndexes($table);
287 foreach($idxs as $name => $iarr) {
288 $idxoptions = array();
291 if(!empty($iarr[
'unique'])) {
292 $idxoptions[
'UNIQUE'] = 1;
295 foreach($iarr[
'columns'] as $fld) {
299 $idxname = $prefixidx.str_replace($table,$desttable,$name);
303 $idxname = $fn($desttable,$idxname,$fldnames,$idxoptions);
305 $sqla2 = $this->ddDest->_IndexSQL($idxname, $desttable, $fldnames,$idxoptions);
306 $sqla = array_merge($sqla,$sqla2);
319 return $this->connDest->concat(
"' ",
"chr(".ord($v).
")",
"'");
334 $this->connDest = $o;
339 $this->connDest2 = $o;
533 function ReplicateData($table, $desttable =
'', $uniqflds = array(), $where =
'',$ignore_flds = array(),
534 $dstCopyDateFld=
'', $extraflds = array(), $lastUpdateFld =
'')
536 if (is_array($where)) {
537 $wheresrc = $where[0];
538 $wheredest = $where[1];
540 $wheresrc = $wheredest = $where;
542 $dstCopyDateName = $dstCopyDateFld;
543 $dstCopyDateFld = strtoupper($dstCopyDateFld);
546 if (is_string($uniqflds) && strlen($uniqflds)) $uniqflds = array($uniqflds);
547 if (!$desttable) $desttable = $table;
551 if (is_array(reset($uniqflds))) {
557 $destuniqflds = $uniqflds[0];
558 if (
sizeof($uniqflds)>1 && $uniqflds[1])
559 $srcuniqflds = $uniqflds[1];
561 $srcuniqflds = array();
563 if (
sizeof($uniqflds)>2)
564 $srcPKDest = reset($uniqflds[2]);
567 $destuniqflds = $uniqflds;
568 $srcuniqflds = array();
571 foreach($destuniqflds as $k => $u) {
572 if ($u ==
'*INSERTONLY*' || $u ==
'*ONLYINSERT*') {
576 $uniq[strtoupper($u)] = $k;
586 foreach($ignore_flds as $u) {
587 $ignoreflds[strtoupper($u)] = 1;
590 $ignoreflds = array();
596 $dest->noNullStrings =
false;
597 $src->noNullStrings =
false;
598 $src2->noNullStrings =
false;
600 if ($src === $dest) $this->
execute =
false;
602 $types = $src->MetaColumns($table);
604 echo
"Source $table does not exist<br>\n";
607 $dtypes = $dest->MetaColumns($desttable);
609 echo
"Destination $desttable does not exist<br>\n";
616 $srcwheref = array();
617 $fldoffsets = array();
619 foreach($types as $name => $t) {
622 if ($name2 && $name2[0] ==
'"' && $name2[strlen($name2)-1] ==
'"') $name22 = substr($name2,1,strlen($name2)-2);
623 elseif ($name2 && $name2[0] ==
'`' && $name2[strlen($name2)-1] ==
'`') $name22 = substr($name2,1,strlen($name2)-2);
624 else $name22 = $name2;
628 if (!isset($dtypes[($name22)]) || !$name2) {
629 if ($this->debug) echo
" Skipping $name ==> $name2 as not in destination $desttable<br>";
633 if ($name2 == $dstCopyDateFld) {
634 $dstCopyDateName = $t->name;
640 $mt = $src->MetaType($t->type);
641 if ($this->datesAreTimeStamps && $mt ==
'D') $mt =
'T';
642 if ($mt ==
'D') $fldval = $dest->DBDate($fldval);
643 elseif ($mt ==
'T') $fldval = $dest->DBTimeStamp($fldval);
644 $ufld = strtoupper($fld);
646 if (isset($ignoreflds[($name2)]) && !isset($uniq[$ufld])) {
650 if ($this->debug) echo
" field=$fld type=$mt fldval=$fldval<br>";
652 if (!isset($uniq[$ufld])) {
656 $selflds[] = $selfld;
658 $p = $dest->Param($k);
660 if ($mt ==
'D') $p = $dest->DBDate($p,
true);
661 else if ($mt ==
'T') $p = $dest->DBTimeStamp($p,
true);
664 $sets[] =
"$fld = ".$this->RunUpdateFilter($desttable, $fld, $p);
672 if (!empty($srcuniqflds)) $srcwheref[] = $srcuniqflds[$uniq[$ufld]];
673 if ($mt ==
'C') { # normally we don
't include the primary key in the insert if it is numeric, but ok if varchar
680 foreach($extraflds as $fld => $evals) {
681 if (!is_array($evals)) $evals = array($evals, $evals);
682 $insflds[] = $this->RunInsertFilter($desttable,$fld, $p); $params[] = $evals[0];
683 $sets[] = "$fld = ".$evals[1];
686 if ($dstCopyDateFld) {
687 $sets[] = "$dstCopyDateName = ".$dest->sysTimeStamp;
688 $insflds[] = $this->RunInsertFilter($desttable,$dstCopyDateName, $p); $params[] = $dest->sysTimeStamp;
692 if (!empty($srcPKDest)) {
693 $selflds[] = $srcPKDest;
694 $fldoffsets = array($k+1);
697 foreach($wheref as $uu => $fld) {
699 $p = $dest->Param($k);
700 $sp = $src->Param($k);
701 if (!empty($srcuniqflds)) {
702 if ($uu > 1) die("Only one primary key for srcuniqflds allowed currently");
703 $destsrckey = reset($srcuniqflds);
704 $wheres[] = reset($srcuniqflds).' =
'.$p;
706 $insflds[] = $this->RunInsertFilter($desttable,$destsrckey, $p);
709 $wheres[] = $fld.' =
'.$p;
710 if (!isset($ignoreflds[strtoupper($fld)]) || !empty($insertpkey)) {
711 $insflds[] = $this->RunInsertFilter($desttable,$fld, $p);
717 $srcwheres[] = $fld.' =
'.$sp;
723 if (!empty($srcPKDest)) {
724 $fldoffsets = array($k);
725 $srcwheres = array($fld.'=
'.$src->Param($k));
729 if ($lastUpdateFld) {
730 $selflds[] = $lastUpdateFld;
732 $selflds[] = 'null as Z55_DUMMY_LA5TUPD
';
734 $insfldss = implode(',
', $insflds);
735 $fldss = implode(',
', $selflds);
736 $setss = implode(',
', $sets);
737 $paramss = implode(',
', $params);
738 $wheress = implode(' AND
', $wheres);
739 if (isset($srcwheres))
740 $srcwheress = implode(' AND
',$srcwheres);
744 if ($this->readUncommitted && strpos($src->databaseType,'mssql
')) $seltable .= ' with (NOLOCK)
';
746 $sa['SEL'] = "SELECT $fldss FROM $seltable $wheresrc";
747 $sa['INS
'] = "INSERT INTO $desttable ($insfldss) VALUES ($paramss) /**INS**/";
748 $sa['UPD
'] = "UPDATE $desttable SET $setss WHERE $wheress /**UPD**/";
752 $DB1 = "/* <font color=green> Source DB - sample sql in case you need to adapt code\n\n";
753 $DB2 = "/* <font color=green> Dest DB - sample sql in case you need to adapt code\n\n";
755 if (!$this->execute) echo '
758 white-space: -moz-pre-wrap !important;
759 white-space: -pre-wrap;
760 white-space: -o-pre-wrap;
761 word-wrap:
break-word;
765 if ($deleteFirst && $this->deleteFirst) {
766 $where = preg_replace('/[ \n\r\t]+order[ \n\r\t]+by.*$/i
', '', $where);
767 $sql = "DELETE FROM $desttable $wheredest\n";
768 if (!$this->execute) echo $DB2,'</font>*/
',$sql,"\n";
769 else $dest->Execute($sql);
772 global $ADODB_COUNTRECS;
774 $savemode = $src->setFetchMode(ADODB_FETCH_NUM);
775 $ADODB_COUNTRECS = false;
777 if (!$this->execute) {
778 echo $DB1,$sa['SEL'],"</font>\n*/\n\n";
779 echo $DB2,$sa['INS
'],"</font>\n*/\n\n";
780 $suffix = ($onlyInsert) ? ' PRIMKEY=?
' : '';
781 echo $DB2,$sa['UPD
'],"$suffix</font>\n*/\n\n";
783 $rs = $src->Execute($sa['SEL']);
788 $sqlarr = explode('?
',$sa['INS
']);
789 $nparams = sizeof($sqlarr)-1;
791 $useQmark = $dest && ($dest->dataProvider != 'oci8
');
793 while ($rs && !$rs->EOF) {
796 $arr = array_reverse($rs->fields);
797 //Use each() instead of foreach to reduce memory usage -mikefedyk
798 while(list(, $v) = each($arr)) {
800 // from Ron Baldwin <ron.baldwin#sourceprose.com>
801 // Only quote string types
803 if ($typ == 'string')
804 //New memory copy of input created here -mikefedyk
805 $sql .= $dest->qstr($v);
806 else if ($typ == 'double')
807 $sql .= str_replace(',
','.
',$v); // locales fix so 1.1 does not get converted to 1,1
808 else if ($typ == 'boolean
')
809 $sql .= $v ? $dest->true : $dest->false;
810 else if ($typ == 'object') {
811 if (method_exists($v, '__toString
')) $sql .= $dest->qstr($v->__toString());
812 else $sql .= $dest->qstr((string) $v);
813 } else if ($v === null)
819 if ($i == $nparams) break;
822 if (isset($sqlarr[$i])) {
828 $arr = array_reverse($rs->fields);
829 foreach($arr as $k => $v) { // only works on oracle currently
830 $k = sizeof($arr)-$k-1;
831 $v = str_replace(":","%~%COLON%!%",$v);
832 $INS = str_replace(':
'.$k,$this->fixupbinary($dest->qstr($v)),$INS);
834 $INS = str_replace("%~%COLON%!%",":",$INS);
835 if ($this->htmlSpecialChars) $INS = htmlspecialchars($INS);
837 echo "-- $cnt\n",$INS,";\n\n";
842 $src->setFetchMode($savemode);
845 $saved = $src->debug;
847 if ($this->limitRecs>100)
848 $rs = $src->SelectLimit($sa['SEL'],$this->limitRecs);
850 $rs = $src->Execute($sa['SEL']);
851 $src->debug = $saved;
853 if ($this->errHandler) $this->_doerr('SEL',array());
854 return array(0,0,0,0);
858 if ($this->commitReplicate || $commitRecs > 0) {
860 if ($this->updateSrcFn) $src2->BeginTrans();
863 if ($this->updateSrcFn && strpos($src2->databaseType,'mssql
') !== false) {
864 # problem is writers interfere with readers in mssql
865 $rs = $src->_rs2rs($rs);
871 $sizeofrow = sizeof($selflds);
873 $fn = $this->selFilter;
874 $commitRecs = $this->commitRecs;
876 $saved = $dest->debug;
878 if ($this->deleteFirst) $onlyInsert = true;
879 while ($origrow = $rs->FetchRow()) {
881 if ($dest->debug) {flush(); @ob_flush();}
884 if (!$fn($desttable, $origrow, $deleteFirst, $this, $selflds)) continue;
887 $row = array_slice($origrow,0,$sizeofrow-1);
893 if (isset($srcPKDest)) {
894 if (is_null($origrow[$sizeofrow-3])) {
899 if (!$upderr && !$dest->Execute($sa['UPD
'],$row)) {
902 if ($this->errHandler) $this->_doerr('UPD
',$row);
903 if (!$this->neverAbort) break;
906 if ($upderr || $dest->Affected_Rows() == 0) {
909 if (!empty($uniqflds)) $this->RunUpdateSrcFn($src2, $table, $fldoffsets, $origrow, $srcwheress, 'UPD
', null, $lastUpdateFld);
916 if (isset($srcPKDest)) {
917 $row = array_slice($origrow,0,$sizeofrow-2);
920 if (! $dest->Execute($sa['INS
'],$row)) {
923 if ($this->errHandler) $this->_doerr('INS
',$row);
924 if ($this->neverAbort) continue;
927 if ($dest->dataProvider == 'oci8
') {
928 if ($this->oracleSequence) $lastid = $dest->GetOne("select ".$this->oracleSequence.".currVal from dual");
929 else $lastid = 'null
';
931 $lastid = $dest->Insert_ID();
934 if (!$inserr && !empty($uniqflds)) {
935 $this->RunUpdateSrcFn($src2, $table, $fldoffsets, $origrow, $srcwheress, 'INS
', $lastid,$lastUpdateFld);
942 if ($commitRecs > 0 && ($cnt % $commitRecs) == 0) {
943 $dest->CommitTrans();
946 if ($this->updateSrcFn) {
947 $src2->CommitTrans();
955 if ($this->commitReplicate || $commitRecs > 0) {
956 if (!$this->neverAbort && $err) {
957 $dest->RollbackTrans();
958 if ($this->updateSrcFn) $src2->RollbackTrans();
960 $dest->CommitTrans();
961 if ($this->updateSrcFn) $src2->CommitTrans();
965 if ($cnt != $ins + $upd) echo "<p>ERROR: $cnt != INS $ins + UPD $upd</p>";
966 $src->setFetchMode($savemode);
967 return array(!$err, $cnt, $ins, $upd);
969 // trigger support only for sql server and oracle
971 function MergeSrcSetup($srcTable, $pkeys, $srcUpdateDateFld, $srcCopyDateFld, $srcCopyFlagFld,
972 $srcCopyFlagType='C(1)
', $srcCopyFlagVals = array('Y
','N
','P
','=
'))
975 $src = $this->connSrc;
976 $idx = $srcTable.'_mrgIdx
';
977 $cols = $src->MetaColumns($srcTable);
979 if (!isset($cols[strtoupper($srcUpdateDateFld)])) {
980 $sqla = $this->ddSrc->AddColumnSQL($srcTable, "$srcUpdateDateFld TS DEFTIMESTAMP");
981 foreach($sqla as $sql) $src->Execute($sql);
984 if ($srcCopyDateFld && !isset($cols[strtoupper($srcCopyDateFld)])) {
985 $sqla = $this->ddSrc->AddColumnSQL($srcTable, "$srcCopyDateFld TS DEFTIMESTAMP");
986 foreach($sqla as $sql) $src->Execute($sql);
989 $sysdate = $src->sysTimeStamp;
990 $arrv0 = $src->qstr($srcCopyFlagVals[0]);
991 $arrv1 = $src->qstr($srcCopyFlagVals[1]);
992 $arrv2 = $src->qstr($srcCopyFlagVals[2]);
993 $arrv3 = $src->qstr($srcCopyFlagVals[3]);
995 if ($srcCopyFlagFld && !isset($cols[strtoupper($srcCopyFlagFld)])) {
996 $sqla = $this->ddSrc->AddColumnSQL($srcTable, "$srcCopyFlagFld $srcCopyFlagType DEFAULT $arrv1");
997 foreach($sqla as $sql) $src->Execute($sql);
1003 $name = "{$srcTable}_mrgTr";
1004 if (is_array($pkeys) && strpos($src->databaseType,'mssql
') !== false) {
1005 $pk = reset($pkeys);
1007 #$sqla[] = "DROP TRIGGER $name";
1010 ON $srcTable /* for data replication and merge */
1015 $srcUpdateDateFld = case when I.$srcCopyFlagFld = $arrv2 or I.$srcCopyFlagFld = $arrv3 then I.$srcUpdateDateFld
1017 $srcCopyFlagFld = case
1018 when I.$srcCopyFlagFld = $arrv2 then $arrv0
1019 when I.$srcCopyFlagFld = $arrv3 then D.$srcCopyFlagFld
1021 FROM $srcTable S Join Inserted AS I on I.$pk = S.$pk
1022 JOIN Deleted as D ON I.$pk = D.$pk
1023 WHERE I.$srcCopyFlagFld = D.$srcCopyFlagFld or I.$srcCopyFlagFld = $arrv2
1024 or I.$srcCopyFlagFld = $arrv3 or I.$srcCopyFlagFld is null
1026 $sqla[] = 'CREATE
'.$sqltr; // first if does not exists
1027 $sqla[] = 'ALTER
'.$sqltr; // second if it already exists
1028 } else if (strpos($src->databaseType,'oci
') !== false) {
1030 if (strlen($srcTable)>22) $tableidx = substr($srcTable,0,16).substr(crc32($srcTable),6);
1031 else $tableidx = $srcTable;
1033 $name = $tableidx.$this->trgSuffix;
1034 $idx = $tableidx.$this->idxSuffix;
1036 CREATE OR REPLACE TRIGGER $name /* for data replication and merge */
1037 BEFORE UPDATE ON $srcTable REFERENCING NEW AS NEW OLD AS OLD
1040 if :new.$srcCopyFlagFld = $arrv2 then
1041 :new.$srcCopyFlagFld := $arrv0;
1042 elsif :new.$srcCopyFlagFld = $arrv3 then
1043 :new.$srcCopyFlagFld := :old.$srcCopyFlagFld;
1044 elsif :old.$srcCopyFlagFld = :new.$srcCopyFlagFld or :new.$srcCopyFlagFld is null then
1045 if $this->trLogic then
1046 :new.$srcUpdateDateFld := $sysdate;
1047 :new.$srcCopyFlagFld := $arrv1;
1053 foreach($sqla as $sql) $src->Execute($sql);
1055 if ($srcCopyFlagFld) $srcCopyFlagFld .= ',
';
1056 $src->Execute("CREATE INDEX {$idx} on $srcTable ($srcCopyFlagFld$srcUpdateDateFld)");
1061 Perform Merge by copying all data modified from src to dest
1062 then update src copied flag if present.
1064 Returns array taken from ReplicateData:
1067 $arr[0] = true if no error, false if error
1068 $arr[1] = number of recs processed
1069 $arr[2] = number of successful inserts
1070 $arr[3] = number of successful updates
1072 $srcTable = src table
1073 $dstTable = dest table
1074 $pkeys = primary keys array. if empty, then only inserts will occur
1075 $srcignoreflds = ignore these flds (must be upper cased)
1076 $setsrc = updateSrcFn string
1077 $srcUpdateDateFld = field in src with the last update date
1078 $srcCopyFlagFld = false = optional field that holds the copied indicator
1079 $flagvals=array('Y
','N
','P
','=
') = array of values indicating array(copied, not copied).
1080 Null is assumed to mean not copied. The 3rd value 'P
' indicates that we want to force 'Y
', bypassing
1081 default trigger behaviour to reset the COPIED='N
' when the record is replicated from other side.
1082 The last value '=
' is don't change copyflag.
1083 $srcCopyDateFld = field that holds last copy
date in src table, which will be updated on
Merge()
1084 $dstCopyDateFld = field that holds last copy
date in dst table, which will be updated on
Merge()
1085 $defaultDestRaiseErrorFn = The adodb raiseErrorFn handler. Default is to not raise an error.
1086 Just output error message to stdout
1091 function
Merge($srcTable, $dstTable, $pkeys, $srcignoreflds, $setsrc,
1093 $srcCopyFlagFld, $flagvals=array('Y','N','P','='),
1094 $srcCopyDateFld = false,
1095 $dstCopyDateFld = false,
1097 $orderBy = '',
# MUST INCLUDE THE "ORDER BY" suffix
1098 $copyDoneFlagIdx = 3,
1099 $defaultDestRaiseErrorFn =
'')
1104 $time = $src->Time();
1112 $srcignoreflds[] = $srcUpdateDateFld;
1113 $srcignoreflds[] = $srcCopyFlagFld;
1114 $srcignoreflds[] = $srcCopyDateFld;
1116 if (empty($whereClauses)) $whereClauses =
'1=1';
1117 $where =
" WHERE ($whereClauses) and ($srcCopyFlagFld = ".$src->qstr($flagvals[1]).
')';
1118 if ($orderBy) $where .=
' '.$orderBy;
1119 else $where .=
' ORDER BY '.$srcUpdateDateFld;
1121 if ($setsrc) $set[] = $setsrc;
1122 else $set = array();
1124 if ($srcCopyFlagFld) $set[] =
"$srcCopyFlagFld = ".$src->qstr($flagvals[2]);
1125 if ($srcCopyDateFld) $set[]=
"$srcCopyDateFld = ".$src->sysTimeStamp;
1126 if ($set) $this->updateSrcFn = array(implode(
', ',$set));
1127 else $this->updateSrcFn =
'';
1130 $extra[$srcCopyFlagFld] = array($dest->qstr($flagvals[0]),$dest->qstr($flagvals[$copyDoneFlagIdx]));
1132 $saveraise = $dest->raiseErrorFn;
1133 $dest->raiseErrorFn =
'';
1135 if ($this->compat && $this->compat == 1.0) $srcUpdateDateFld =
'';
1136 $arr = $this->
ReplicateData($srcTable, $dstTable, $pkeys, $where, $srcignoreflds,
1137 $dstCopyDateFld,$extra,$srcUpdateDateFld);
1139 $dest->raiseErrorFn = $saveraise;
1141 $this->updateSrcFn = $upd;
1155 function MergeDone($srcTable, $dstTable, $pkeys, $srcignoreflds, $setsrc,
1157 $srcCopyFlagFld, $flagvals=array(
'Y',
'N',
'P',
'='),
1158 $srcCopyDateFld =
false,
1159 $dstCopyDateFld =
false,
1161 $orderBy =
'', # MUST INCLUDE THE
"ORDER BY" suffix
1162 $copyDoneFlagIdx = 2,
1163 $defaultDestRaiseErrorFn =
'')
1165 return $this->
Merge($srcTable, $dstTable, $pkeys, $srcignoreflds, $setsrc,
1167 $srcCopyFlagFld, $flagvals,
1171 $orderBy, # MUST INCLUDE THE
"ORDER BY" suffix
1173 $defaultDestRaiseErrorFn);
1179 if ($fn) $fn($this, $reason, $selflds);