diff --git a/database/gdb/gdb_model.go b/database/gdb/gdb_model.go index f02ab4c08f5..39b9fed3580 100644 --- a/database/gdb/gdb_model.go +++ b/database/gdb/gdb_model.go @@ -17,44 +17,45 @@ import ( // Model is core struct implementing the DAO for ORM. type Model struct { - db DB // Underlying DB interface. - tx TX // Underlying TX interface. - rawSql string // rawSql is the raw SQL string which marks a raw SQL based Model not a table based Model. - schema string // Custom database schema. - linkType int // Mark for operation on master or slave. - tablesInit string // Table names when model initialization. - tables string // Operation table names, which can be more than one table names and aliases, like: "user", "user u", "user u, user_detail ud". - fields []any // Operation fields, multiple fields joined using char ','. - fieldsEx []any // Excluded operation fields, it here uses slice instead of string type for quick filtering. - withArray []any // Arguments for With feature. - withAll bool // Enable model association operations on all objects that have "with" tag in the struct. - extraArgs []any // Extra custom arguments for sql, which are prepended to the arguments before sql committed to underlying driver. - whereBuilder *WhereBuilder // Condition builder for where operation. - groupBy string // Used for "group by" statement. - orderBy string // Used for "order by" statement. - having []any // Used for "having..." statement. - start int // Used for "select ... start, limit ..." statement. - limit int // Used for "select ... start, limit ..." statement. - option int // Option for extra operation features. - offset int // Offset statement for some databases grammar. - partition string // Partition table partition name. - data any // Data for operation, which can be type of map/[]map/struct/*struct/string, etc. - batch int // Batch number for batch Insert/Replace/Save operations. - filter bool // Filter data and where key-value pairs according to the fields of the table. - distinct string // Force the query to only return distinct results. - lockInfo string // Lock for update or in shared lock. - cacheEnabled bool // Enable sql result cache feature, which is mainly for indicating cache duration(especially 0) usage. - cacheOption CacheOption // Cache option for query statement. - hookHandler HookHandler // Hook functions for model hook feature. - unscoped bool // Disables soft deleting features when select/delete operations. - safe bool // If true, it clones and returns a new model object whenever operation done; or else it changes the attribute of current model. - onDuplicate any // onDuplicate is used for on Upsert clause. - onDuplicateEx any // onDuplicateEx is used for excluding some columns on Upsert clause. - onConflict any // onConflict is used for conflict keys on Upsert clause. - tableAliasMap map[string]string // Table alias to true table name, usually used in join statements. - softTimeOption SoftTimeOption // SoftTimeOption is the option to customize soft time feature for Model. - shardingConfig ShardingConfig // ShardingConfig for database/table sharding feature. - shardingValue any // Sharding value for sharding feature. + db DB // Underlying DB interface. + tx TX // Underlying TX interface. + rawSql string // rawSql is the raw SQL string which marks a raw SQL based Model not a table based Model. + schema string // Custom database schema. + linkType int // Mark for operation on master or slave. + tablesInit string // Table names when model initialization. + tables string // Operation table names, which can be more than one table names and aliases, like: "user", "user u", "user u, user_detail ud". + fields []any // Operation fields, multiple fields joined using char ','. + fieldsEx []any // Excluded operation fields, it here uses slice instead of string type for quick filtering. + withArray []any // Arguments for With feature. + withAll bool // Enable model association operations on all objects that have "with" tag in the struct. + extraArgs []any // Extra custom arguments for sql, which are prepended to the arguments before sql committed to underlying driver. + whereBuilder *WhereBuilder // Condition builder for where operation. + groupBy string // Used for "group by" statement. + orderBy string // Used for "order by" statement. + having []any // Used for "having..." statement. + start int // Used for "select ... start, limit ..." statement. + limit int // Used for "select ... start, limit ..." statement. + option int // Option for extra operation features. + offset int // Offset statement for some databases grammar. + partition string // Partition table partition name. + data any // Data for operation, which can be type of map/[]map/struct/*struct/string, etc. + batch int // Batch number for batch Insert/Replace/Save operations. + filter bool // Filter data and where key-value pairs according to the fields of the table. + distinct string // Force the query to only return distinct results. + lockInfo string // Lock for update or in shared lock. + cacheEnabled bool // Enable sql result cache feature, which is mainly for indicating cache duration(especially 0) usage. + cacheOption CacheOption // Cache option for query statement. + pageCacheOption []CacheOption // Cache option for paging query statement. + hookHandler HookHandler // Hook functions for model hook feature. + unscoped bool // Disables soft deleting features when select/delete operations. + safe bool // If true, it clones and returns a new model object whenever operation done; or else it changes the attribute of current model. + onDuplicate any // onDuplicate is used for on Upsert clause. + onDuplicateEx any // onDuplicateEx is used for excluding some columns on Upsert clause. + onConflict any // onConflict is used for conflict keys on Upsert clause. + tableAliasMap map[string]string // Table alias to true table name, usually used in join statements. + softTimeOption SoftTimeOption // SoftTimeOption is the option to customize soft time feature for Model. + shardingConfig ShardingConfig // ShardingConfig for database/table sharding feature. + shardingValue any // Sharding value for sharding feature. } // ModelHandler is a function that handles given Model and returns a new Model that is custom modified. diff --git a/database/gdb/gdb_model_cache.go b/database/gdb/gdb_model_cache.go index dd7dac7fa4e..3d5fe229a64 100644 --- a/database/gdb/gdb_model_cache.go +++ b/database/gdb/gdb_model_cache.go @@ -50,6 +50,18 @@ func (m *Model) Cache(option CacheOption) *Model { return model } +// PageCache sets the cache feature for pagination queries. It allows to configure +// separate cache options for count query and data query in pagination. +// +// Note that, the cache feature is disabled if the model is performing select statement +// on a transaction. +func (m *Model) PageCache(countOption CacheOption, dataOption CacheOption) *Model { + model := m.getModel() + model.pageCacheOption = []CacheOption{countOption, dataOption} + model.cacheEnabled = true + return model +} + // checkAndRemoveSelectCache checks and removes the cache in insert/update/delete statement if // cache feature is enabled. func (m *Model) checkAndRemoveSelectCache(ctx context.Context) { diff --git a/database/gdb/gdb_model_select.go b/database/gdb/gdb_model_select.go index 00317629513..cad1ae95ba2 100644 --- a/database/gdb/gdb_model_select.go +++ b/database/gdb/gdb_model_select.go @@ -56,6 +56,9 @@ func (m *Model) AllAndCount(useFieldForCount bool) (result Result, totalCount in if !useFieldForCount { countModel.fields = []any{Raw("1")} } + if len(m.pageCacheOption) > 0 { + countModel = countModel.Cache(m.pageCacheOption[0]) + } // Get the total count of records totalCount, err = countModel.Count() @@ -68,8 +71,13 @@ func (m *Model) AllAndCount(useFieldForCount bool) (result Result, totalCount in return } + resultModel := m.Clone() + if len(m.pageCacheOption) > 1 { + resultModel = resultModel.Cache(m.pageCacheOption[1]) + } + // Retrieve all records - result, err = m.doGetAll(m.GetCtx(), SelectTypeDefault, false) + result, err = resultModel.doGetAll(m.GetCtx(), SelectTypeDefault, false) return } @@ -337,7 +345,9 @@ func (m *Model) ScanAndCount(pointer any, totalCount *int, useFieldForCount bool if !useFieldForCount { countModel.fields = []any{Raw("1")} } - + if len(m.pageCacheOption) > 0 { + countModel = countModel.Cache(m.pageCacheOption[0]) + } // Get the total count of records *totalCount, err = countModel.Count() if err != nil { @@ -348,7 +358,11 @@ func (m *Model) ScanAndCount(pointer any, totalCount *int, useFieldForCount bool if *totalCount == 0 { return } - err = m.Scan(pointer) + scanModel := m.Clone() + if len(m.pageCacheOption) > 1 { + scanModel = scanModel.Cache(m.pageCacheOption[1]) + } + err = scanModel.Scan(pointer) return }