Example #1
0
        public static string Copy(Program program, TableNode sourceTable, TableNode targetTable, GenerateStatementHandler generateStatement)
        {
            Statement targetStatement =
                generateStatement
                (
                    sourceTable,
                    targetTable,
                    (Expression)targetTable.EmitStatement(Alphora.Dataphor.DAE.Language.D4.EmitMode.ForCopy)
                );

            Schema.Key displaySourceKey = program.FindClusteringKey(sourceTable.TableVar);

            StringBuilder result = new StringBuilder();
            long          succeededUpdateCount          = 0;
            long          failedUpdateCount             = 0;
            bool          maxResultLengthMessageWritten = false;

            // Start a new process so that we don't mess with the transaction context of this one
            ProcessInfo info = new ProcessInfo(program.ServerProcess.ServerSession.SessionInfo);

            info.UseImplicitTransactions = false;
            IServerProcess targetProcess = ((IServerSession)program.ServerProcess.ServerSession).StartProcess(info);

            try
            {
                Program targetProgram = new Program((ServerProcess)targetProcess);
                targetProgram.Code = targetTable;
                targetProgram.Start(null);
                try
                {
                    // Have the target program use the main program's context
                    Stack oldTargetContext = targetProgram.SwitchContext(program.Stack);
                    try
                    {
                        info.DefaultIsolationLevel = IsolationLevel.Browse;
                        IServerProcess sourceProcess = ((IServerSession)program.ServerProcess.ServerSession).StartProcess(info);
                        try
                        {
                            Program sourceProgram = new Program((ServerProcess)sourceProcess);
                            sourceProgram.Code = sourceTable;
                            sourceProgram.Start(null);
                            try
                            {
                                // Have the source program use the main program's context
                                Stack oldSourceContext = sourceProgram.SwitchContext(program.Stack);
                                try
                                {
                                    ITable source = (ITable)sourceTable.Execute(sourceProgram);
                                    try
                                    {
                                        source.Open();

                                        // TODO: IBAS Project #26790 - allow cross-process row copies for streamed types
                                        // There is a MarshalRow call in the LocalProcess, would that solve this problem?
                                        using (Row row = new Row(targetProcess.ValueManager, sourceTable.DataType.CreateRowType()))
                                        {
                                            DataParams paramsValue = new DataParams();
                                            paramsValue.Add(new DataParam("ASourceRow", row.DataType, DAE.Language.Modifier.Const, row));

                                            IServerStatementPlan target = targetProcess.PrepareStatement(new D4TextEmitter().Emit(targetStatement), paramsValue);
                                            try
                                            {
                                                target.CheckCompiled();

                                                while (source.Next())
                                                {
                                                    row.ClearValues();
                                                    targetProcess.BeginTransaction(IsolationLevel.Isolated);
                                                    try
                                                    {
                                                        source.Select(row);
                                                        target.Execute(paramsValue);
                                                        targetProcess.CommitTransaction();
                                                        succeededUpdateCount++;
                                                    }
                                                    catch (Exception exception)
                                                    {
                                                        failedUpdateCount++;
                                                        targetProcess.RollbackTransaction();
                                                        if (result.Length < 100000)
                                                        {
                                                            result.Append(KeyValuesToString(displaySourceKey, row) + " - " + exception.Message + "\r\n");
                                                        }
                                                        else
                                                        {
                                                            if (!maxResultLengthMessageWritten)
                                                            {
                                                                result.Append(Strings.Get("MaxResultLengthExceeded"));
                                                                maxResultLengthMessageWritten = true;
                                                            }
                                                        }
                                                    }

                                                    // Yield in case our process is aborted.
                                                    program.CheckAborted();
                                                }
                                            }
                                            finally
                                            {
                                                targetProcess.UnprepareStatement(target);
                                            }
                                        }
                                    }
                                    finally
                                    {
                                        source.Close();
                                    }
                                }
                                finally
                                {
                                    sourceProgram.SwitchContext(oldSourceContext);                                      // Don't let the source program cleanup the main context
                                }
                            }
                            finally
                            {
                                sourceProgram.Stop(null);
                            }
                        }
                        finally
                        {
                            ((IServerSession)program.ServerProcess.ServerSession).StopProcess(sourceProcess);
                        }

                        result.AppendFormat(Strings.Get("Results"), succeededUpdateCount, failedUpdateCount);
                        return(result.ToString());
                    }
                    finally
                    {
                        targetProgram.SwitchContext(oldTargetContext);                          // Don't let the target program cleanup the main context
                    }
                }
                finally
                {
                    targetProgram.Stop(null);
                }
            }
            finally
            {
                ((IServerSession)program.ServerProcess.ServerSession).StopProcess(targetProcess);
            }
        }