( ctx *sql.Context, conn *stdsql.Conn, tx *stdsql.Tx, table tableIdentifier, appender *DeltaAppender, stats *FlushStats, )
| 135 | } |
| 136 | |
| 137 | func (c *DeltaController) updateTable( |
| 138 | ctx *sql.Context, |
| 139 | conn *stdsql.Conn, |
| 140 | tx *stdsql.Tx, |
| 141 | table tableIdentifier, |
| 142 | appender *DeltaAppender, |
| 143 | stats *FlushStats, |
| 144 | ) error { |
| 145 | if tx == nil { |
| 146 | return fmt.Errorf("no active transaction") |
| 147 | } |
| 148 | defer appender.ResetCounters() |
| 149 | |
| 150 | // We consider the following cases: |
| 151 | // 1. INSERT only - no DELETE or UPDATE. In this case, we can do a simple INSERT INTO in an optimized way, |
| 152 | // without the deduplication step (as the source has confirmed that there are no duplicates) and the DELETE step. |
| 153 | // The data can go directly from the delta view to the base table. |
| 154 | // 2. DELETE only - no INSERT or UPDATE. In this case, we can do a simple DELETE FROM in an optimized way, |
| 155 | // without the the INSERT step and the deduplication step (as the source has confirmed that there are no duplicates). |
| 156 | // The delta view can be directly used to delete rows from the base table, without the need for a temporary table. |
| 157 | // 3. INSERT + non-primary-key UPDATE - no DELETE. In this case, we can skip the DELETE step. |
| 158 | // Therefore, the temporary table is not needed as the delta view will be read only once. |
| 159 | // 4. The general case - INSERT, DELETE, and UPDATE. In this case, we need to create a temporary table |
| 160 | // to store the deduplicated delta and then do the INSERT and DELETE steps. |
| 161 | |
| 162 | // Identify the types of changes in the delta |
| 163 | hasInserts := appender.counters.event.insert > 0 |
| 164 | hasDeletes := appender.counters.event.delete > 0 |
| 165 | hasUpdates := appender.counters.event.update > 0 |
| 166 | |
| 167 | if log := ctx.GetLogger(); log.Logger.IsLevelEnabled(logrus.DebugLevel) { |
| 168 | log.Debugf("Delta: %s.%s: stats: %+v", table.dbName, table.tableName, appender.counters) |
| 169 | } |
| 170 | |
| 171 | withoutIndex := configuration.IsReplicationWithoutIndex() |
| 172 | |
| 173 | switch { |
| 174 | case hasInserts && !hasDeletes && !hasUpdates: |
| 175 | // Case 1: INSERT only |
| 176 | return c.handleInsertOnly(ctx, conn, tx, table, appender, stats) |
| 177 | case hasDeletes && !hasInserts && !hasUpdates: |
| 178 | // Case 2: DELETE only |
| 179 | return c.handleDeleteOnly(ctx, conn, tx, table, appender, stats) |
| 180 | case appender.counters.action.delete == 0 && !withoutIndex: |
| 181 | // Case 3: INSERT + non-primary-key UPDATE |
| 182 | return c.handleZeroDelete(ctx, conn, tx, table, appender, stats) |
| 183 | case withoutIndex: |
| 184 | // Case 4: Without index |
| 185 | return c.handleWithoutIndex(ctx, conn, tx, table, appender, stats) |
| 186 | default: |
| 187 | // Case 4: General case |
| 188 | return c.handleGeneralCase(ctx, conn, tx, table, appender, stats) |
| 189 | } |
| 190 | } |
| 191 | |
| 192 | // Helper function to build the Arrow record and register the view |
| 193 | func (c *DeltaController) prepareArrowView( |
no test coverage detected