From 8ba5578552e8a1787b8293e0a0338036febebe6e Mon Sep 17 00:00:00 2001 From: smzgl Date: Thu, 28 Aug 2025 03:22:01 +0800 Subject: [PATCH 1/4] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8Dmysql=E4=B8=8D?= =?UTF-8?q?=E5=90=8C=E6=95=B0=E6=8D=AE=E5=BA=93=E4=B8=8B=E7=9B=B8=E5=90=8C?= =?UTF-8?q?=E8=A1=A8=E5=90=8D=E7=9B=B8=E5=90=8C=E5=AD=97=E6=AE=B5=E5=90=8D?= =?UTF-8?q?=E5=87=BA=E7=8E=B0=E5=AD=97=E6=AE=B5=E5=8F=A0=E5=8A=A0=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 当不同数据库存在相同表名和相同字段名, 并且该字段存在约束时, 例如字段类型是JSON, 会出现字段叠加. 导致访问数据库时, 出现数组越界. --- contrib/drivers/mysql/mysql_table_fields.go | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/drivers/mysql/mysql_table_fields.go b/contrib/drivers/mysql/mysql_table_fields.go index 72ffa7e29ec..7b4888e80ea 100644 --- a/contrib/drivers/mysql/mysql_table_fields.go +++ b/contrib/drivers/mysql/mysql_table_fields.go @@ -29,6 +29,7 @@ SELECT FROM information_schema.COLUMNS AS c LEFT JOIN information_schema.CHECK_CONSTRAINTS AS ch ON c.TABLE_NAME = ch.TABLE_NAME + AND c.TABLE_SCHEMA = ch.CONSTRAINT_SCHEMA AND c.COLUMN_NAME = ch.CONSTRAINT_NAME WHERE c.TABLE_SCHEMA = '%s' From dd4346fc4e0c6c4f10e34e37952ba73987f14dba Mon Sep 17 00:00:00 2001 From: smzgl Date: Wed, 14 Jan 2026 21:28:40 +0800 Subject: [PATCH 2/4] =?UTF-8?q?feat(gdb/gdb=5Fmodel=5Flock.go):=20?= =?UTF-8?q?=E6=94=AF=E6=8C=81FOR=20UPDATE=20SKIP=20LOCKED=20=E8=AF=AD?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- database/gdb/gdb_model_lock.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/database/gdb/gdb_model_lock.go b/database/gdb/gdb_model_lock.go index a207a126e8d..52dc5ce20c2 100644 --- a/database/gdb/gdb_model_lock.go +++ b/database/gdb/gdb_model_lock.go @@ -13,6 +13,14 @@ func (m *Model) LockUpdate() *Model { return model } +// LockUpdateSkipLocked sets the lock for update for current operation . +// It skips the locked rows. +func (m *Model) LockUpdateSkipLocked() *Model { + model := m.getModel() + model.lockInfo = "FOR UPDATE SKIP LOCKED" + return model +} + // LockShared sets the lock in share mode for current operation. func (m *Model) LockShared() *Model { model := m.getModel() From e5d03b431373dc9b3f37631ae3654f3c00eb273e Mon Sep 17 00:00:00 2001 From: hailaz <739476267@qq.com> Date: Thu, 15 Jan 2026 12:17:37 +0800 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=BA=93=E9=94=81=E5=B8=B8=E9=87=8F=E4=B8=8E=E9=80=9A?= =?UTF-8?q?=E7=94=A8=E9=94=81=E5=AE=9A=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- database/gdb/gdb_model_lock.go | 108 +++++++++++++++++++++++++++++++-- 1 file changed, 104 insertions(+), 4 deletions(-) diff --git a/database/gdb/gdb_model_lock.go b/database/gdb/gdb_model_lock.go index 52dc5ce20c2..d15697970f9 100644 --- a/database/gdb/gdb_model_lock.go +++ b/database/gdb/gdb_model_lock.go @@ -6,24 +6,124 @@ package gdb +// Lock clause constants for different databases. +// These constants provide type-safe and IDE-friendly access to various lock syntaxes. +const ( + // Common lock clauses (supported by most databases) + LockForUpdate = "FOR UPDATE" + LockForUpdateSkipLocked = "FOR UPDATE SKIP LOCKED" + + // MySQL lock clauses + LockInShareMode = "LOCK IN SHARE MODE" // MySQL legacy syntax + LockForShare = "FOR SHARE" // MySQL 8.0+ and PostgreSQL + LockForUpdateNowait = "FOR UPDATE NOWAIT" // MySQL 8.0+ and Oracle + + // PostgreSQL specific lock clauses + LockForNoKeyUpdate = "FOR NO KEY UPDATE" + LockForKeyShare = "FOR KEY SHARE" + LockForShareNowait = "FOR SHARE NOWAIT" + LockForShareSkipLocked = "FOR SHARE SKIP LOCKED" + LockForNoKeyUpdateNowait = "FOR NO KEY UPDATE NOWAIT" + LockForNoKeyUpdateSkipLocked = "FOR NO KEY UPDATE SKIP LOCKED" + LockForKeyShareNowait = "FOR KEY SHARE NOWAIT" + LockForKeyShareSkipLocked = "FOR KEY SHARE SKIP LOCKED" + + // Oracle specific lock clauses + LockForUpdateWait5 = "FOR UPDATE WAIT 5" + LockForUpdateWait10 = "FOR UPDATE WAIT 10" + LockForUpdateWait30 = "FOR UPDATE WAIT 30" + + // SQL Server lock hints (use with WITH clause) + LockWithUpdLock = "WITH (UPDLOCK)" + LockWithHoldLock = "WITH (HOLDLOCK)" + LockWithXLock = "WITH (XLOCK)" + LockWithTabLock = "WITH (TABLOCK)" + LockWithNoLock = "WITH (NOLOCK)" + LockWithUpdLockHoldLock = "WITH (UPDLOCK, HOLDLOCK)" +) + +// Lock sets a custom lock clause for the current operation. +// This is a generic method that allows you to specify any lock syntax supported by your database. +// You can use predefined constants or custom strings. +// +// Database-specific lock syntax support: +// +// PostgreSQL (most comprehensive): +// - "FOR UPDATE" - Exclusive lock, blocks all access +// - "FOR NO KEY UPDATE" - Weaker exclusive lock, doesn't block FOR KEY SHARE +// - "FOR SHARE" - Shared lock, allows reads but blocks writes +// - "FOR KEY SHARE" - Weakest lock, only locks key values +// - All above can be combined with: +// - "NOWAIT" - Return immediately if lock cannot be acquired +// - "SKIP LOCKED" - Skip locked rows instead of waiting +// +// MySQL: +// - "FOR UPDATE" - Exclusive lock (all versions) +// - "LOCK IN SHARE MODE" - Shared lock (legacy syntax) +// - "FOR SHARE" - Shared lock (MySQL 8.0+) +// - "FOR UPDATE NOWAIT" - MySQL 8.0+ only +// - "FOR UPDATE SKIP LOCKED" - MySQL 8.0+ only +// +// Oracle: +// - "FOR UPDATE" - Exclusive lock +// - "FOR UPDATE NOWAIT" - Exclusive lock, no wait +// - "FOR UPDATE SKIP LOCKED" - Exclusive lock, skip locked rows +// - "FOR UPDATE WAIT n" - Exclusive lock, wait n seconds +// - "FOR UPDATE OF column_list" - Lock specific columns +// +// SQL Server (uses WITH hints): +// - "WITH (UPDLOCK)" - Update lock +// - "WITH (HOLDLOCK)" - Hold lock until transaction end +// - "WITH (XLOCK)" - Exclusive lock +// - "WITH (TABLOCK)" - Table lock +// - "WITH (NOLOCK)" - No lock (dirty read) +// - "WITH (UPDLOCK, HOLDLOCK)" - Combined update and hold lock +// +// SQLite: +// - Limited locking support, database-level locks only +// - No row-level lock syntax supported +// +// Usage examples: +// +// db.Model("users").Lock("FOR UPDATE NOWAIT").Where("id", 1).One() +// db.Model("users").Lock("FOR SHARE SKIP LOCKED").Where("status", "active").All() +// db.Model("users").Lock("WITH (UPDLOCK)").Where("id", 1).One() // SQL Server +// db.Model("users").Lock("FOR UPDATE OF name, email").Where("id", 1).One() // Oracle +// db.Model("users").Lock("FOR UPDATE WAIT 15").Where("id", 1).One() // Oracle custom wait +// +// Or use predefined constants for better IDE support: +// +// db.Model("users").Lock(gdb.LockForUpdateNowait).Where("id", 1).One() +// db.Model("users").Lock(gdb.LockForShareSkipLocked).Where("status", "active").All() +func (m *Model) Lock(lockClause string) *Model { + model := m.getModel() + model.lockInfo = lockClause + return model +} + // LockUpdate sets the lock for update for current operation. +// This is equivalent to Lock("FOR UPDATE"). func (m *Model) LockUpdate() *Model { model := m.getModel() - model.lockInfo = "FOR UPDATE" + model.lockInfo = LockForUpdate return model } -// LockUpdateSkipLocked sets the lock for update for current operation . +// LockUpdateSkipLocked sets the lock for update for current operation. // It skips the locked rows. +// This is equivalent to Lock("FOR UPDATE SKIP LOCKED"). +// Note: Supported by PostgreSQL, Oracle, and MySQL 8.0+. func (m *Model) LockUpdateSkipLocked() *Model { model := m.getModel() - model.lockInfo = "FOR UPDATE SKIP LOCKED" + model.lockInfo = LockForUpdateSkipLocked return model } // LockShared sets the lock in share mode for current operation. +// This is equivalent to Lock("LOCK IN SHARE MODE") for MySQL or Lock("FOR SHARE") for PostgreSQL. +// Note: For maximum compatibility, this uses MySQL's legacy syntax. func (m *Model) LockShared() *Model { model := m.getModel() - model.lockInfo = "LOCK IN SHARE MODE" + model.lockInfo = LockInShareMode return model } From 95c189bce4453c3ef74e321fbcc185a83045d3fe Mon Sep 17 00:00:00 2001 From: hailaz <739476267@qq.com> Date: Thu, 15 Jan 2026 12:41:20 +0800 Subject: [PATCH 4/4] Update database/gdb/gdb_model_lock.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- database/gdb/gdb_model_lock.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/gdb/gdb_model_lock.go b/database/gdb/gdb_model_lock.go index d15697970f9..3fb4e1f45e4 100644 --- a/database/gdb/gdb_model_lock.go +++ b/database/gdb/gdb_model_lock.go @@ -109,7 +109,7 @@ func (m *Model) LockUpdate() *Model { return model } -// LockUpdateSkipLocked sets the lock for update for current operation. +// LockUpdateSkipLocked sets the lock for update with skip locked behavior for current operation. // It skips the locked rows. // This is equivalent to Lock("FOR UPDATE SKIP LOCKED"). // Note: Supported by PostgreSQL, Oracle, and MySQL 8.0+.