Browse Source

refactor sqlmap and sqltemplate

xormplus 8 years ago
parent
commit
85d2f4c840
12 changed files with 1225 additions and 484 deletions
  1. 44 55
      README.md
  2. 2 2
      engine.go
  3. 28 0
      engine_group.go
  4. 2 7
      engineplus.go
  5. 7 7
      fswatcher.go
  6. 37 21
      session_plus.go
  7. 99 74
      sqlmap.go
  8. 55 311
      sqltemplate.go
  9. 314 0
      sqltemplate_default.go
  10. 321 0
      sqltemplate_jet.go
  11. 309 0
      sqltemplate_pongo2.go
  12. 7 7
      sqltemplates_executor.go

+ 44 - 55
README.md

@@ -16,7 +16,7 @@ xorm是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作
 * 使用连写来简化调用
 * 支持使用Id, In, Where, Limit, Join, Having, Table, Sql, Cols等函数和结构体等方式作为条件
 * 支持级联加载Struct
-* 支持类ibatis方式配置SQL语句(支持xml配置文件、json配置文件、pongo2模板和自定义实现配置4种方式)
+* 支持类ibatis方式配置SQL语句(支持xml配置文件、json配置文件,支持[pongo2](https://github.com/flosch/pongo2)、[jet](https://github.com/CloudyKit/jet)、[html/template](https://github.com/golang/go/tree/master/src/html/template)模板和自定义实现配置多种方式)
 * 支持动态SQL功能
 * 支持一次批量混合执行多个CRUD操作,并返回多个结果集
 * 支持数据库查询结果直接返回Json字符串和xml字符串
@@ -76,18 +76,20 @@ if err != nil {
 }
 
 /*--------------------------------------------------------------------------------------------------
-1、使用SetSqlMapRootDir()方法设置SqlMap配置文件总根目录,返回Engine实例本身,如采用sql/xormcfg.ini配置文件中的配置,可直接使用InitSqlMap()初始化
-2、使用SetSqlTemplateRootDir()方法设置SqlTemplate模板配置文件总根目录,返回Engine实例本身,如采用sql/xormcfg.ini配置文件中的配置,可直接使用InitSqlTemplate()初始化
-3、SqlMap配置文件总根目录和SqlTemplate模板配置文件总根目录,可代码指定,也可在配置文件中配置,代码指定优先级高于配置
+1、使用RegisterSqlMap()注册SqlMap配置
+2、RegisterSqlTemplate()方法注册SSqlTemplate模板配置
+3、SqlMap配置文件总根目录和SqlTemplate模板配置文件总根目录可为同一目录
 --------------------------------------------------------------------------------------------------*/
 
-//初始化SqlMap配置,可选功能,如应用中无需使用SqlMap,可无需初始化
-err = engine.SetSqlMapRootDir("./sql/oracle").InitSqlMap()
+//注册SqlMap配置,可选功能,如应用中无需使用SqlMap,可无需初始化
+//此处使用xml格式的配置,配置文件根目录为"./sql/oracle",配置文件后缀为".xml"
+err = x.RegisterSqlMap(xorm.Xml("./sql/oracle", ".xml"))
 if err != nil {
 	t.Fatal(err)
 }
-//初始化动态SQL模板配置,可选功能,如应用中无需使用SqlTemplate,可无需初始化
-err = engine.SetSqlTemplateRootDir("./sql/oracle").InitSqlTemplate(xorm.SqlTemplateOptions{Extension: ".xx"})
+//注册动态SQL模板配置,可选功能,如应用中无需使用SqlTemplate,可无需初始化
+//此处注册动态SQL模板配置,使用Pongo2模板引擎,配置文件根目录为"./sql/oracle",配置文件后缀为".stpl"
+err = x.RegisterSqlTemplate(xorm.Pongo2("./sql/oracle", ".stpl"))
 if err != nil {
 	t.Fatal(err)
 }
@@ -100,9 +102,8 @@ if err != nil {
 
 ```
 
-* <b>db.InitSqlMap()过程</b>
-    * 如使用SetSqlMapRootDir()方法指定SqlMap配置文件总根目录,则InitSqlMap()方法按指定目录遍历SqlMapRootDir所配置的目录及其子目录下的所有xml配置文件(<a href="https://github.com/xormplus/xorm/blob/master/test/sql/oracle/studygolang.xml">配置文件样例</a>)或json配置文件(<a href="https://github.com/xormplus/xorm/blob/master/test/sql/oracle/test.json">配置文件样例</a>)
-    * 如未使用SetSqlMapRootDir()方法指定SqlMap配置文件总根目录,则读取程序所在目下的sql/xormcfg.ini配置文件(<a href="https://github.com/xormplus/xorm/blob/master/test/sql/xormcfg.ini">样例</a>)中的SqlMapRootDir配置项,遍历SqlMapRootDir所配置的目录及其子目录下的所有xml配置文件(<a href="https://github.com/xormplus/xorm/blob/master/test/sql/oracle/studygolang.xml">配置文件样例</a>)或json配置文件(<a href="https://github.com/xormplus/xorm/blob/master/test/sql/oracle/test.json">配置文件样例</a>)
+* <b>db.RegisterSqlMap()过程</b>
+    * 使用RegisterSqlMap()方法指定SqlMap配置文件文件格式,配置文件总根目录,配置文件后缀名,RegisterSqlMap()方法按指定目录遍历所配置的目录及其子目录下的所有xml配置文件(<a href="https://github.com/xormplus/xorm/blob/master/test/sql/oracle/studygolang.xml">配置文件样例</a>)或json配置文件(<a href="https://github.com/xormplus/xorm/blob/master/test/sql/oracle/test.json">配置文件样例</a>)
     * 解析所有配置SqlMap的xml配置文件或json配置文件
     * xml配置文件中sql标签的id属性值作为SqlMap的key,如有重名id,则后加载的覆盖之前加载的配置sql条目
     * json配置文件中key值作为SqlMap的key,如有重名key,则后加载的覆盖之前加载的配置sql条目
@@ -110,10 +111,9 @@ if err != nil {
     * 配置文件中sql配置会读入内存并缓存
     * 由于SqlTemplate模板能完成更多复杂组装和特殊场景需求等强大功能,故SqlMap的xml或json只提供这种极简配置方式,非ibatis的OGNL的表达式实现方式
 
-* <b>db.InitSqlTemplate()过程</b>
-    * 如使用SetSqlTemplateRootDir()方法指定SqlTemplate模板配置文件总根目录,则InitSqlTemplate()方法按指定目录遍历SqlTemplateRootDir所配置的目录及其子目录及其子目录下的所有stpl模板文件(<a href="https://github.com/xormplus/xorm/blob/master/test/sql/oracle/select.example.stpl">模板文件样例</a>)
-    * 如指使用SetSqlTemplateRootDir()方法指定SqlTemplate模板配置文件总根目录,则InitSqlTemplate()方法读取程序所在目下的sql/xormcfg.ini配置文件(<a href="https://github.com/xormplus/xorm/blob/master/test/sql/xormcfg.ini">样例</a>)中的SqlTemplateRootDir配置项,遍历SqlTemplateRootDir所配置的目录及其子目录下的所有stpl模板文件(<a href="https://github.com/xormplus/xorm/blob/master/test/sql/oracle/select.example.stpl">模板文件样例</a>)
-    * 解析stpl模板文件
+* <b>db.RegisterSqlTemplate()过程</b>
+    * 使用RegisterSqlTemplate()方法指定SqlTemplate模板的模板引擎(支持[pongo2](https://github.com/flosch/pongo2)、[jet](https://github.com/CloudyKit/jet)、[html/template](https://github.com/golang/go/tree/master/src/html/template)3种模板引擎,但只能选用一种,不能同时混用),配置文件总根目录,配置文件后缀名,RegisterSqlTemplate()方法按指定目录遍历所配置的目录及其子目录及其子目录下的所有stpl模板文件(<a href="https://github.com/xormplus/xorm/blob/master/test/sql/oracle/select.example.stpl">模板文件样例</a>)
+    * 使用指定模板引擎解析stpl模板文件
     * stpl模板文件名作为SqlTemplate存储的key(不包含目录路径),如有不同路径下出现同名文件,则后加载的覆盖之前加载的配置模板内容
     * stpl模板内容会读入内存并缓存
 
@@ -477,25 +477,17 @@ if err != nil {
 * <b>SqlMap及SqlTemplate相关功能API</b>
 
 ```go
-//设置SqlMap文件总根目录,可代码指定,也可在配置文件中配置,如使用配置文件中的配置则无需调用该方法,代码指定优先级高于配置
-engine.SetSqlMapRootDir()
-//设置SqlTemplate模板配置文件总根目录,可代码指定,也可在配置文件中配置,如使用配置文件中的配置则无需调用该方法,代码指定优先级高于配置
-engine.SetSqlTemplateRootDir()
-
-//初始化加载SqlMap配置文件,默认初始化xml格式内容后缀为".xml",json格式内容后缀为".json",默认初始化容量100
-err := engine.InitSqlMap()
-err := engine.InitSqlTemplate()//初始化加载SqlTemplate配置文件,默认初始化后缀为".stpl",初始化容量100
-
-//SqlMap配置文件和SqlTemplate配置文件后缀不要相同
-//指定SqlMap配置文件xml格式内容后缀为".xx",但配置内容必须为样例的xml格式,如不指定,默认后缀为".xml"
-//指定SqlMap配置文件json格式内容后缀为".json",但配置内容必须为样例的json格式,如不指定,默认后缀为".json"
-//同时还可以指定初始化容量,如不指定,默认初始化容量100
-opt := xorm.SqlMapOptions{Extension: map[string]string{"xml": ".xxx", "json": ".json"}}
-err := engine.InitSqlMap(opt) //按指定SqlMap配置文件xml格式内容后缀为".xxx"初始化,配置文件json格式内容后缀为".json"初始化
-
-//指定SqlTemplate配置文件后缀为".yy",初始化容量200,如不指定,默认后缀为".stpl",初始化容量100
-option := xorm.SqlTemplateOptions{Extension: ".yy", Capacity: 200}
-err = engine.InitSqlTemplate(option) //按指定SqlTemplate配置文件后缀为".yy"初始化
+//注册SqlMap配置,xml格式
+err := engine.RegisterSqlMap(xorm.Xml("./sql/oracle", ".xml"))
+//注册SqlMap配置,json格式
+err := engine.RegisterSqlMap(xorm.Json("./sql/oracle", ".json"))
+//注册SqlTemplate配置,使用Pongo2模板引擎
+err := engine.RegisterSqlTemplate(xorm.Pongo2("./sql/oracle", ".stpl"))
+//注册SqlTemplate配置,使用Jet模板引擎
+err := engine.RegisterSqlTemplate(xorm.Jet("./sql/oracle", ".jet"))
+//注册SqlTemplate配置,使用html/template模板引擎
+err := engine.RegisterSqlTemplate(xorm.Default("./sql/oracle", ".tpl"))
+
 
 //开启SqlMap配置文件和SqlTemplate配置文件更新监控功能,将配置文件更新内容实时更新到内存,如无需要可以不调用该方法
 //该监控模式下,如删除配置文件,内存中不会删除相关配置
@@ -504,8 +496,8 @@ engine.StartFSWatcher()
 engine.StopFSWatcher()
 
 /*------------------------------------------------------------------------------------
-1、以下方法是在没有engine.InitSqlMap()和engine.InitSqlTemplate()初始化相关配置文件的情况下让您在代码中可以轻松的手动管理SqlMap配置及SqlTemplate模板。
-2、engine.InitSqlMap()和engine.InitSqlTemplate()初始化相关配置文件之后也可以使用以下方法灵活的对SqlMap配置及SqlTemplate模板进行管理
+1、以下方法是在没有engine.RegisterSqlMap()和engine.RegisterSqlTemplate()初始化相关配置文件的情况下让您在代码中可以轻松的手动管理SqlMap配置及SqlTemplate模板。
+2、engine.RegisterSqlMap()和engine.RegisterSqlTemplate()初始化相关配置文件之后也可以使用以下方法灵活的对SqlMap配置及SqlTemplate模板进行管理
 3、方便支持您系统中其他初始化配置源,可不依赖于本库的初始化配置方式
 4、可在代码中依据业务场景,动态的添加、更新、删除SqlMap配置及SqlTemplate模板
 5、手工管理的SqlMap配置及SqlTemplate模板,与xorm初始化方法一样会将相关配置缓存,但不会生成相关配置文件
@@ -525,15 +517,15 @@ engine.BatchAddSql(map[key]sql) //批量新增SqlMap配置
 engine.BatchUpdateSql(map[key]sql) //批量更新SqlMap配置
 engine.BatchRemoveSql([]key) //批量删除SqlMap配置
 
-engine.LoadSqlTemplate(filepath) //加载指定文件的SqlTemplate模板
-engine.ReloadSqlTemplate(filepath) //重新加载指定文件的SqlTemplate模板
+engine.SqlTemplate.LoadSqlTemplate(filepath) //加载指定文件的SqlTemplate模板
+engine.SqlTemplate.ReloadSqlTemplate(filepath) //重新加载指定文件的SqlTemplate模板
 
-engine.BatchLoadSqlTemplate([]filepath) //批量加载SqlTemplate模板
-engine.BatchReloadSqlTemplate([]filepath) //批量加载SqlTemplate模板
+engine.SqlTemplate.BatchLoadSqlTemplate([]filepath) //批量加载SqlTemplate模板
+engine.SqlTemplate.BatchReloadSqlTemplate([]filepath) //批量加载SqlTemplate模板
 
-engine.AddSqlTemplate(key, sql) //新增一条SqlTemplate模板,sql为SqlTemplate模板内容字符串
-engine.UpdateSqlTemplate(key, sql) //更新一条SqlTemplate模板,sql为SqlTemplate模板内容字符串
-engine.RemoveSqlTemplate(key) //删除一条SqlTemplate模板
+engine.SqlTemplate.AddSqlTemplate(key, sql) //新增一条SqlTemplate模板,sql为SqlTemplate模板内容字符串
+engine.SqlTemplate.UpdateSqlTemplate(key, sql) //更新一条SqlTemplate模板,sql为SqlTemplate模板内容字符串
+engine.SqlTemplate.RemoveSqlTemplate(key) //删除一条SqlTemplate模板
 
 engine.BatchAddSqlTemplate(map[key]sql) //批量新增SqlTemplate配置,sql为SqlTemplate模板内容字符串
 engine.BatchUpdateSqlTemplate(map[key]sql) //批量更新SqlTemplate配置,sql为SqlTemplate模板内容字符串
@@ -564,7 +556,7 @@ engine.GetSqlMap(...key)
 3、如不传任何参数,调用engine.GetSqlTemplates(),则返回整个内存中当前缓存的所有SqlTemplate配置
 4、engine.GetSqlTemplates()返回类型为map[string]*pongo2.Template,可以方便的实现链式调用pongo2的Execute(),ExecuteBytes(),ExecuteWriter()方法
 */
-engine.GetSqlTemplates(...key)
+engine.SqlTemplate.GetSqlTemplates(...key)
 ```
 
 * <b>SqlMap配置文件及SqlTemplate模板加密存储及解析</b>
@@ -605,18 +597,17 @@ if err != nil {
 	t.Fatal(err)
 }
 
-puk := "sdlfj2_++1111111111"
-enc := new(xorm.TripleDesEncrypt)
-enc.PubKey = puk
+enc := &xorm.AesEncrypt{
+		PubKey: "122334",
+	}
 //如自定义加解密算法,则此处传入的enc为自己实现的加解密算法,后续代码与本示例一致
-cipher := xorm.Cipher(enc)
-opt := xorm.SqlMapOptions{Cipher: cipher}
-err = engine.SetSqlMapRootDir("./sql/3des").InitSqlMap(opt)
+err = x.RegisterSqlMap(xorm.Xml("./sql/aes", ".xml"), enc)
+
 if err != nil {
 	t.Fatal(err)
 }
 //这里也可以new其他加密解密算法,SqlMap配置文件和SqlTemplate模板的加密结算算法可不相同
-err = engine.SetSqlTemplateRootDir("./sql/3des").InitSqlTemplate(xorm.SqlTemplateOptions{Cipher: cipher})
+err = x.RegisterSqlTemplate(xorm.Pongo2("./sql/aes", ".stpl"), enc)
 if err != nil {
 	t.Fatal(err)
 }
@@ -672,14 +663,12 @@ if err != nil {
 enc := new(xorm.RsaEncrypt)
 enc.PubKey = pukeyStr
 enc.DecryptMode = xorm.RSA_PUBKEY_DECRYPT_MODE
-cipher := xorm.Cipher(enc)
-opt := xorm.SqlMapOptions{Cipher: cipher}
-err = engine.SetSqlMapRootDir("./sql/rsa").InitSqlMap(opt)
+err = engine.RegisterSqlMap(xorm.Xml("./sql/rsa", ".xml"), enc)
 if err != nil {
 	t.Fatal(err)
 }
 
-err = engine.SetSqlTemplateRootDir("./sql/rsa").InitSqlTemplate(xorm.SqlTemplateOptions{Cipher: cipher})
+err = engine.RegisterSqlTemplate(xorm.Pongo2("./sql/rsa", ".stpl"), enc)
 if err != nil {
 	t.Fatal(err)
 }

+ 2 - 2
engine.go

@@ -34,8 +34,8 @@ type Engine struct {
 	TableMapper   core.IMapper
 	TagIdentifier string
 	Tables        map[reflect.Type]*core.Table
-	sqlMap        SqlMap
-	sqlTemplate   SqlTemplate
+	SqlMap        SqlMap
+	SqlTemplate   SqlTemplate
 	watcher       *fsnotify.Watcher
 	mutex         *sync.RWMutex
 	Cacher        core.Cacher

+ 28 - 0
engine_group.go

@@ -192,3 +192,31 @@ func (eg *EngineGroup) Slave() *Engine {
 func (eg *EngineGroup) Slaves() []*Engine {
 	return eg.slaves
 }
+
+func (eg *EngineGroup) RegisterSqlTemplate(sqlt SqlTemplate, Cipher ...Cipher) error {
+	err := eg.Engine.RegisterSqlTemplate(sqlt, Cipher...)
+	if err != nil {
+		return err
+	}
+	for i := 0; i < len(eg.slaves); i++ {
+		err = eg.slaves[i].RegisterSqlTemplate(sqlt, Cipher...)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func (eg *EngineGroup) RegisterSqlMap(sqlm SqlM, Cipher ...Cipher) error {
+	err := eg.Engine.RegisterSqlMap(sqlm, Cipher...)
+	if err != nil {
+		return err
+	}
+	for i := 0; i < len(eg.slaves); i++ {
+		err = eg.slaves[i].RegisterSqlMap(sqlm, Cipher...)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}

+ 2 - 7
engineplus.go

@@ -5,12 +5,7 @@ import (
 )
 
 func (engine *Engine) SetSqlMapRootDir(sqlMapRootDir string) *Engine {
-	engine.sqlMap.SqlMapRootDir = sqlMapRootDir
-	return engine
-}
-
-func (engine *Engine) SetSqlTemplateRootDir(sqlTemplateRootDir string) *Engine {
-	engine.sqlTemplate.SqlTemplateRootDir = sqlTemplateRootDir
+	engine.SqlMap.SqlMapRootDir = sqlMapRootDir
 	return engine
 }
 
@@ -18,7 +13,7 @@ func (engine *Engine) SqlMapClient(sqlTagName string, args ...interface{}) *Sess
 	session := engine.NewSession()
 	session.isAutoClose = true
 	session.isSqlFunc = true
-	return session.Sql(engine.sqlMap.Sql[sqlTagName], args...)
+	return session.Sql(engine.SqlMap.Sql[sqlTagName], args...)
 }
 
 func (engine *Engine) SqlTemplateClient(sqlTagName string, args ...interface{}) *Session {

+ 7 - 7
fswatcher.go

@@ -21,14 +21,14 @@ func (engine *Engine) StartFSWatcher() error {
 			select {
 			case event := <-engine.watcher.Events:
 				if event.Op&fsnotify.Write == fsnotify.Write {
-					if strings.HasSuffix(event.Name, engine.sqlTemplate.Extension) {
-						err = engine.reloadSqlTemplate(event.Name)
+					if strings.HasSuffix(event.Name, engine.SqlTemplate.Extension()) {
+						err = engine.ReloadSqlTemplate(event.Name)
 						if err != nil {
 							engine.logger.Error(err)
 						}
 					}
 
-					if strings.HasSuffix(event.Name, engine.sqlMap.Extension["xml"]) || strings.HasSuffix(event.Name, engine.sqlMap.Extension["json"]) {
+					if strings.HasSuffix(event.Name, engine.SqlMap.Extension["xml"]) || strings.HasSuffix(event.Name, engine.SqlMap.Extension["json"]) {
 						err = engine.reloadSqlMap(event.Name)
 						if err != nil {
 							engine.logger.Error(err)
@@ -44,15 +44,15 @@ func (engine *Engine) StartFSWatcher() error {
 		}
 	}()
 
-	if engine.sqlMap.SqlMapRootDir != "" {
-		err = engine.watcher.Add(engine.sqlMap.SqlMapRootDir)
+	if engine.SqlMap.SqlMapRootDir != "" {
+		err = engine.watcher.Add(engine.SqlMap.SqlMapRootDir)
 		if err != nil {
 			return err
 		}
 	}
 
-	if engine.sqlTemplate.SqlTemplateRootDir != "" {
-		err = engine.watcher.Add(engine.sqlTemplate.SqlTemplateRootDir)
+	if engine.SqlTemplate.RootDir() != "" {
+		err = engine.watcher.Add(engine.SqlTemplate.RootDir())
 		if err != nil {
 			return err
 		}

+ 37 - 21
session_plus.go

@@ -15,7 +15,7 @@ import (
 
 	"github.com/Chronokeeper/anyxml"
 	"github.com/xormplus/core"
-	"gopkg.in/flosch/pongo2.v3"
+	//	"gopkg.in/flosch/pongo2.v3"
 )
 
 type ResultBean struct {
@@ -377,35 +377,51 @@ func (resultStructs *ResultStructs) XmlIndent(prefix string, indent string, reco
 }
 
 func (session *Session) SqlMapClient(sqlTagName string, args ...interface{}) *Session {
-	return session.Sql(session.engine.sqlMap.Sql[sqlTagName], args...)
-}
+	return session.Sql(session.engine.SqlMap.Sql[sqlTagName], args...)
+}
+
+//func (session *Session) SqlTemplateClient(sqlTagName string, args ...interface{}) *Session {
+//	session.isSqlFunc = true
+//	if session.engine.sqlTemplate.Template[sqlTagName] == nil {
+//		if len(args) == 0 {
+//			return session.Sql("")
+//		} else {
+//			map1 := args[0].(*map[string]interface{})
+//			return session.Sql("", map1)
+//		}
+//	}
+
+//	if len(args) == 0 {
+//		parmap := &pongo2.Context{"1": 1}
+//		sql, err := session.engine.sqlTemplate.Template[sqlTagName].Execute(*parmap)
+//		if err != nil {
+//			session.engine.logger.Error(err)
+
+//		}
+//		return session.Sql(sql)
+//	} else {
+//		map1 := args[0].(*map[string]interface{})
+//		sql, err := session.engine.sqlTemplate.Template[sqlTagName].Execute(*map1)
+//		if err != nil {
+//			session.engine.logger.Error(err)
+
+//		}
+//		return session.Sql(sql, map1)
+//	}
+
+//}
 
 func (session *Session) SqlTemplateClient(sqlTagName string, args ...interface{}) *Session {
 	session.isSqlFunc = true
-	if session.engine.sqlTemplate.Template[sqlTagName] == nil {
-		if len(args) == 0 {
-			return session.Sql("")
-		} else {
-			map1 := args[0].(*map[string]interface{})
-			return session.Sql("", map1)
-		}
+	sql, err := session.engine.SqlTemplate.Execute(sqlTagName, args...)
+	if err != nil {
+		session.engine.logger.Error(err)
 	}
 
 	if len(args) == 0 {
-		parmap := &pongo2.Context{"1": 1}
-		sql, err := session.engine.sqlTemplate.Template[sqlTagName].Execute(*parmap)
-		if err != nil {
-			session.engine.logger.Error(err)
-
-		}
 		return session.Sql(sql)
 	} else {
 		map1 := args[0].(*map[string]interface{})
-		sql, err := session.engine.sqlTemplate.Template[sqlTagName].Execute(*map1)
-		if err != nil {
-			session.engine.logger.Error(err)
-
-		}
 		return session.Sql(sql, map1)
 	}
 

+ 99 - 74
sqlmap.go

@@ -3,13 +3,12 @@ package xorm
 import (
 	"encoding/json"
 	"encoding/xml"
+	"fmt"
 	"io/ioutil"
 
 	"os"
 	"path/filepath"
 	"strings"
-
-	"github.com/Unknwon/goconfig"
 )
 
 type SqlMap struct {
@@ -20,12 +19,6 @@ type SqlMap struct {
 	Cipher        Cipher
 }
 
-type SqlMapOptions struct {
-	Capacity  uint
-	Extension map[string]string
-	Cipher    Cipher
-}
-
 type Result struct {
 	Sql []Sql `xml:"sql"`
 }
@@ -36,11 +29,11 @@ type Sql struct {
 }
 
 func (engine *Engine) SetSqlMapCipher(cipher Cipher) {
-	engine.sqlMap.Cipher = cipher
+	engine.SqlMap.Cipher = cipher
 }
 
 func (engine *Engine) ClearSqlMapCipher() {
-	engine.sqlMap.Cipher = nil
+	engine.SqlMap.Cipher = nil
 }
 
 func (sqlMap *SqlMap) checkNilAndInit() {
@@ -54,42 +47,74 @@ func (sqlMap *SqlMap) checkNilAndInit() {
 	}
 }
 
-func (engine *Engine) InitSqlMap(options ...SqlMapOptions) error {
-	var opt SqlMapOptions
+type SqlM interface {
+	RootDir() string
+	Extension() string
+}
+
+type XmlSqlMap struct {
+	sqlMapRootDir string
+	extension     string
+}
+
+type JsonSqlMap struct {
+	sqlMapRootDir string
+	extension     string
+}
 
-	if len(options) > 0 {
-		opt = options[0]
+func Xml(directory, extension string) *XmlSqlMap {
+	return &XmlSqlMap{
+		sqlMapRootDir: directory,
+		extension:     extension,
 	}
+}
 
-	if len(opt.Extension) == 0 {
-		opt.Extension = map[string]string{"xml": ".xml", "json": ".json"}
-	} else {
-		if opt.Extension["xml"] == "" || len(opt.Extension["xml"]) == 0 {
-			opt.Extension["xml"] = ".xml"
-		}
-		if opt.Extension["json"] == "" || len(opt.Extension["json"]) == 0 {
-			opt.Extension["json"] = ".json"
-		}
+func Json(directory, extension string) *JsonSqlMap {
+	return &JsonSqlMap{
+		sqlMapRootDir: directory,
+		extension:     extension,
 	}
+}
 
-	engine.sqlMap.Extension = opt.Extension
-	engine.sqlMap.Capacity = opt.Capacity
+func (sqlMap *XmlSqlMap) RootDir() string {
+	return sqlMap.sqlMapRootDir
+}
 
-	engine.sqlMap.Cipher = opt.Cipher
+func (sqlMap *JsonSqlMap) RootDir() string {
+	return sqlMap.sqlMapRootDir
+}
 
-	var err error
-	if engine.sqlMap.SqlMapRootDir == "" {
-		cfg, err := goconfig.LoadConfigFile("./sql/xormcfg.ini")
-		if err != nil {
-			return err
+func (sqlMap *XmlSqlMap) Extension() string {
+	return sqlMap.extension
+}
+
+func (sqlMap *JsonSqlMap) Extension() string {
+	return sqlMap.extension
+}
+
+func (engine *Engine) RegisterSqlMap(sqlm SqlM, Cipher ...Cipher) error {
+	switch sqlm.(type) {
+	case *XmlSqlMap:
+		if len(engine.SqlMap.Extension) == 0 {
+			engine.SqlMap.Extension = map[string]string{"xml": ".xml", "json": ".json"}
 		}
-		engine.sqlMap.SqlMapRootDir, err = cfg.GetValue("", "SqlMapRootDir")
-		if err != nil {
-			return err
+		engine.SqlMap.Extension["xml"] = sqlm.Extension()
+	case *JsonSqlMap:
+		if len(engine.SqlMap.Extension) == 0 {
+			engine.SqlMap.Extension = map[string]string{"xml": ".xml", "json": ".json"}
 		}
+		engine.SqlMap.Extension["json"] = sqlm.Extension()
+	default:
+		return ErrParamsType
+	}
+
+	if len(Cipher) > 0 {
+		engine.SqlMap.Cipher = Cipher[0]
 	}
 
-	err = filepath.Walk(engine.sqlMap.SqlMapRootDir, engine.sqlMap.walkFunc)
+	engine.SqlMap.SqlMapRootDir = sqlm.RootDir()
+
+	err := filepath.Walk(engine.SqlMap.SqlMapRootDir, engine.SqlMap.walkFunc)
 	if err != nil {
 		return err
 	}
@@ -99,18 +124,18 @@ func (engine *Engine) InitSqlMap(options ...SqlMapOptions) error {
 
 func (engine *Engine) LoadSqlMap(filepath string) error {
 
-	if len(engine.sqlMap.Extension) == 0 {
-		engine.sqlMap.Extension = map[string]string{"xml": ".xml", "json": ".json"}
+	if len(engine.SqlMap.Extension) == 0 {
+		engine.SqlMap.Extension = map[string]string{"xml": ".xml", "json": ".json"}
 	} else {
-		if engine.sqlMap.Extension["xml"] == "" || len(engine.sqlMap.Extension["xml"]) == 0 {
-			engine.sqlMap.Extension["xml"] = ".xml"
+		if engine.SqlMap.Extension["xml"] == "" || len(engine.SqlMap.Extension["xml"]) == 0 {
+			engine.SqlMap.Extension["xml"] = ".xml"
 		}
-		if engine.sqlMap.Extension["json"] == "" || len(engine.sqlMap.Extension["json"]) == 0 {
-			engine.sqlMap.Extension["json"] = ".json"
+		if engine.SqlMap.Extension["json"] == "" || len(engine.SqlMap.Extension["json"]) == 0 {
+			engine.SqlMap.Extension["json"] = ".json"
 		}
 	}
 
-	if strings.HasSuffix(filepath, engine.sqlMap.Extension["xml"]) || strings.HasSuffix(filepath, engine.sqlMap.Extension["json"]) {
+	if strings.HasSuffix(filepath, engine.SqlMap.Extension["xml"]) || strings.HasSuffix(filepath, engine.SqlMap.Extension["json"]) {
 		err := engine.loadSqlMap(filepath)
 		if err != nil {
 			return err
@@ -121,19 +146,19 @@ func (engine *Engine) LoadSqlMap(filepath string) error {
 }
 
 func (engine *Engine) BatchLoadSqlMap(filepathSlice []string) error {
-	if len(engine.sqlMap.Extension) == 0 {
-		engine.sqlMap.Extension = map[string]string{"xml": ".xml", "json": ".json"}
+	if len(engine.SqlMap.Extension) == 0 {
+		engine.SqlMap.Extension = map[string]string{"xml": ".xml", "json": ".json"}
 	} else {
-		if engine.sqlMap.Extension["xml"] == "" || len(engine.sqlMap.Extension["xml"]) == 0 {
-			engine.sqlMap.Extension["xml"] = ".xml"
+		if engine.SqlMap.Extension["xml"] == "" || len(engine.SqlMap.Extension["xml"]) == 0 {
+			engine.SqlMap.Extension["xml"] = ".xml"
 		}
-		if engine.sqlMap.Extension["json"] == "" || len(engine.sqlMap.Extension["json"]) == 0 {
-			engine.sqlMap.Extension["json"] = ".json"
+		if engine.SqlMap.Extension["json"] == "" || len(engine.SqlMap.Extension["json"]) == 0 {
+			engine.SqlMap.Extension["json"] = ".json"
 		}
 	}
 
 	for _, filepath := range filepathSlice {
-		if strings.HasSuffix(filepath, engine.sqlMap.Extension["xml"]) || strings.HasSuffix(filepath, engine.sqlMap.Extension["json"]) {
+		if strings.HasSuffix(filepath, engine.SqlMap.Extension["xml"]) || strings.HasSuffix(filepath, engine.SqlMap.Extension["json"]) {
 			err := engine.loadSqlMap(filepath)
 			if err != nil {
 				return err
@@ -145,18 +170,18 @@ func (engine *Engine) BatchLoadSqlMap(filepathSlice []string) error {
 }
 
 func (engine *Engine) ReloadSqlMap(filepath string) error {
-	if len(engine.sqlMap.Extension) == 0 {
-		engine.sqlMap.Extension = map[string]string{"xml": ".xml", "json": ".json"}
+	if len(engine.SqlMap.Extension) == 0 {
+		engine.SqlMap.Extension = map[string]string{"xml": ".xml", "json": ".json"}
 	} else {
-		if engine.sqlMap.Extension["xml"] == "" || len(engine.sqlMap.Extension["xml"]) == 0 {
-			engine.sqlMap.Extension["xml"] = ".xml"
+		if engine.SqlMap.Extension["xml"] == "" || len(engine.SqlMap.Extension["xml"]) == 0 {
+			engine.SqlMap.Extension["xml"] = ".xml"
 		}
-		if engine.sqlMap.Extension["json"] == "" || len(engine.sqlMap.Extension["json"]) == 0 {
-			engine.sqlMap.Extension["json"] = ".json"
+		if engine.SqlMap.Extension["json"] == "" || len(engine.SqlMap.Extension["json"]) == 0 {
+			engine.SqlMap.Extension["json"] = ".json"
 		}
 	}
 
-	if strings.HasSuffix(filepath, engine.sqlMap.Extension["xml"]) || strings.HasSuffix(filepath, engine.sqlMap.Extension["json"]) {
+	if strings.HasSuffix(filepath, engine.SqlMap.Extension["xml"]) || strings.HasSuffix(filepath, engine.SqlMap.Extension["json"]) {
 		err := engine.reloadSqlMap(filepath)
 		if err != nil {
 			return err
@@ -167,19 +192,19 @@ func (engine *Engine) ReloadSqlMap(filepath string) error {
 }
 
 func (engine *Engine) BatchReloadSqlMap(filepathSlice []string) error {
-	if len(engine.sqlMap.Extension) == 0 {
-		engine.sqlMap.Extension = map[string]string{"xml": ".xml", "json": ".json"}
+	if len(engine.SqlMap.Extension) == 0 {
+		engine.SqlMap.Extension = map[string]string{"xml": ".xml", "json": ".json"}
 	} else {
-		if engine.sqlMap.Extension["xml"] == "" || len(engine.sqlMap.Extension["xml"]) == 0 {
-			engine.sqlMap.Extension["xml"] = ".xml"
+		if engine.SqlMap.Extension["xml"] == "" || len(engine.SqlMap.Extension["xml"]) == 0 {
+			engine.SqlMap.Extension["xml"] = ".xml"
 		}
-		if engine.sqlMap.Extension["json"] == "" || len(engine.sqlMap.Extension["json"]) == 0 {
-			engine.sqlMap.Extension["json"] = ".json"
+		if engine.SqlMap.Extension["json"] == "" || len(engine.SqlMap.Extension["json"]) == 0 {
+			engine.SqlMap.Extension["json"] = ".json"
 		}
 	}
 
 	for _, filepath := range filepathSlice {
-		if strings.HasSuffix(filepath, engine.sqlMap.Extension["xml"]) || strings.HasSuffix(filepath, engine.sqlMap.Extension["json"]) {
+		if strings.HasSuffix(filepath, engine.SqlMap.Extension["xml"]) || strings.HasSuffix(filepath, engine.SqlMap.Extension["json"]) {
 			err := engine.loadSqlMap(filepath)
 			if err != nil {
 				return err
@@ -201,7 +226,7 @@ func (engine *Engine) loadSqlMap(filepath string) error {
 		return nil
 	}
 
-	err = engine.sqlMap.paresSql(filepath)
+	err = engine.SqlMap.paresSql(filepath)
 	if err != nil {
 		return err
 	}
@@ -219,7 +244,7 @@ func (engine *Engine) reloadSqlMap(filepath string) error {
 	if info.IsDir() {
 		return nil
 	}
-	err = engine.sqlMap.paresSql(filepath)
+	err = engine.SqlMap.paresSql(filepath)
 	if err != nil {
 		return err
 	}
@@ -249,7 +274,7 @@ func (sqlMap *SqlMap) walkFunc(path string, info os.FileInfo, err error) error {
 func (sqlMap *SqlMap) paresSql(filepath string) error {
 
 	content, err := ioutil.ReadFile(filepath)
-
+	fmt.Println("filepath:", filepath)
 	if err != nil {
 		return err
 	}
@@ -295,7 +320,7 @@ func (sqlMap *SqlMap) paresSql(filepath string) error {
 }
 
 func (engine *Engine) AddSql(key string, sql string) {
-	engine.sqlMap.addSql(key, sql)
+	engine.SqlMap.addSql(key, sql)
 }
 
 func (sqlMap *SqlMap) addSql(key string, sql string) {
@@ -304,7 +329,7 @@ func (sqlMap *SqlMap) addSql(key string, sql string) {
 }
 
 func (engine *Engine) UpdateSql(key string, sql string) {
-	engine.sqlMap.updateSql(key, sql)
+	engine.SqlMap.updateSql(key, sql)
 }
 
 func (sqlMap *SqlMap) updateSql(key string, sql string) {
@@ -313,7 +338,7 @@ func (sqlMap *SqlMap) updateSql(key string, sql string) {
 }
 
 func (engine *Engine) RemoveSql(key string) {
-	engine.sqlMap.removeSql(key)
+	engine.SqlMap.removeSql(key)
 }
 
 func (sqlMap *SqlMap) removeSql(key string) {
@@ -322,7 +347,7 @@ func (sqlMap *SqlMap) removeSql(key string) {
 }
 
 func (engine *Engine) BatchAddSql(sqlStrMap map[string]string) {
-	engine.sqlMap.batchAddSql(sqlStrMap)
+	engine.SqlMap.batchAddSql(sqlStrMap)
 }
 
 func (sqlMap *SqlMap) batchAddSql(sqlStrMap map[string]string) {
@@ -333,7 +358,7 @@ func (sqlMap *SqlMap) batchAddSql(sqlStrMap map[string]string) {
 }
 
 func (engine *Engine) BatchUpdateSql(sqlStrMap map[string]string) {
-	engine.sqlMap.batchUpdateSql(sqlStrMap)
+	engine.SqlMap.batchUpdateSql(sqlStrMap)
 }
 
 func (sqlMap *SqlMap) batchUpdateSql(sqlStrMap map[string]string) {
@@ -344,7 +369,7 @@ func (sqlMap *SqlMap) batchUpdateSql(sqlStrMap map[string]string) {
 }
 
 func (engine *Engine) BatchRemoveSql(key []string) {
-	engine.sqlMap.batchRemoveSql(key)
+	engine.SqlMap.batchRemoveSql(key)
 }
 
 func (sqlMap *SqlMap) batchRemoveSql(key []string) {
@@ -355,7 +380,7 @@ func (sqlMap *SqlMap) batchRemoveSql(key []string) {
 }
 
 func (engine *Engine) GetSql(key string) string {
-	return engine.sqlMap.getSql(key)
+	return engine.SqlMap.getSql(key)
 }
 
 func (sqlMap *SqlMap) getSql(key string) string {
@@ -363,7 +388,7 @@ func (sqlMap *SqlMap) getSql(key string) string {
 }
 
 func (engine *Engine) GetSqlMap(keys ...interface{}) map[string]string {
-	return engine.sqlMap.getSqlMap(keys...)
+	return engine.SqlMap.getSqlMap(keys...)
 }
 
 func (sqlMap *SqlMap) getSqlMap(keys ...interface{}) map[string]string {

+ 55 - 311
sqltemplate.go

@@ -1,75 +1,67 @@
 package xorm
 
 import (
-	"io/ioutil"
+	"html/template"
 	"os"
 	"path/filepath"
-	"strings"
 
-	"github.com/Unknwon/goconfig"
+	"github.com/CloudyKit/jet"
 	"gopkg.in/flosch/pongo2.v3"
 )
 
-type SqlTemplate struct {
-	SqlTemplateRootDir string
-	Template           map[string]*pongo2.Template
-	Extension          string
-	Capacity           uint
-	Cipher             Cipher
+type SqlTemplate interface {
+	WalkFunc(path string, info os.FileInfo, err error) error
+	paresSqlTemplate(filename string, filepath string) error
+	ReadTemplate(filepath string) ([]byte, error)
+	Execute(key string, args ...interface{}) (string, error)
+	RootDir() string
+	Extension() string
+	SetSqlTemplateCipher(cipher Cipher)
+	LoadSqlTemplate(filepath string) error
+	BatchLoadSqlTemplate(filepathSlice []string) error
+	ReloadSqlTemplate(filepath string) error
+	BatchReloadSqlTemplate(filepathSlice []string) error
+	AddSqlTemplate(key string, sqlTemplateStr string) error
+	UpdateSqlTemplate(key string, sqlTemplateStr string) error
+	RemoveSqlTemplate(key string)
+	BatchAddSqlTemplate(key string, sqlTemplateStrMap map[string]string) error
+	BatchUpdateSqlTemplate(key string, sqlTemplateStrMap map[string]string) error
+	BatchRemoveSqlTemplate(key []string)
 }
 
-type SqlTemplateOptions struct {
-	Capacity  uint
-	Extension string
-	Cipher    Cipher
-}
-
-func (engine *Engine) SetSqlTemplateCipher(cipher Cipher) {
-	engine.sqlTemplate.Cipher = cipher
-}
-
-func (engine *Engine) ClearSqlTemplateCipher() {
-	engine.sqlTemplate.Cipher = nil
-}
-
-func (sqlTemplate *SqlTemplate) checkNilAndInit() {
-	if sqlTemplate.Template == nil {
-		if sqlTemplate.Capacity == 0 {
-			sqlTemplate.Template = make(map[string]*pongo2.Template, 100)
-		} else {
-			sqlTemplate.Template = make(map[string]*pongo2.Template, sqlTemplate.Capacity)
-		}
+func Pongo2(directory, extension string) *Pongo2Template {
+	template := make(map[string]*pongo2.Template, 100)
+	return &Pongo2Template{
+		SqlTemplateRootDir: directory,
+		extension:          extension,
+		Template:           template,
 	}
 }
 
-func (engine *Engine) InitSqlTemplate(options ...SqlTemplateOptions) error {
-	var opt SqlTemplateOptions
-
-	if len(options) > 0 {
-		opt = options[0]
+func Default(directory, extension string) *HTMLTemplate {
+	template := make(map[string]*template.Template, 100)
+	return &HTMLTemplate{
+		SqlTemplateRootDir: directory,
+		extension:          extension,
+		Template:           template,
 	}
+}
 
-	if len(opt.Extension) == 0 {
-		opt.Extension = ".stpl"
+func Jet(directory, extension string) *JetTemplate {
+	template := make(map[string]*jet.Template, 100)
+	return &JetTemplate{
+		SqlTemplateRootDir: directory,
+		extension:          extension,
+		Template:           template,
 	}
-	engine.sqlTemplate.Extension = opt.Extension
-	engine.sqlTemplate.Capacity = opt.Capacity
-
-	engine.sqlTemplate.Cipher = opt.Cipher
+}
 
-	var err error
-	if engine.sqlTemplate.SqlTemplateRootDir == "" {
-		cfg, err := goconfig.LoadConfigFile("./sql/xormcfg.ini")
-		if err != nil {
-			return err
-		}
-		engine.sqlTemplate.SqlTemplateRootDir, err = cfg.GetValue("", "SqlTemplateRootDir")
-		if err != nil {
-			return err
-		}
+func (engine *Engine) RegisterSqlTemplate(sqlt SqlTemplate, Cipher ...Cipher) error {
+	engine.SqlTemplate = sqlt
+	if len(Cipher) > 0 {
+		engine.SqlTemplate.SetSqlTemplateCipher(Cipher[0])
 	}
-
-	err = filepath.Walk(engine.sqlTemplate.SqlTemplateRootDir, engine.sqlTemplate.walkFunc)
+	err := filepath.Walk(engine.SqlTemplate.RootDir(), engine.SqlTemplate.WalkFunc)
 	if err != nil {
 		return err
 	}
@@ -78,291 +70,43 @@ func (engine *Engine) InitSqlTemplate(options ...SqlTemplateOptions) error {
 }
 
 func (engine *Engine) LoadSqlTemplate(filepath string) error {
-	if len(engine.sqlTemplate.Extension) == 0 {
-		engine.sqlTemplate.Extension = ".stpl"
-	}
-	if strings.HasSuffix(filepath, engine.sqlTemplate.Extension) {
-		err := engine.loadSqlTemplate(filepath)
-		if err != nil {
-			return err
-		}
-	}
-
-	return nil
+	return engine.SqlTemplate.LoadSqlTemplate(filepath)
 }
 
 func (engine *Engine) BatchLoadSqlTemplate(filepathSlice []string) error {
-	if len(engine.sqlTemplate.Extension) == 0 {
-		engine.sqlTemplate.Extension = ".stpl"
-	}
-	for _, filepath := range filepathSlice {
-		if strings.HasSuffix(filepath, engine.sqlTemplate.Extension) {
-			err := engine.loadSqlTemplate(filepath)
-			if err != nil {
-				return err
-			}
-		}
-	}
-
-	return nil
+	return engine.SqlTemplate.BatchLoadSqlTemplate(filepathSlice)
 }
 
 func (engine *Engine) ReloadSqlTemplate(filepath string) error {
-	if len(engine.sqlTemplate.Extension) == 0 {
-		engine.sqlTemplate.Extension = ".stpl"
-	}
-	if strings.HasSuffix(filepath, engine.sqlTemplate.Extension) {
-		err := engine.reloadSqlTemplate(filepath)
-		if err != nil {
-			return err
-		}
-	}
-
-	return nil
+	return engine.SqlTemplate.ReloadSqlTemplate(filepath)
 }
 
 func (engine *Engine) BatchReloadSqlTemplate(filepathSlice []string) error {
-	if len(engine.sqlTemplate.Extension) == 0 {
-		engine.sqlTemplate.Extension = ".stpl"
-	}
-	for _, filepath := range filepathSlice {
-		if strings.HasSuffix(filepath, engine.sqlTemplate.Extension) {
-			err := engine.loadSqlTemplate(filepath)
-			if err != nil {
-				return err
-			}
-		}
-	}
-
-	return nil
-}
-
-func (engine *Engine) loadSqlTemplate(filepath string) error {
-	info, err := os.Lstat(filepath)
-	if err != nil {
-		return err
-	}
-
-	if info.IsDir() {
-		return nil
-	}
-
-	err = engine.sqlTemplate.paresSqlTemplate(info.Name(), filepath)
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
-
-func (engine *Engine) reloadSqlTemplate(filepath string) error {
-	info, err := os.Lstat(filepath)
-	if err != nil {
-		return err
-	}
-
-	if info.IsDir() {
-		return nil
-	}
-
-	err = engine.sqlTemplate.paresSqlTemplate(info.Name(), filepath)
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
-
-func (sqlTemplate *SqlTemplate) walkFunc(path string, info os.FileInfo, err error) error {
-	if err != nil {
-		return err
-	}
-
-	if info.IsDir() {
-		return nil
-	}
-
-	if strings.HasSuffix(path, sqlTemplate.Extension) {
-		err = sqlTemplate.paresSqlTemplate(info.Name(), path)
-		if err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-func (sqlTemplate *SqlTemplate) paresSqlTemplate(filename string, filepath string) error {
-	var template *pongo2.Template
-	var err error
-	var content []byte
-
-	if sqlTemplate.Cipher == nil {
-		template, err = pongo2.FromFile(filepath)
-		if err != nil {
-			return err
-		}
-	} else {
-		content, err = ioutil.ReadFile(filepath)
-
-		if err != nil {
-			return err
-		}
-		content, err = sqlTemplate.Cipher.Decrypt(content)
-		if err != nil {
-			return err
-		}
-		template, err = pongo2.FromString(string(content))
-		if err != nil {
-			return err
-		}
-	}
-
-	sqlTemplate.checkNilAndInit()
-	sqlTemplate.Template[filename] = template
-
-	return nil
+	return engine.SqlTemplate.BatchReloadSqlTemplate(filepathSlice)
 }
 
 func (engine *Engine) AddSqlTemplate(key string, sqlTemplateStr string) error {
-	return engine.sqlTemplate.addSqlTemplate(key, sqlTemplateStr)
-}
-
-func (sqlTemplate *SqlTemplate) addSqlTemplate(key string, sqlTemplateStr string) error {
-
-	template, err := pongo2.FromString(sqlTemplateStr)
-	if err != nil {
-		return err
-	}
-
-	sqlTemplate.checkNilAndInit()
-	sqlTemplate.Template[key] = template
-
-	return nil
-
+	return engine.SqlTemplate.AddSqlTemplate(key, sqlTemplateStr)
 }
 
 func (engine *Engine) UpdateSqlTemplate(key string, sqlTemplateStr string) error {
-	return engine.sqlTemplate.updateSqlTemplate(key, sqlTemplateStr)
-}
-
-func (sqlTemplate *SqlTemplate) updateSqlTemplate(key string, sqlTemplateStr string) error {
-
-	template, err := pongo2.FromString(sqlTemplateStr)
-	if err != nil {
-		return err
-	}
-	sqlTemplate.checkNilAndInit()
-	sqlTemplate.Template[key] = template
-
-	return nil
-
+	return engine.SqlTemplate.UpdateSqlTemplate(key, sqlTemplateStr)
 }
 
 func (engine *Engine) RemoveSqlTemplate(key string) {
-	engine.sqlTemplate.removeSqlTemplate(key)
-}
-
-func (sqlTemplate *SqlTemplate) removeSqlTemplate(key string) {
-	sqlTemplate.checkNilAndInit()
-	delete(sqlTemplate.Template, key)
+	engine.SqlTemplate.RemoveSqlTemplate(key)
 }
 
 func (engine *Engine) BatchAddSqlTemplate(key string, sqlTemplateStrMap map[string]string) error {
-	return engine.sqlTemplate.batchAddSqlTemplate(key, sqlTemplateStrMap)
-
-}
-
-func (sqlTemplate *SqlTemplate) batchAddSqlTemplate(key string, sqlTemplateStrMap map[string]string) error {
-	sqlTemplate.checkNilAndInit()
-	for k, v := range sqlTemplateStrMap {
-		template, err := pongo2.FromString(v)
-		if err != nil {
-			return err
-		}
-
-		sqlTemplate.Template[k] = template
-	}
-
-	return nil
+	return engine.SqlTemplate.BatchAddSqlTemplate(key, sqlTemplateStrMap)
 
 }
 
 func (engine *Engine) BatchUpdateSqlTemplate(key string, sqlTemplateStrMap map[string]string) error {
-	return engine.sqlTemplate.batchAddSqlTemplate(key, sqlTemplateStrMap)
-
-}
-
-func (sqlTemplate *SqlTemplate) batchUpdateSqlTemplate(key string, sqlTemplateStrMap map[string]string) error {
-	sqlTemplate.checkNilAndInit()
-	for k, v := range sqlTemplateStrMap {
-		template, err := pongo2.FromString(v)
-		if err != nil {
-			return err
-		}
-
-		sqlTemplate.Template[k] = template
-	}
-
-	return nil
+	return engine.SqlTemplate.BatchUpdateSqlTemplate(key, sqlTemplateStrMap)
 
 }
 
 func (engine *Engine) BatchRemoveSqlTemplate(key []string) {
-	engine.sqlTemplate.batchRemoveSqlTemplate(key)
-}
-
-func (sqlTemplate *SqlTemplate) batchRemoveSqlTemplate(key []string) {
-	sqlTemplate.checkNilAndInit()
-	for _, v := range key {
-		delete(sqlTemplate.Template, v)
-	}
-}
-
-func (engine *Engine) GetSqlTemplate(key string) *pongo2.Template {
-	return engine.sqlTemplate.getSqlTemplate(key)
-}
-
-func (sqlTemplate *SqlTemplate) getSqlTemplate(key string) *pongo2.Template {
-	return sqlTemplate.Template[key]
-}
-
-func (engine *Engine) GetSqlTemplates(keys ...interface{}) map[string]*pongo2.Template {
-	return engine.sqlTemplate.getSqlTemplates(keys...)
-}
-
-func (sqlTemplate *SqlTemplate) getSqlTemplates(keys ...interface{}) map[string]*pongo2.Template {
-
-	var resultSqlTemplates map[string]*pongo2.Template
-	i := len(keys)
-	if i == 0 {
-		return sqlTemplate.Template
-	}
-
-	if i == 1 {
-		switch keys[0].(type) {
-		case string:
-			resultSqlTemplates = make(map[string]*pongo2.Template, 1)
-		case []string:
-			ks := keys[0].([]string)
-			n := len(ks)
-			resultSqlTemplates = make(map[string]*pongo2.Template, n)
-		}
-	} else {
-		resultSqlTemplates = make(map[string]*pongo2.Template, i)
-	}
-
-	for k, _ := range keys {
-		switch keys[k].(type) {
-		case string:
-			key := keys[k].(string)
-			resultSqlTemplates[key] = sqlTemplate.Template[key]
-		case []string:
-			ks := keys[k].([]string)
-			for _, v := range ks {
-				resultSqlTemplates[v] = sqlTemplate.Template[v]
-			}
-		}
-	}
-
-	return resultSqlTemplates
+	engine.SqlTemplate.BatchRemoveSqlTemplate(key)
 }

+ 314 - 0
sqltemplate_default.go

@@ -0,0 +1,314 @@
+package xorm
+
+import (
+	"bytes"
+	"io/ioutil"
+	"os"
+	"strings"
+
+	"html/template"
+)
+
+type HTMLTemplate struct {
+	SqlTemplateRootDir string
+	Template           map[string]*template.Template
+	extension          string
+	Capacity           uint
+	Cipher             Cipher
+	Type               int
+}
+
+func (sqlTemplate *HTMLTemplate) RootDir() string {
+	return sqlTemplate.SqlTemplateRootDir
+}
+
+func (sqlTemplate *HTMLTemplate) Extension() string {
+	return sqlTemplate.extension
+}
+
+func (sqlTemplate *HTMLTemplate) SetSqlTemplateCipher(cipher Cipher) {
+	sqlTemplate.Cipher = cipher
+}
+
+func (sqlTemplate *HTMLTemplate) WalkFunc(path string, info os.FileInfo, err error) error {
+	if err != nil {
+		return err
+	}
+
+	if info.IsDir() {
+		return nil
+	}
+
+	if strings.HasSuffix(path, sqlTemplate.extension) {
+		err = sqlTemplate.paresSqlTemplate(info.Name(), path)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func (sqlTemplate *HTMLTemplate) paresSqlTemplate(filename string, filepath string) error {
+	var sqlt *template.Template
+	var err error
+	var content []byte
+
+	if sqlTemplate.Cipher == nil {
+		sqlt = template.Must(template.ParseFiles(filepath))
+	} else {
+		content, err = sqlTemplate.ReadTemplate(filepath)
+		if err != nil {
+			return err
+		}
+		sqlt = template.Must(template.New(filename).Parse(string(content)))
+	}
+
+	sqlTemplate.checkNilAndInit()
+	sqlTemplate.Template[filename] = sqlt
+	return nil
+
+}
+
+func (sqlTemplate *HTMLTemplate) ReadTemplate(filepath string) ([]byte, error) {
+	content, err := ioutil.ReadFile(filepath)
+	if err != nil {
+		return nil, err
+	}
+	content, err = sqlTemplate.Cipher.Decrypt(content)
+	if err != nil {
+		return nil, err
+	}
+	return content, nil
+}
+
+//-------------------------------------------------------------------------------------------------------------
+func (sqlTemplate *HTMLTemplate) LoadSqlTemplate(filepath string) error {
+
+	if strings.HasSuffix(filepath, sqlTemplate.extension) {
+		err := sqlTemplate.loadSqlTemplate(filepath)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func (sqlTemplate *HTMLTemplate) BatchLoadSqlTemplate(filepathSlice []string) error {
+
+	for _, filepath := range filepathSlice {
+		if strings.HasSuffix(filepath, sqlTemplate.extension) {
+			err := sqlTemplate.loadSqlTemplate(filepath)
+			if err != nil {
+				return err
+			}
+		}
+	}
+
+	return nil
+}
+
+func (sqlTemplate *HTMLTemplate) ReloadSqlTemplate(filepath string) error {
+
+	if strings.HasSuffix(filepath, sqlTemplate.extension) {
+		err := sqlTemplate.reloadSqlTemplate(filepath)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func (sqlTemplate *HTMLTemplate) BatchReloadSqlTemplate(filepathSlice []string) error {
+
+	for _, filepath := range filepathSlice {
+		if strings.HasSuffix(filepath, sqlTemplate.extension) {
+			err := sqlTemplate.loadSqlTemplate(filepath)
+			if err != nil {
+				return err
+			}
+		}
+	}
+
+	return nil
+}
+
+func (sqlTemplate *HTMLTemplate) loadSqlTemplate(filepath string) error {
+	info, err := os.Lstat(filepath)
+	if err != nil {
+		return err
+	}
+
+	if info.IsDir() {
+		return nil
+	}
+
+	err = sqlTemplate.paresSqlTemplate(info.Name(), filepath)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (sqlTemplate *HTMLTemplate) reloadSqlTemplate(filepath string) error {
+	info, err := os.Lstat(filepath)
+	if err != nil {
+		return err
+	}
+
+	if info.IsDir() {
+		return nil
+	}
+
+	err = sqlTemplate.paresSqlTemplate(info.Name(), filepath)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (sqlTemplate *HTMLTemplate) checkNilAndInit() {
+	if sqlTemplate.Template == nil {
+		sqlTemplate.Template = make(map[string]*template.Template, 100)
+	}
+}
+
+func (sqlTemplate *HTMLTemplate) AddSqlTemplate(key string, sqlTemplateStr string) error {
+
+	var sqlt *template.Template
+	var err error
+	sqlt = template.New(key)
+	sqlt, err = sqlt.Parse(sqlTemplateStr)
+	if err != nil {
+		return err
+	}
+
+	sqlTemplate.checkNilAndInit()
+	sqlTemplate.Template[key] = sqlt
+
+	return nil
+
+}
+
+func (sqlTemplate *HTMLTemplate) UpdateSqlTemplate(key string, sqlTemplateStr string) error {
+
+	var sqlt *template.Template
+	var err error
+	sqlt = template.New(key)
+	sqlt, err = sqlt.Parse(sqlTemplateStr)
+	if err != nil {
+		return err
+	}
+
+	sqlTemplate.checkNilAndInit()
+	sqlTemplate.Template[key] = sqlt
+
+	return nil
+
+}
+
+func (sqlTemplate *HTMLTemplate) RemoveSqlTemplate(key string) {
+	sqlTemplate.checkNilAndInit()
+	delete(sqlTemplate.Template, key)
+}
+
+func (sqlTemplate *HTMLTemplate) BatchAddSqlTemplate(key string, sqlTemplateStrMap map[string]string) error {
+
+	sqlTemplate.checkNilAndInit()
+
+	for k, v := range sqlTemplateStrMap {
+		sqlt := template.New(key)
+		sqlt, err := sqlt.Parse(v)
+		if err != nil {
+			return err
+		}
+
+		sqlTemplate.Template[k] = sqlt
+	}
+
+	return nil
+
+}
+
+func (sqlTemplate *HTMLTemplate) BatchUpdateSqlTemplate(key string, sqlTemplateStrMap map[string]string) error {
+	sqlTemplate.checkNilAndInit()
+	for k, v := range sqlTemplateStrMap {
+		sqlt := template.New(key)
+		sqlt, err := sqlt.Parse(v)
+		if err != nil {
+			return err
+		}
+
+		sqlTemplate.Template[k] = sqlt
+	}
+
+	return nil
+
+}
+
+func (sqlTemplate *HTMLTemplate) BatchRemoveSqlTemplate(key []string) {
+	sqlTemplate.checkNilAndInit()
+	for _, v := range key {
+		delete(sqlTemplate.Template, v)
+	}
+}
+
+func (sqlTemplate *HTMLTemplate) GetSqlTemplate(key string) *template.Template {
+	return sqlTemplate.Template[key]
+}
+
+func (sqlTemplate *HTMLTemplate) GetSqlTemplates(keys ...interface{}) map[string]*template.Template {
+
+	var resultSqlTemplates map[string]*template.Template
+	i := len(keys)
+	if i == 0 {
+		return sqlTemplate.Template
+	}
+
+	if i == 1 {
+		switch keys[0].(type) {
+		case string:
+			resultSqlTemplates = make(map[string]*template.Template, 1)
+		case []string:
+			ks := keys[0].([]string)
+			n := len(ks)
+			resultSqlTemplates = make(map[string]*template.Template, n)
+		}
+	} else {
+		resultSqlTemplates = make(map[string]*template.Template, i)
+	}
+
+	for k, _ := range keys {
+		switch keys[k].(type) {
+		case string:
+			key := keys[k].(string)
+			resultSqlTemplates[key] = sqlTemplate.Template[key]
+		case []string:
+			ks := keys[k].([]string)
+			for _, v := range ks {
+				resultSqlTemplates[v] = sqlTemplate.Template[v]
+			}
+		}
+	}
+
+	return resultSqlTemplates
+}
+
+func (sqlTemplate *HTMLTemplate) Execute(key string, args ...interface{}) (string, error) {
+	var buf bytes.Buffer
+	if sqlTemplate.Template[key] == nil {
+		return "", nil
+	}
+
+	if len(args) == 0 {
+		err := sqlTemplate.Template[key].Execute(&buf, nil)
+		return buf.String(), err
+	} else {
+		map1 := args[0].(*map[string]interface{})
+		err := sqlTemplate.Template[key].Execute(&buf, *map1)
+		return buf.String(), err
+	}
+}

+ 321 - 0
sqltemplate_jet.go

@@ -0,0 +1,321 @@
+package xorm
+
+import (
+	"bytes"
+	"io/ioutil"
+	"os"
+	"strings"
+
+	"github.com/CloudyKit/jet"
+)
+
+type JetTemplate struct {
+	SqlTemplateRootDir string
+	Template           map[string]*jet.Template
+	extension          string
+	Capacity           uint
+	Cipher             Cipher
+}
+
+func (sqlTemplate *JetTemplate) RootDir() string {
+	return sqlTemplate.SqlTemplateRootDir
+}
+
+func (sqlTemplate *JetTemplate) Extension() string {
+	return sqlTemplate.extension
+}
+
+func (sqlTemplate *JetTemplate) SetSqlTemplateCipher(cipher Cipher) {
+	sqlTemplate.Cipher = cipher
+}
+
+func (sqlTemplate *JetTemplate) WalkFunc(path string, info os.FileInfo, err error) error {
+	if err != nil {
+		return err
+	}
+
+	if info.IsDir() {
+		return nil
+	}
+
+	if strings.HasSuffix(path, sqlTemplate.extension) {
+		err = sqlTemplate.paresSqlTemplate(info.Name(), path)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func (sqlTemplate *JetTemplate) paresSqlTemplate(filename string, filepath string) error {
+	var sqlt *jet.Template
+	var err error
+	var content []byte
+	if sqlTemplate.Cipher == nil {
+		templates := jet.NewSet(sqlTemplate.SqlTemplateRootDir)
+		sqlt, err = templates.GetTemplate(filename)
+		if err != nil {
+			return err
+		}
+	} else {
+		content, err = sqlTemplate.ReadTemplate(filepath)
+		if err != nil {
+			return err
+		}
+		templates := jet.NewSet(sqlTemplate.SqlTemplateRootDir)
+		sqlt, err = templates.LoadTemplate(filename, string(content))
+		if err != nil {
+			return err
+		}
+	}
+
+	sqlTemplate.checkNilAndInit()
+
+	sqlTemplate.Template[filename] = sqlt
+
+	return nil
+
+}
+
+func (sqlTemplate *JetTemplate) ReadTemplate(filepath string) ([]byte, error) {
+	content, err := ioutil.ReadFile(filepath)
+	if err != nil {
+		return nil, err
+	}
+	content, err = sqlTemplate.Cipher.Decrypt(content)
+	if err != nil {
+		return nil, err
+	}
+	return content, nil
+}
+
+//-------------------------------------------------------------------------------------------------------------
+func (sqlTemplate *JetTemplate) LoadSqlTemplate(filepath string) error {
+
+	if strings.HasSuffix(filepath, sqlTemplate.extension) {
+		err := sqlTemplate.loadSqlTemplate(filepath)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func (sqlTemplate *JetTemplate) BatchLoadSqlTemplate(filepathSlice []string) error {
+
+	for _, filepath := range filepathSlice {
+		if strings.HasSuffix(filepath, sqlTemplate.extension) {
+			err := sqlTemplate.loadSqlTemplate(filepath)
+			if err != nil {
+				return err
+			}
+		}
+	}
+
+	return nil
+}
+
+func (sqlTemplate *JetTemplate) ReloadSqlTemplate(filepath string) error {
+
+	if strings.HasSuffix(filepath, sqlTemplate.extension) {
+		err := sqlTemplate.reloadSqlTemplate(filepath)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func (sqlTemplate *JetTemplate) BatchReloadSqlTemplate(filepathSlice []string) error {
+
+	for _, filepath := range filepathSlice {
+		if strings.HasSuffix(filepath, sqlTemplate.extension) {
+			err := sqlTemplate.loadSqlTemplate(filepath)
+			if err != nil {
+				return err
+			}
+		}
+	}
+
+	return nil
+}
+
+func (sqlTemplate *JetTemplate) loadSqlTemplate(filepath string) error {
+	info, err := os.Lstat(filepath)
+	if err != nil {
+		return err
+	}
+
+	if info.IsDir() {
+		return nil
+	}
+
+	err = sqlTemplate.paresSqlTemplate(info.Name(), filepath)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (sqlTemplate *JetTemplate) reloadSqlTemplate(filepath string) error {
+	info, err := os.Lstat(filepath)
+	if err != nil {
+		return err
+	}
+
+	if info.IsDir() {
+		return nil
+	}
+
+	err = sqlTemplate.paresSqlTemplate(info.Name(), filepath)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (sqlTemplate *JetTemplate) checkNilAndInit() {
+	if sqlTemplate.Template == nil {
+		sqlTemplate.Template = make(map[string]*jet.Template, 100)
+	}
+}
+
+func (sqlTemplate *JetTemplate) AddSqlTemplate(key string, sqlTemplateStr string) error {
+
+	templates := jet.NewSet(sqlTemplate.SqlTemplateRootDir)
+	sqlt, err := templates.LoadTemplate(key, sqlTemplateStr)
+	if err != nil {
+		return err
+	}
+
+	sqlTemplate.checkNilAndInit()
+	sqlTemplate.Template[key] = sqlt
+
+	return nil
+
+}
+
+func (sqlTemplate *JetTemplate) UpdateSqlTemplate(key string, sqlTemplateStr string) error {
+
+	templates := jet.NewSet(sqlTemplate.SqlTemplateRootDir)
+	sqlt, err := templates.LoadTemplate(key, sqlTemplateStr)
+	if err != nil {
+		return err
+	}
+
+	sqlTemplate.checkNilAndInit()
+	sqlTemplate.Template[key] = sqlt
+
+	return nil
+
+}
+
+func (sqlTemplate *JetTemplate) RemoveSqlTemplate(key string) {
+	sqlTemplate.checkNilAndInit()
+	delete(sqlTemplate.Template, key)
+}
+
+func (sqlTemplate *JetTemplate) BatchAddSqlTemplate(key string, sqlTemplateStrMap map[string]string) error {
+
+	templates := jet.NewSet(sqlTemplate.SqlTemplateRootDir)
+
+	sqlTemplate.checkNilAndInit()
+
+	for k, v := range sqlTemplateStrMap {
+		sqlt, err := templates.LoadTemplate(key, v)
+		if err != nil {
+			return err
+		}
+
+		sqlTemplate.Template[k] = sqlt
+	}
+
+	return nil
+
+}
+
+func (sqlTemplate *JetTemplate) BatchUpdateSqlTemplate(key string, sqlTemplateStrMap map[string]string) error {
+	templates := jet.NewSet(sqlTemplate.SqlTemplateRootDir)
+	sqlTemplate.checkNilAndInit()
+	for k, v := range sqlTemplateStrMap {
+		sqlt, err := templates.LoadTemplate(key, v)
+		if err != nil {
+			return err
+		}
+
+		sqlTemplate.Template[k] = sqlt
+	}
+
+	return nil
+
+}
+
+func (sqlTemplate *JetTemplate) BatchRemoveSqlTemplate(key []string) {
+	sqlTemplate.checkNilAndInit()
+	for _, v := range key {
+		delete(sqlTemplate.Template, v)
+	}
+}
+
+func (sqlTemplate *JetTemplate) GetSqlTemplate(key string) *jet.Template {
+	return sqlTemplate.Template[key]
+}
+
+func (sqlTemplate *JetTemplate) GetSqlTemplates(keys ...interface{}) map[string]*jet.Template {
+
+	var resultSqlTemplates map[string]*jet.Template
+	i := len(keys)
+	if i == 0 {
+		return sqlTemplate.Template
+	}
+
+	if i == 1 {
+		switch keys[0].(type) {
+		case string:
+			resultSqlTemplates = make(map[string]*jet.Template, 1)
+		case []string:
+			ks := keys[0].([]string)
+			n := len(ks)
+			resultSqlTemplates = make(map[string]*jet.Template, n)
+		}
+	} else {
+		resultSqlTemplates = make(map[string]*jet.Template, i)
+	}
+
+	for k, _ := range keys {
+		switch keys[k].(type) {
+		case string:
+			key := keys[k].(string)
+			resultSqlTemplates[key] = sqlTemplate.Template[key]
+		case []string:
+			ks := keys[k].([]string)
+			for _, v := range ks {
+				resultSqlTemplates[v] = sqlTemplate.Template[v]
+			}
+		}
+	}
+
+	return resultSqlTemplates
+}
+
+func (sqlTemplate *JetTemplate) Execute(key string, args ...interface{}) (string, error) {
+	var buf bytes.Buffer
+	if sqlTemplate.Template[key] == nil {
+		return "", nil
+	}
+
+	if len(args) == 0 {
+		err := sqlTemplate.Template[key].Execute(&buf, nil, nil)
+		return buf.String(), err
+	} else {
+		map1 := args[0].(*map[string]interface{})
+		vars := make(jet.VarMap)
+		vars.Set("data", map1)
+		err := sqlTemplate.Template[key].Execute(&buf, vars, nil)
+		return buf.String(), err
+	}
+}

+ 309 - 0
sqltemplate_pongo2.go

@@ -0,0 +1,309 @@
+package xorm
+
+import (
+	"io/ioutil"
+	"os"
+	"strings"
+
+	"gopkg.in/flosch/pongo2.v3"
+)
+
+type Pongo2Template struct {
+	SqlTemplateRootDir string
+	Template           map[string]*pongo2.Template
+	extension          string
+	Capacity           uint
+	Cipher             Cipher
+	Type               int
+}
+
+func (sqlTemplate *Pongo2Template) RootDir() string {
+	return sqlTemplate.SqlTemplateRootDir
+}
+
+func (sqlTemplate *Pongo2Template) Extension() string {
+	return sqlTemplate.extension
+}
+
+func (sqlTemplate *Pongo2Template) SetSqlTemplateCipher(cipher Cipher) {
+	sqlTemplate.Cipher = cipher
+}
+
+func (sqlTemplate *Pongo2Template) WalkFunc(path string, info os.FileInfo, err error) error {
+	if err != nil {
+		return err
+	}
+
+	if info.IsDir() {
+		return nil
+	}
+
+	if strings.HasSuffix(path, sqlTemplate.extension) {
+		err = sqlTemplate.paresSqlTemplate(info.Name(), path)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func (sqlTemplate *Pongo2Template) paresSqlTemplate(filename string, filepath string) error {
+	var sqlt *pongo2.Template
+	var err error
+	var content []byte
+
+	if sqlTemplate.Cipher == nil {
+		sqlt, err = pongo2.FromFile(filepath)
+		if err != nil {
+			return err
+		}
+	} else {
+		content, err = sqlTemplate.ReadTemplate(filepath)
+		if err != nil {
+			return err
+		}
+		sqlt, err = pongo2.FromString(string(content))
+		if err != nil {
+			return err
+		}
+	}
+
+	sqlTemplate.checkNilAndInit()
+
+	sqlTemplate.Template[filename] = sqlt
+	return nil
+
+}
+
+func (sqlTemplate *Pongo2Template) ReadTemplate(filepath string) ([]byte, error) {
+	content, err := ioutil.ReadFile(filepath)
+	if err != nil {
+		return nil, err
+	}
+	content, err = sqlTemplate.Cipher.Decrypt(content)
+	if err != nil {
+		return nil, err
+	}
+	return content, nil
+}
+
+//-------------------------------------------------------------------------------------------------------------
+func (sqlTemplate *Pongo2Template) LoadSqlTemplate(filepath string) error {
+
+	if strings.HasSuffix(filepath, sqlTemplate.extension) {
+		err := sqlTemplate.loadSqlTemplate(filepath)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func (sqlTemplate *Pongo2Template) BatchLoadSqlTemplate(filepathSlice []string) error {
+
+	for _, filepath := range filepathSlice {
+		if strings.HasSuffix(filepath, sqlTemplate.extension) {
+			err := sqlTemplate.loadSqlTemplate(filepath)
+			if err != nil {
+				return err
+			}
+		}
+	}
+
+	return nil
+}
+
+func (sqlTemplate *Pongo2Template) ReloadSqlTemplate(filepath string) error {
+
+	if strings.HasSuffix(filepath, sqlTemplate.extension) {
+		err := sqlTemplate.reloadSqlTemplate(filepath)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func (sqlTemplate *Pongo2Template) BatchReloadSqlTemplate(filepathSlice []string) error {
+
+	for _, filepath := range filepathSlice {
+		if strings.HasSuffix(filepath, sqlTemplate.extension) {
+			err := sqlTemplate.loadSqlTemplate(filepath)
+			if err != nil {
+				return err
+			}
+		}
+	}
+
+	return nil
+}
+
+func (sqlTemplate *Pongo2Template) loadSqlTemplate(filepath string) error {
+	info, err := os.Lstat(filepath)
+	if err != nil {
+		return err
+	}
+
+	if info.IsDir() {
+		return nil
+	}
+
+	err = sqlTemplate.paresSqlTemplate(info.Name(), filepath)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (sqlTemplate *Pongo2Template) reloadSqlTemplate(filepath string) error {
+	info, err := os.Lstat(filepath)
+	if err != nil {
+		return err
+	}
+
+	if info.IsDir() {
+		return nil
+	}
+
+	err = sqlTemplate.paresSqlTemplate(info.Name(), filepath)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (sqlTemplate *Pongo2Template) checkNilAndInit() {
+	if sqlTemplate.Template == nil {
+		sqlTemplate.Template = make(map[string]*pongo2.Template, 100)
+	}
+}
+
+func (sqlTemplate *Pongo2Template) AddSqlTemplate(key string, sqlTemplateStr string) error {
+
+	template, err := pongo2.FromString(sqlTemplateStr)
+	if err != nil {
+		return err
+	}
+
+	sqlTemplate.checkNilAndInit()
+	sqlTemplate.Template[key] = template
+
+	return nil
+
+}
+
+func (sqlTemplate *Pongo2Template) UpdateSqlTemplate(key string, sqlTemplateStr string) error {
+
+	template, err := pongo2.FromString(sqlTemplateStr)
+	if err != nil {
+		return err
+	}
+	sqlTemplate.checkNilAndInit()
+	sqlTemplate.Template[key] = template
+
+	return nil
+
+}
+
+func (sqlTemplate *Pongo2Template) RemoveSqlTemplate(key string) {
+	sqlTemplate.checkNilAndInit()
+	delete(sqlTemplate.Template, key)
+}
+
+func (sqlTemplate *Pongo2Template) BatchAddSqlTemplate(key string, sqlTemplateStrMap map[string]string) error {
+	sqlTemplate.checkNilAndInit()
+	for k, v := range sqlTemplateStrMap {
+		template, err := pongo2.FromString(v)
+		if err != nil {
+			return err
+		}
+
+		sqlTemplate.Template[k] = template
+	}
+
+	return nil
+
+}
+
+func (sqlTemplate *Pongo2Template) BatchUpdateSqlTemplate(key string, sqlTemplateStrMap map[string]string) error {
+	sqlTemplate.checkNilAndInit()
+	for k, v := range sqlTemplateStrMap {
+		template, err := pongo2.FromString(v)
+		if err != nil {
+			return err
+		}
+
+		sqlTemplate.Template[k] = template
+	}
+
+	return nil
+
+}
+
+func (sqlTemplate *Pongo2Template) BatchRemoveSqlTemplate(key []string) {
+	sqlTemplate.checkNilAndInit()
+	for _, v := range key {
+		delete(sqlTemplate.Template, v)
+	}
+}
+
+func (sqlTemplate *Pongo2Template) GetSqlTemplate(key string) *pongo2.Template {
+	return sqlTemplate.Template[key]
+}
+
+func (sqlTemplate *Pongo2Template) GetSqlTemplates(keys ...interface{}) map[string]*pongo2.Template {
+
+	var resultSqlTemplates map[string]*pongo2.Template
+	i := len(keys)
+	if i == 0 {
+		return sqlTemplate.Template
+	}
+
+	if i == 1 {
+		switch keys[0].(type) {
+		case string:
+			resultSqlTemplates = make(map[string]*pongo2.Template, 1)
+		case []string:
+			ks := keys[0].([]string)
+			n := len(ks)
+			resultSqlTemplates = make(map[string]*pongo2.Template, n)
+		}
+	} else {
+		resultSqlTemplates = make(map[string]*pongo2.Template, i)
+	}
+
+	for k, _ := range keys {
+		switch keys[k].(type) {
+		case string:
+			key := keys[k].(string)
+			resultSqlTemplates[key] = sqlTemplate.Template[key]
+		case []string:
+			ks := keys[k].([]string)
+			for _, v := range ks {
+				resultSqlTemplates[v] = sqlTemplate.Template[v]
+			}
+		}
+	}
+
+	return resultSqlTemplates
+}
+
+func (sqlTemplate *Pongo2Template) Execute(key string, args ...interface{}) (string, error) {
+	if sqlTemplate.Template[key] == nil {
+		return "", nil
+	}
+
+	if len(args) == 0 {
+		parmap := &pongo2.Context{"1": 1}
+		sql, err := sqlTemplate.Template[key].Execute(*parmap)
+		return sql, err
+	} else {
+		map1 := args[0].(*map[string]interface{})
+		sql, err := sqlTemplate.Template[key].Execute(*map1)
+		return sql, err
+	}
+}

+ 7 - 7
sqltemplates_executor.go

@@ -40,7 +40,7 @@ func (sqlTemplatesExecutor *SqlTemplatesExecutor) Execute() ([][]map[string]inte
 	case string:
 		sqlkey := strings.TrimSpace(sqlTemplatesExecutor.sqlkeys.(string))
 		if sqlTemplatesExecutor.parmas == nil {
-			sqlStr, err = sqlTemplatesExecutor.session.engine.GetSqlTemplate(sqlkey).Execute(nil)
+			sqlStr, err = sqlTemplatesExecutor.session.engine.SqlTemplate.Execute(sqlkey)
 			if err != nil {
 				if sqlTemplatesExecutor.session.isSqlFunc == true {
 					err1 := sqlTemplatesExecutor.session.Rollback()
@@ -68,7 +68,7 @@ func (sqlTemplatesExecutor *SqlTemplatesExecutor) Execute() ([][]map[string]inte
 			case []map[string]interface{}:
 				parmaMap, _ := sqlTemplatesExecutor.parmas.([]map[string]interface{})
 
-				sqlStr, err = sqlTemplatesExecutor.session.engine.GetSqlTemplate(sqlkey).Execute(parmaMap[0])
+				sqlStr, err = sqlTemplatesExecutor.session.engine.SqlTemplate.Execute(sqlkey, parmaMap[0])
 				if err != nil {
 					if sqlTemplatesExecutor.session.isSqlFunc == true {
 						err1 := sqlTemplatesExecutor.session.Rollback()
@@ -95,7 +95,7 @@ func (sqlTemplatesExecutor *SqlTemplatesExecutor) Execute() ([][]map[string]inte
 			case map[string]interface{}:
 				parmaMap, _ := sqlTemplatesExecutor.parmas.(map[string]interface{})
 
-				sqlStr, err = sqlTemplatesExecutor.session.engine.GetSqlTemplate(sqlkey).Execute(parmaMap)
+				sqlStr, err = sqlTemplatesExecutor.session.engine.SqlTemplate.Execute(sqlkey, parmaMap)
 				if err != nil {
 					if sqlTemplatesExecutor.session.isSqlFunc == true {
 						err1 := sqlTemplatesExecutor.session.Rollback()
@@ -163,7 +163,7 @@ func (sqlTemplatesExecutor *SqlTemplatesExecutor) Execute() ([][]map[string]inte
 
 		if sqlTemplatesExecutor.parmas == nil {
 			for i, _ := range sqlkeysSlice {
-				sqlStr, err := sqlTemplatesExecutor.session.engine.GetSqlTemplate(sqlkeysSlice[i]).Execute(nil)
+				sqlStr, err := sqlTemplatesExecutor.session.engine.SqlTemplate.Execute(sqlkeysSlice[i])
 				if err != nil {
 					if sqlTemplatesExecutor.session.isSqlFunc == true {
 						err1 := sqlTemplatesExecutor.session.Rollback()
@@ -255,7 +255,7 @@ func (sqlTemplatesExecutor *SqlTemplatesExecutor) Execute() ([][]map[string]inte
 			}
 
 			for i, _ := range sqlkeysSlice {
-				sqlStr, err := sqlTemplatesExecutor.session.engine.GetSqlTemplate(sqlkeysSlice[i]).Execute(parmaSlice[i])
+				sqlStr, err := sqlTemplatesExecutor.session.engine.SqlTemplate.Execute(sqlkeysSlice[i], parmaSlice[i])
 				if err != nil {
 					if sqlTemplatesExecutor.session.isSqlFunc == true {
 						err1 := sqlTemplatesExecutor.session.Rollback()
@@ -362,7 +362,7 @@ func (sqlTemplatesExecutor *SqlTemplatesExecutor) Execute() ([][]map[string]inte
 		if sqlTemplatesExecutor.parmas == nil {
 
 			for k, _ := range sqlkeysMap {
-				sqlStr, err := sqlTemplatesExecutor.session.engine.GetSqlTemplate(sqlkeysMap[k]).Execute(nil)
+				sqlStr, err := sqlTemplatesExecutor.session.engine.SqlTemplate.Execute(sqlkeysMap[k])
 				if err != nil {
 					if sqlTemplatesExecutor.session.isSqlFunc == true {
 						err1 := sqlTemplatesExecutor.session.Rollback()
@@ -454,7 +454,7 @@ func (sqlTemplatesExecutor *SqlTemplatesExecutor) Execute() ([][]map[string]inte
 			}
 
 			for k, _ := range sqlkeysMap {
-				sqlStr, err := sqlTemplatesExecutor.session.engine.GetSqlTemplate(sqlkeysMap[k]).Execute(parmasMap[k])
+				sqlStr, err := sqlTemplatesExecutor.session.engine.SqlTemplate.Execute(sqlkeysMap[k], parmasMap[k])
 				if err != nil {
 					if sqlTemplatesExecutor.session.isSqlFunc == true {
 						err1 := sqlTemplatesExecutor.session.Rollback()