From 632a86f56afebf7fdaeba90e1a20adcac09db00e Mon Sep 17 00:00:00 2001 From: sunvim Date: Thu, 18 Jun 2015 17:41:41 +0800 Subject: [PATCH 1/4] =?UTF-8?q?Get=E6=95=B0=E6=8D=AE=E6=97=B6=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E4=BA=86=E5=BC=BA=E5=88=B6=E6=80=A7=E6=8E=92=E4=BB=96?= =?UTF-8?q?=E9=94=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- statement.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/statement.go b/statement.go index 0a8de1ee..c3eb67bd 100644 --- a/statement.go +++ b/statement.go @@ -49,7 +49,7 @@ type Statement struct { GroupByStr string HavingStr string ColumnStr string - selectStr string + selectStr string columnMap map[string]bool useAllCols bool OmitStr string @@ -416,7 +416,7 @@ func buildConditions(engine *Engine, table *core.Table, bean interface{}, var colName string if addedTableName { - colName = engine.Quote(tableName)+"."+engine.Quote(col.Name) + colName = engine.Quote(tableName) + "." + engine.Quote(col.Name) } else { colName = engine.Quote(col.Name) } @@ -428,7 +428,7 @@ func buildConditions(engine *Engine, table *core.Table, bean interface{}, } if col.IsDeleted && !unscoped { // tag "deleted" is enabled - colNames = append(colNames, fmt.Sprintf("(%v IS NULL or %v = '0001-01-01 00:00:00')", + colNames = append(colNames, fmt.Sprintf("(%v IS NULL or %v = '0001-01-01 00:00:00')", colName, colName)) } @@ -1139,14 +1139,14 @@ func (statement *Statement) genCountSql(bean interface{}) (string, []interface{} return statement.genSelectSql(fmt.Sprintf("count(%v)", id)), append(statement.Params, statement.BeanArgs...) } -func (statement *Statement) genSelectSql(columnStr string) (a string) { +func (statement *Statement) genSelectSql(columnStr string) string { /*if statement.GroupByStr != "" { if columnStr == "" { columnStr = statement.Engine.Quote(strings.Replace(statement.GroupByStr, ",", statement.Engine.Quote(","), -1)) } //statement.GroupByStr = columnStr }*/ - var distinct string + var distinct, a string if statement.IsDistinct { distinct = "DISTINCT " } @@ -1241,8 +1241,9 @@ func (statement *Statement) genSelectSql(columnStr string) (a string) { a = fmt.Sprintf("SELECT %v FROM (SELECT %v,ROWNUM RN FROM (%v) at WHERE ROWNUM <= %d) aat WHERE RN > %d", columnStr, columnStr, a, statement.Start+statement.LimitN, statement.Start) } } - - return + //在事务中强制性加入排他锁,不开事务则不起作用 FOR oracle & pg & mysql + a += " FOR UPDATE " + return a } func (statement *Statement) processIdParam() { From f549b458b8605d8ed49af92f937c714c3938db06 Mon Sep 17 00:00:00 2001 From: sunsc Date: Tue, 30 Jun 2015 16:45:12 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=82=B2=E8=A7=82?= =?UTF-8?q?=E9=94=81=E9=80=89=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- session.go | 15 ++++++++++----- statement.go | 2 -- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/session.go b/session.go index a1984805..11272c3f 100644 --- a/session.go +++ b/session.go @@ -29,6 +29,7 @@ type Session struct { IsCommitedOrRollbacked bool TransType string IsAutoClose bool + LockRead bool //set sad lock for accepting ro read dirty data // Automatically reset the statement after operations that execute a SQL // query such as Count(), Find(), Get(), ... @@ -637,7 +638,7 @@ func (session *Session) canCache() bool { if session.Statement.RefTable == nil || session.Statement.JoinStr != "" || session.Statement.RawSQL != "" || - session.Tx != nil || + session.Tx != nil || len(session.Statement.selectStr) > 0 { return false } @@ -744,7 +745,7 @@ func (session *Session) cacheGet(bean interface{}, sqlStr string, args ...interf } func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr interface{}, args ...interface{}) (err error) { - if !session.canCache() || + if !session.canCache() || indexNoCase(sqlStr, "having") != -1 || indexNoCase(sqlStr, "group by") != -1 { return ErrCacheFailed @@ -1001,6 +1002,10 @@ func (session *Session) Get(bean interface{}) (bool, error) { if session.Statement.RawSQL == "" { sqlStr, args = session.Statement.genGetSql(bean) + //加入悲观锁 FOR oracle & pg & mysql + if session.LockRead { + sqlStr += " FOR UPDATE " + } } else { sqlStr = session.Statement.RawSQL args = session.Statement.RawParams @@ -1187,7 +1192,7 @@ func (session *Session) Find(rowsSlicePtr interface{}, condiBean ...interface{}) var addedTableName = (len(session.Statement.JoinStr) > 0) colNames, args := buildConditions(session.Engine, table, condiBean[0], true, true, false, true, session.Statement.allUseBool, session.Statement.useAllCols, - session.Statement.unscoped, session.Statement.mustColumnMap, + session.Statement.unscoped, session.Statement.mustColumnMap, session.Statement.TableName(), addedTableName) session.Statement.ConditionStr = strings.Join(colNames, " AND ") session.Statement.BeanArgs = args @@ -3414,7 +3419,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 if session.Statement.ColumnStr == "" { colNames, args = buildUpdates(session.Engine, table, bean, false, false, false, false, session.Statement.allUseBool, session.Statement.useAllCols, - session.Statement.mustColumnMap, session.Statement.nullableMap, + session.Statement.mustColumnMap, session.Statement.nullableMap, session.Statement.columnMap, true) } else { colNames, args, err = genCols(table, session, bean, true, true) @@ -3696,7 +3701,7 @@ func (session *Session) Delete(bean interface{}) (int64, error) { session.Statement.RefTable = table colNames, args := buildConditions(session.Engine, table, bean, true, true, false, true, session.Statement.allUseBool, session.Statement.useAllCols, - session.Statement.unscoped, session.Statement.mustColumnMap, + session.Statement.unscoped, session.Statement.mustColumnMap, session.Statement.TableName(), false) var condition = "" diff --git a/statement.go b/statement.go index c3eb67bd..7083fe54 100644 --- a/statement.go +++ b/statement.go @@ -1241,8 +1241,6 @@ func (statement *Statement) genSelectSql(columnStr string) string { a = fmt.Sprintf("SELECT %v FROM (SELECT %v,ROWNUM RN FROM (%v) at WHERE ROWNUM <= %d) aat WHERE RN > %d", columnStr, columnStr, a, statement.Start+statement.LimitN, statement.Start) } } - //在事务中强制性加入排他锁,不开事务则不起作用 FOR oracle & pg & mysql - a += " FOR UPDATE " return a } From 026c2f53f5e25e3b6a9e0e1deff5fad9339edbe7 Mon Sep 17 00:00:00 2001 From: sunsc Date: Tue, 30 Jun 2015 17:57:36 +0800 Subject: [PATCH 3/4] add SetLockRead --- session.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/session.go b/session.go index 11272c3f..b798fbf7 100644 --- a/session.go +++ b/session.go @@ -97,6 +97,16 @@ func (session *Session) Sql(querystring string, args ...interface{}) *Session { return session } +//set read lock +func (session *Session) SetLockRead(lr ...bool) *Session { + if 0 == len(lr) { + session.LockRead = true + } else { + session.LockRead = lr[0] + } + return session +} + // Method Where provides custom query condition. func (session *Session) Where(querystring string, args ...interface{}) *Session { session.Statement.Where(querystring, args...) From c8bed659dfe77b8bd3ee65b7570126da8df2c333 Mon Sep 17 00:00:00 2001 From: sunsc Date: Tue, 30 Jun 2015 18:13:00 +0800 Subject: [PATCH 4/4] adjust session init --- session.go | 1 + 1 file changed, 1 insertion(+) diff --git a/session.go b/session.go index b798fbf7..79176cd6 100644 --- a/session.go +++ b/session.go @@ -56,6 +56,7 @@ func (session *Session) Init() { session.IsCommitedOrRollbacked = false session.IsAutoClose = false session.AutoResetStatement = true + session.LockRead = false // !nashtsai! is lazy init better? session.afterInsertBeans = make(map[interface{}]*[]func(interface{}), 0)