feat(contrib/drivers/dm): add Replace/InsertIgnore support and field type/length enhancements for dm database (#4541)

This pull request introduces significant improvements to the DM database
driver, especially around insert operations, and refines documentation
and tests to reflect these changes. The main focus is enabling support
for "replace" and "insert ignore" operations using DM's `MERGE`
statement, improving type reporting for table fields, and updating
documentation for clarity and accuracy.

### DM Driver Insert Operations

* Added support for `Replace` and `InsertIgnore` operations in the DM
driver by internally mapping them to DM's `MERGE` statement. This
enables upsert and insert-ignore behavior for DM databases, improving
compatibility with other drivers.
* Implemented helper methods (`doMergeInsert`, `doInsertIgnore`, and
`getPrimaryKeys`) to generate correct `MERGE` SQL statements and
automatically detect primary keys when needed.
[[1]](diffhunk://#diff-f51b30e3f0b0f1284b905385a89992efd0de2fe9ff8c5a4062344dfab17d428eL31-R94)
[[2]](diffhunk://#diff-f51b30e3f0b0f1284b905385a89992efd0de2fe9ff8c5a4062344dfab17d428eL115-R212)
* Updated the logic for building update values and SQL generation to
ensure correct behavior for both upsert and insert-ignore cases.
[[1]](diffhunk://#diff-f51b30e3f0b0f1284b905385a89992efd0de2fe9ff8c5a4062344dfab17d428eL61-R109)
[[2]](diffhunk://#diff-f51b30e3f0b0f1284b905385a89992efd0de2fe9ff8c5a4062344dfab17d428eL89-R132)
[[3]](diffhunk://#diff-f51b30e3f0b0f1284b905385a89992efd0de2fe9ff8c5a4062344dfab17d428eL100-R144)
[[4]](diffhunk://#diff-f51b30e3f0b0f1284b905385a89992efd0de2fe9ff8c5a4062344dfab17d428eL115-R212)

### Table Field Type Reporting

* Improved the DM driver's `TableFields` method to report column types
with length/precision (e.g., `VARCHAR(128)` instead of just `VARCHAR`),
aligning with expectations and other drivers.
[[1]](diffhunk://#diff-40a365112421ae1967bd960f8acefcc91ddb8180865b78bc49cd090fbf4883daL26-R26)
[[2]](diffhunk://#diff-40a365112421ae1967bd960f8acefcc91ddb8180865b78bc49cd090fbf4883daR88-R105)
* Updated related unit tests to expect the new type format for DM table
fields.

### Documentation Updates

* Removed outdated or redundant documentation in both English and
Chinese driver README files, and clarified supported features and
limitations for DM and other drivers.
[[1]](diffhunk://#diff-d49f5bc3a34b11a6ccb82cc54675b06a7dea5f0a943ae91c4ca0d28bd5003299L1)
[[2]](diffhunk://#diff-d49f5bc3a34b11a6ccb82cc54675b06a7dea5f0a943ae91c4ca0d28bd5003299L47-R46)
[[3]](diffhunk://#diff-d49f5bc3a34b11a6ccb82cc54675b06a7dea5f0a943ae91c4ca0d28bd5003299L119-L122)
[[4]](diffhunk://#diff-05411a14e9c7ca235f7f436bfde732853aa93b364361fe80d65ac768f4e4d613L1-L126)

### Test Suite Enhancements

* Refactored and restored unit tests for DM driver insert operations,
including tests for `Save`, `Insert`, and the new `InsertIgnore`
functionality to ensure correct behavior and compatibility.
[[1]](diffhunk://#diff-2b1a59b8b2adaa1ca3074629374ab122929e4d4fbb4cc794b8e1db60ebf8d4c2L143-L245)
[[2]](diffhunk://#diff-2b1a59b8b2adaa1ca3074629374ab122929e4d4fbb4cc794b8e1db60ebf8d4c2R512-R632)
* Minor adjustments to DM test initialization for improved clarity.

### Core Insert Logic Minor Refactoring

* Minor variable renaming for clarity in the core insert logic
(`gdb_core.go`), improving code readability.
[[1]](diffhunk://#diff-b1bbe5e3995261813e4e0ac6ffee8a37c236eaa2759f2bd82e211711695a70bcL449-R452)
[[2]](diffhunk://#diff-b1bbe5e3995261813e4e0ac6ffee8a37c236eaa2759f2bd82e211711695a70bcL466-R474)

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
John Guo
2025-12-04 20:12:12 +08:00
committed by GitHub
parent 6e0ba551f9
commit baf30a0e99
10 changed files with 1659 additions and 293 deletions

View File

@ -446,8 +446,10 @@ func (c *Core) DoInsert(ctx context.Context, link Link, table string, list List,
// Group the list by fields. Different fields to different list.
// It here uses ListMap to keep sequence for data inserting.
// ============================================================================================
var keyListMap = gmap.NewListMap()
var tmpkeyListMap = make(map[string]List)
var (
keyListMap = gmap.NewListMap()
tmpKeyListMap = make(map[string]List)
)
for _, item := range list {
mapLen := len(item)
if mapLen == 0 {
@ -463,13 +465,13 @@ func (c *Core) DoInsert(ctx context.Context, link Link, table string, list List,
keys = tmpKeys // for fieldsToSequence
tmpKeysInSequenceStr := gstr.Join(tmpKeys, ",")
if tmpkeyListMapItem, ok := tmpkeyListMap[tmpKeysInSequenceStr]; ok {
tmpkeyListMap[tmpKeysInSequenceStr] = append(tmpkeyListMapItem, item)
if tmpKeyListMapItem, ok := tmpKeyListMap[tmpKeysInSequenceStr]; ok {
tmpKeyListMap[tmpKeysInSequenceStr] = append(tmpKeyListMapItem, item)
} else {
tmpkeyListMap[tmpKeysInSequenceStr] = List{item}
tmpKeyListMap[tmpKeysInSequenceStr] = List{item}
}
}
for tmpKeysInSequenceStr, itemList := range tmpkeyListMap {
for tmpKeysInSequenceStr, itemList := range tmpKeyListMap {
keyListMap.Set(tmpKeysInSequenceStr, itemList)
}
if keyListMap.Size() > 1 {

View File

@ -380,6 +380,7 @@ func (m *softTimeMaintainer) GetValueByFieldTypeForCreateOrUpdate(
ctx context.Context, fieldType LocalType, isDeletedField bool,
) any {
var value any
// for create or update procedure, the deleted field is always set to non-deleted value.
if isDeletedField {
switch fieldType {
case LocalTypeDate, LocalTypeTime, LocalTypeDatetime: