xormplus 9 år sedan
förälder
incheckning
98b66cc6ab
8 ändrade filer med 1018 tillägg och 194 borttagningar
  1. 71 34
      README.md
  2. 43 0
      engineplus.go
  3. 102 0
      sessionplus.go
  4. 258 159
      sql_executor.go
  5. 80 0
      sqlmap.go
  6. 311 0
      sqlmaps_executor.go
  7. 50 1
      sqltemplate.go
  8. 103 0
      test/xorm_test.go

+ 71 - 34
README.md

@@ -11,25 +11,16 @@ xorm是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作
 ## 特性
 ## 特性
 
 
 * 支持Struct和数据库表之间的灵活映射,并支持自动同步
 * 支持Struct和数据库表之间的灵活映射,并支持自动同步
-
 * 事务支持
 * 事务支持
-
 * 同时支持原始SQL语句和ORM操作的混合执行
 * 同时支持原始SQL语句和ORM操作的混合执行
-
 * 支持类ibatis方式配置SQL语句(支持xml配置文件和pongo2模板2种方式)
 * 支持类ibatis方式配置SQL语句(支持xml配置文件和pongo2模板2种方式)
-
 * 支持动态SQL功能
 * 支持动态SQL功能
-
+* 支持一次批量混合执行CRUD操作,并返回多个结果集
 * 使用连写来简化调用
 * 使用连写来简化调用
-
 * 支持使用Id, In, Where, Limit, Join, Having, Table, Sql, Cols等函数和结构体等方式作为条件
 * 支持使用Id, In, Where, Limit, Join, Having, Table, Sql, Cols等函数和结构体等方式作为条件
-
 * 支持级联加载Struct
 * 支持级联加载Struct
-
 * 支持缓存
 * 支持缓存
-
 * 支持根据数据库自动生成xorm的结构体
 * 支持根据数据库自动生成xorm的结构体
-
 * 支持记录版本(即乐观锁)
 * 支持记录版本(即乐观锁)
 
 
 ## 驱动支持
 ## 驱动支持
@@ -37,21 +28,13 @@ xorm是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作
 目前支持的Go数据库驱动和对应的数据库如下:
 目前支持的Go数据库驱动和对应的数据库如下:
 
 
 * Mysql: [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql)
 * Mysql: [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql)
-
 * MyMysql: [github.com/ziutek/mymysql](https://github.com/ziutek/mymysql)
 * MyMysql: [github.com/ziutek/mymysql](https://github.com/ziutek/mymysql)
-
 * Postgres: [github.com/lib/pq](https://github.com/lib/pq)
 * Postgres: [github.com/lib/pq](https://github.com/lib/pq)
-
 * Tidb: [github.com/pingcap/tidb](https://github.com/pingcap/tidb)
 * Tidb: [github.com/pingcap/tidb](https://github.com/pingcap/tidb)
-
 * SQLite: [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3)
 * SQLite: [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3)
-
 * MsSql: [github.com/denisenkom/go-mssqldb](https://github.com/denisenkom/go-mssqldb)
 * MsSql: [github.com/denisenkom/go-mssqldb](https://github.com/denisenkom/go-mssqldb)
-
 * MsSql: [github.com/lunny/godbc](https://github.com/lunny/godbc)
 * MsSql: [github.com/lunny/godbc](https://github.com/lunny/godbc)
-
 * Oracle: [github.com/mattn/go-oci8](https://github.com/mattn/go-oci8) (试验性支持)
 * Oracle: [github.com/mattn/go-oci8](https://github.com/mattn/go-oci8) (试验性支持)
-
 * ql: [github.com/cznic/ql](https://github.com/cznic/ql) (试验性支持)
 * ql: [github.com/cznic/ql](https://github.com/cznic/ql) (试验性支持)
 
 
 ## 安装
 ## 安装
@@ -104,7 +87,8 @@ if err != nil {
 	t.Fatal(err)
 	t.Fatal(err)
 }
 }
 
 
-err = engine.StartFSWatcher() //开启SqlMap配置文件和SqlTemplate配置文件更新监控功能,将配置文件更新内容实时更新到内存,如无需要可以不调用该方法
+//开启SqlMap配置文件和SqlTemplate配置文件更新监控功能,将配置文件更新内容实时更新到内存,如无需要可以不调用该方法
+err = engine.StartFSWatcher()
 if err != nil {
 if err != nil {
 	t.Fatal(err)
 	t.Fatal(err)
 }
 }
@@ -129,47 +113,58 @@ if err != nil {
 * 支持最原始的SQL语句查询
 * 支持最原始的SQL语句查询
 
 
 ```go
 ```go
-//第1种方式,返回的结果类型为 []map[string][]byte
+/*-------------------------------------------------------------------------------------
+ * 第1种方式:返回的结果类型为 []map[string][]byte
+-------------------------------------------------------------------------------------*/
 sql_1 := "select * from user"
 sql_1 := "select * from user"
 results, err := engine.Query(sql_1)
 results, err := engine.Query(sql_1)
 
 
-//第2种方式,返回的结果类型为 []map[string]interface{}
+/*-------------------------------------------------------------------------------------
+ * 第2种方式:返回的结果类型为 []map[string]interface{}
+-------------------------------------------------------------------------------------*/
 sql_2_1 := "select * from user"
 sql_2_1 := "select * from user"
-results := engine.Sql(sql_2_1).Query().Results
+results, err := engine.Sql(sql_2_1).Query().GetResults()
 
 
 sql_2_2 := "select * from user where id = ? and age = ?"
 sql_2_2 := "select * from user where id = ? and age = ?"
-results := engine.Sql(sql_2_2, 7, 17).Query().Results
-
+results, err := engine.Sql(sql_2_2, 7, 17).Query().GetResults()
 
 
-//第3种方式,执行SqlMap配置文件中的Sql语句,返回的结果类型为 []map[string]interface{}
+/*-------------------------------------------------------------------------------------
+  第3种方式:执行SqlMap配置文件中的Sql语句,返回的结果类型为 []map[string]interface{}
+-------------------------------------------------------------------------------------*/
 sql_id_3_1 := "sql_3_1" //配置文件中sql标签的id属性,SqlMap的key
 sql_id_3_1 := "sql_3_1" //配置文件中sql标签的id属性,SqlMap的key
-results := engine.SqlMapClient(sql_3_1).Query().Results
+results, err := engine.SqlMapClient(sql_3_1).Query().GetResults()
 
 
 sql_id_3_2 := "sql_3_2"
 sql_id_3_2 := "sql_3_2"
-results := engine.SqlMapClient(sql_id_3_2, 7, 17).Query().Results
+results, err := engine.SqlMapClient(sql_id_3_2, 7, 17).Query().GetResults()
 
 
 sql_id_3_3 := "sql_3_3"
 sql_id_3_3 := "sql_3_3"
 paramMap_3_3 := map[string]interface{}{"id": 7, "name": "xormplus"}
 paramMap_3_3 := map[string]interface{}{"id": 7, "name": "xormplus"}
-results1 := engine.SqlMapClient(sql_id_3_3, &paramMap_3_3).Query().Results
+results1, err := engine.SqlMapClient(sql_id_3_3, &paramMap_3_3).Query().GetResults()
 
 
-//第4种方式,执行SqlTemplate配置文件中的Sql语句,返回的结果类型为 []map[string]interface{}
+/*-------------------------------------------------------------------------------------
+ * 第4种方式:执行SqlTemplate配置文件中的Sql语句,返回的结果类型为 []map[string]interface{}
+-------------------------------------------------------------------------------------*/
 sql_key_4_1 := "select.example.stpl" //配置文件名,SqlTemplate的key
 sql_key_4_1 := "select.example.stpl" //配置文件名,SqlTemplate的key
 
 
 //执行的 sql:select * from user where id=7
 //执行的 sql:select * from user where id=7
 //如部分参数未使用,请记得使用对应类型0值,如此处name参数值为空字符串,模板使用指南请详见pongo2
 //如部分参数未使用,请记得使用对应类型0值,如此处name参数值为空字符串,模板使用指南请详见pongo2
 paramMap_4_1 := map[string]interface{}{"count": 1, "id": 7, "name": ""}
 paramMap_4_1 := map[string]interface{}{"count": 1, "id": 7, "name": ""}
-results := engine.SqlTemplateClient(sql_key_4_1, &paramMap_4_1).Query().Results
+results, err := engine.SqlTemplateClient(sql_key_4_1, &paramMap_4_1).Query().GetResults()
 
 
 //执行的 sql:select * from user where name='xormplus'
 //执行的 sql:select * from user where name='xormplus'
 //如部分参数未使用,请记得使用对应类型0值,如此处id参数值为0,模板使用指南请详见pongo2
 //如部分参数未使用,请记得使用对应类型0值,如此处id参数值为0,模板使用指南请详见pongo2
 paramMap_4_2 := map[string]interface{}{"id": 0, "count": 2, "name": "xormplus"}
 paramMap_4_2 := map[string]interface{}{"id": 0, "count": 2, "name": "xormplus"}
-results := engine.SqlTemplateClient(sql_key_4_1, &paramMap_4_2).Query().Results
+results, err := engine.SqlTemplateClient(sql_key_4_1, &paramMap_4_2).Query().GetResults()
 
 
-//第5种方式,返回的结果类型为对应的[]interface{}
+/*-------------------------------------------------------------------------------------
+ * 第5种方式:返回的结果类型为对应的[]interface{}
+-------------------------------------------------------------------------------------*/
 var categories []Category
 var categories []Category
 err := engine.Sql("select * from category where id =?", 16).Find(&categories)
 err := engine.Sql("select * from category where id =?", 16).Find(&categories)
 
 
-//第6种方式,返回的结果类型为对应的[]interface{}
+/*-------------------------------------------------------------------------------------
+ * 第6种方式:返回的结果类型为对应的[]interface{}
+-------------------------------------------------------------------------------------*/
 sql_id_6_1 := "sql_6_1"
 sql_id_6_1 := "sql_6_1"
 var categories []Category
 var categories []Category
 err := engine.SqlMapClient(sql_id_6_1, 16).Find(&categories)
 err := engine.SqlMapClient(sql_id_6_1, 16).Find(&categories)
@@ -179,7 +174,9 @@ var categories []Category
 paramMap_6_2 := map[string]interface{}{"id": 25}
 paramMap_6_2 := map[string]interface{}{"id": 25}
 err := engine.SqlMapClient(sql_id_6_2, &paramMap_6_2).Find(&categories)
 err := engine.SqlMapClient(sql_id_6_2, &paramMap_6_2).Find(&categories)
 
 
-//第7种方式,返回的结果类型为对应的[]interface{}
+/*-------------------------------------------------------------------------------------
+ * 第7种方式:返回的结果类型为对应的[]interface{}
+-------------------------------------------------------------------------------------*/
 //执行的 sql:select * from user where name='xormplus'
 //执行的 sql:select * from user where name='xormplus'
 sql_key_7_1 := "select.example.stpl" //配置文件名,SqlTemplate的key
 sql_key_7_1 := "select.example.stpl" //配置文件名,SqlTemplate的key
 var users []User
 var users []User
@@ -187,6 +184,10 @@ paramMap_7_1 := map[string]interface{}{"id": 0, "count": 2, "name": "xormplus"}
 err := engine.SqlTemplateClient(sql_key_7_1, &paramMap_7_1).Find(&users)
 err := engine.SqlTemplateClient(sql_key_7_1, &paramMap_7_1).Find(&users)
 ```
 ```
 
 
+* 注:
+	* 除以上7种方式外,本库还支持另外3种方式,由于这4种方式支持一次性批量混合CRUD操作,返回多个结果集,且支持多种参数组合形式,内容较多,场景比较复杂,因此不在此处赘述。
+	* 欲了解另外3种方式相关内容您可移步[批量SQL操作](#ROP_ARM)章节,此3种方式将在此章节单独说明
+
 * 第3种和第6种方式所使用的SqlMap配置文件内容如下
 * 第3种和第6种方式所使用的SqlMap配置文件内容如下
 
 
 ```xml
 ```xml
@@ -245,6 +246,10 @@ paramMap_i_t := map[string]interface{}{"key": "config_3", "value": "3"}
 affected, err := engine.SqlTemplateClient(sql_i_3, &paramMap_i_t).Execute()
 affected, err := engine.SqlTemplateClient(sql_i_3, &paramMap_i_t).Execute()
 ```
 ```
 
 
+* 注:
+	* 除以上3种方式外,本库还支持另外3种方式,由于这4种方式支持一次性批量混合CRUD操作,返回多个结果集,且支持多种参数组合形式,内容较多,场景比较复杂,因此不在此处赘述。
+	* 欲了解另外3种方式相关内容您可移步[批量SQL操作](#ROP_ARM)章节,此4种方式将在此章节单独说明
+
 * 支持链式读取数据操作查询返回json或xml字符串
 * 支持链式读取数据操作查询返回json或xml字符串
 
 
 ```go
 ```go
@@ -367,6 +372,7 @@ engine.ReloadSqlMap(filepath) //重新加载指定文件的SqlMap配置
 engine.BatchLoadSqlMap([]filepath) //批量加载SqlMap配置
 engine.BatchLoadSqlMap([]filepath) //批量加载SqlMap配置
 engine.BatchReloadSqlMap([]filepath) //批量加载SqlMap配置
 engine.BatchReloadSqlMap([]filepath) //批量加载SqlMap配置
 
 
+engine.GetSql(key, sql) //获取一条SqlMap配置
 engine.AddSql(key, sql) //新增一条SqlMap配置
 engine.AddSql(key, sql) //新增一条SqlMap配置
 engine.UpdateSql(key, sql) //更新一条SqlMap配置
 engine.UpdateSql(key, sql) //更新一条SqlMap配置
 engine.RemoveSql(key) //删除一条SqlMap配置
 engine.RemoveSql(key) //删除一条SqlMap配置
@@ -388,8 +394,39 @@ engine.RemoveSqlTemplate(key) //删除一条SqlTemplate模板
 engine.BatchAddSqlTemplate(map[key]sql) //批量新增SqlTemplate配置,sql为SqlTemplate模板内容字符串
 engine.BatchAddSqlTemplate(map[key]sql) //批量新增SqlTemplate配置,sql为SqlTemplate模板内容字符串
 engine.BatchUpdateSqlTemplate(map[key]sql) //批量更新SqlTemplate配置,sql为SqlTemplate模板内容字符串
 engine.BatchUpdateSqlTemplate(map[key]sql) //批量更新SqlTemplate配置,sql为SqlTemplate模板内容字符串
 engine.batchUpdateSqlTemplate([]key) //批量删除SqlTemplate配置
 engine.batchUpdateSqlTemplate([]key) //批量删除SqlTemplate配置
+
+/*
+1、指定多个key,批量查询SqlMap配置,...key的数据类型为...interface{},返回类型为map[string]string
+2、支持如下多种调用方式
+	a)engine.GetSqlMap("Test_GetSqlMap_1"),返回key为Test_GetSqlMap_1的SqlMap配置
+    b)engine.GetSqlMap("Test_GetSqlMap_1", "Test_GetSqlMap_3"),返回key为Test_GetSqlMap_1,Test_GetSqlMap_3的SqlMap配置
+    c)engine.GetSqlMap("Test_GetSqlMap_1", "Test_GetSqlMap_3","Test_GetSqlMap_null"),返回key为Test_GetSqlMap_1,Test_GetSqlMap_3的SqlMap,Test_GetSqlMap_null配置,其中Test_GetSqlMap_null在内存中缓存的的key不存在,则在返回的map[string]string中,key Test_GetSqlMap_null配置返回的值为空字符串
+    d)engine.GetSqlMap([]string{"Test_GetSqlMap_1", "Test_GetSqlMap_3"})支持字符串数组形式参数
+    e)engine.GetSqlMap([]string{"Test_GetSqlMap_1", "Test_GetSqlMap_3"},"Test_GetSqlMap_2")支持字符串数组形式和字符串参数混用
+    f)engine.GetSqlMap([]string{"Test_GetSqlMap_1", "Test_GetSqlMap_3"},"Test_GetSqlMap_2",3)支持字符串数组形式,字符串参数和其他类型参数混用,但查询时只会处理字符串类型参数和字符转数组类型参数(因为SqlMap的key是字符串类型),返回的map[string]string也无其他类型的key
+3、如不传任何参数,调用engine.GetSqlMap(),则返回整个内存中当前缓存的所有SqlMap配置
+*/
+engine.GetSqlMap(...key)
+
+/*
+1、指定多个key,批量查询SqlTemplate配置,...key的数据类型为...interface{},返回类型为map[string]*pongo2.Template
+2、支持如下多种调用方式
+	a)engine.GetSqlTemplates("Test_GetSqlTemplates_1"),返回key为Test_GetSqlTemplates_1的SSqlTemplate配置
+    b)engine.GetSqlTemplates("Test_GetSqlTemplates_1", "Test_GetSqlTemplates_3"),返回key为Test_GetSqlTemplates_1,Test_GetSqlTemplates_3的SqlTemplate配置
+    c)engine.GetSqlTemplates("Test_GetSqlTemplates_1", "Test_GetSqlTemplates_3","Test_GetSqlTemplates_null"),返回key为Test_GetSqlTemplates_1,Test_GetSqlTemplates_3的SqlMap,Test_GetSqlMap_null配置,其中Test_GetSqlTemplates_null在内存中缓存的的key不存在,则在返回的map[string]*pongo2.Template中,key Test_GetSqlTemplates_null配置返回的值为nil
+    d)engine.GetSqlTemplates([]string{"Test_GetSqlTemplates_1", "Test_GetSqlTemplates_3"})支持字符串数组形式参数
+    e)engine.GetSqlTemplates([]string{"Test_GetSqlTemplates_1", "Test_GetSqlTemplates_3"},"Test_GetSqlTemplates_2")支持字符串数组形式和字符串参数混用
+    f)engine.GetSqlTemplates([]string{"Test_GetSqlTemplates_1", "Test_GetSqlTemplates_3"},"Test_GetSqlTemplates_2",3)支持字符串数组形式,字符串参数和其他类型参数混用,但查询时只会处理字符串类型参数和字符转数组类型参数(因为SqlTemplate的key是字符串类型),返回的map[string]*pongo2.Template也无其他类型的key
+3、如不传任何参数,调用engine.GetSqlTemplates(),则返回整个内存中当前缓存的所有SqlTemplate配置
+4、engine.GetSqlTemplates()返回类型为map[string]*pongo2.Template,可以方便的实现链式调用pongo2的Execute(),ExecuteBytes(),ExecuteWriter()方法
+*/
+engine.GetSqlTemplates(...key)
 ```
 ```
+<a name="ROP_ARM"/>
+# 一次批量混合执行CRUD操作,并返回批量结果集
+
 
 
+# ORM方式操作数据库
 * ORM方式插入一条或者多条记录
 * ORM方式插入一条或者多条记录
 
 
 ```Go
 ```Go

+ 43 - 0
engineplus.go

@@ -2,6 +2,7 @@ package xorm
 
 
 import (
 import (
 	"encoding/json"
 	"encoding/json"
+	"reflect"
 
 
 	"gopkg.in/flosch/pongo2.v3"
 	"gopkg.in/flosch/pongo2.v3"
 )
 )
@@ -88,3 +89,45 @@ func JSONString(v interface{}, IndentJSON bool) (string, error) {
 	}
 	}
 	return string(result), nil
 	return string(result), nil
 }
 }
+
+func (engine *Engine) Sqls(sqls interface{}, parmas ...interface{}) *SqlsExecutor {
+	session := engine.NewSession()
+	session.IsSqlFuc = true
+	return session.Sqls(sqls, parmas...)
+}
+
+func (engine *Engine) SqlMapsClient(sqls interface{}, parmas ...interface{}) *SqlMapsExecutor {
+	session := engine.NewSession()
+	session.IsSqlFuc = true
+	return session.SqlMapsClient(sqls, parmas...)
+}
+
+func (engine *Engine) SqlTemplatesClient(sqls interface{}, parmas ...interface{}) *SqlsExecutor {
+	session := engine.NewSession()
+	session.IsSqlFuc = true
+	return session.Sqls(sqls, parmas...)
+}
+
+func (engine *Engine) BatchSql(sqls interface{}) *Session {
+	session := engine.NewSession()
+	types := reflect.TypeOf(sqls)
+	if types.Kind() == reflect.Map {
+		engine.logger.Info("sqls is Map")
+		engine.logger.Info(types.Elem())
+		engine.logger.Info(types.Elem().Kind())
+	}
+
+	if types.Kind() == reflect.Slice {
+		engine.logger.Info("sqls is Slice")
+		engine.logger.Info(types.Elem())
+		engine.logger.Info(types.Elem().Kind())
+	}
+
+	switch sqls.(type) {
+	case []string:
+		engine.logger.Info("sqls is []string")
+	case map[string]string:
+		engine.logger.Info("sqls is map[string]string")
+	}
+	return session.BatchSql()
+}

+ 102 - 0
sessionplus.go

@@ -15,6 +15,7 @@ import (
 	"strings"
 	"strings"
 	"time"
 	"time"
 	//	"unsafe"
 	//	"unsafe"
+	"runtime"
 
 
 	"github.com/Chronokeeper/anyxml"
 	"github.com/Chronokeeper/anyxml"
 	"github.com/xormplus/core"
 	"github.com/xormplus/core"
@@ -37,6 +38,10 @@ func (resultBean ResultBean) Json() (bool, string, error) {
 	return resultBean.Has, result, err
 	return resultBean.Has, result, err
 }
 }
 
 
+func (resultBean ResultBean) GetResult() (bool, interface{}, error) {
+	return resultBean.Has, resultBean.Result, resultBean.Error
+}
+
 func (session *Session) GetFirst(bean interface{}) ResultBean {
 func (session *Session) GetFirst(bean interface{}) ResultBean {
 	has, err := session.Get(bean)
 	has, err := session.Get(bean)
 	r := ResultBean{Has: has, Result: bean, Error: err}
 	r := ResultBean{Has: has, Result: bean, Error: err}
@@ -111,6 +116,10 @@ type ResultMap struct {
 	Error   error
 	Error   error
 }
 }
 
 
+func (resultMap ResultMap) GetResults() ([]map[string]interface{}, error) {
+	return resultMap.Results, resultMap.Error
+}
+
 func (resultMap ResultMap) Json() (string, error) {
 func (resultMap ResultMap) Json() (string, error) {
 
 
 	if resultMap.Error != nil {
 	if resultMap.Error != nil {
@@ -231,6 +240,7 @@ func (session *Session) Query() ResultMap {
 	sql := session.Statement.RawSQL
 	sql := session.Statement.RawSQL
 	params := session.Statement.RawParams
 	params := session.Statement.RawParams
 	i := len(params)
 	i := len(params)
+
 	var result []map[string]interface{}
 	var result []map[string]interface{}
 	var err error
 	var err error
 	if i == 1 {
 	if i == 1 {
@@ -907,3 +917,95 @@ func (session *Session) queryPreprocessByMap(sqlStr *string, paramMap interface{
 	*sqlStr = query
 	*sqlStr = query
 	session.Engine.logSQL(*sqlStr, paramMap)
 	session.Engine.logSQL(*sqlStr, paramMap)
 }
 }
+
+func (session *Session) BatchSql() *Session {
+	return session
+}
+
+func (session *Session) BatchExecute() interface{} {
+
+	session.Engine.logger.Info(runtime.Caller(0))
+	session.Engine.logger.Info(runtime.Caller(1))
+	session.Engine.logger.Info(runtime.Caller(2))
+	return []string{"GetSqlMap", "sql_2_1", "sql1"}
+}
+
+func (session *Session) Sqls(sqls interface{}, parmas ...interface{}) *SqlsExecutor {
+
+	sqlsExecutor := new(SqlsExecutor)
+	switch sqls.(type) {
+	case string:
+		sqlsExecutor.sqls = sqls.(string)
+	case []string:
+		sqlsExecutor.sqls = sqls.([]string)
+	case map[string]string:
+		sqlsExecutor.sqls = sqls.(map[string]string)
+	}
+
+	if len(parmas) == 0 {
+		sqlsExecutor.parmas = nil
+	}
+
+	if len(parmas) > 1 {
+		sqlsExecutor.parmas = nil
+		sqlsExecutor.err = ErrParamsType
+	}
+
+	if len(parmas) == 1 {
+		switch parmas[0].(type) {
+		case map[string]interface{}:
+			sqlsExecutor.parmas = parmas[0].(map[string]interface{})
+
+		case []map[string]interface{}:
+			sqlsExecutor.parmas = parmas[0].([]map[string]interface{})
+
+		case map[string]map[string]interface{}:
+			sqlsExecutor.parmas = parmas[0].(map[string]map[string]interface{})
+
+		}
+	}
+
+	sqlsExecutor.session = session
+
+	return sqlsExecutor
+}
+
+func (session *Session) SqlMapsClient(sqlkeys interface{}, parmas ...interface{}) *SqlMapsExecutor {
+	sqlMapsExecutor := new(SqlMapsExecutor)
+
+	switch sqlkeys.(type) {
+	case string:
+		sqlMapsExecutor.sqlkeys = sqlkeys.(string)
+	case []string:
+		sqlMapsExecutor.sqlkeys = sqlkeys.([]string)
+	case map[string]string:
+		sqlMapsExecutor.sqlkeys = sqlkeys.(map[string]string)
+	}
+
+	if len(parmas) == 0 {
+		sqlMapsExecutor.parmas = nil
+	}
+
+	if len(parmas) > 1 {
+		sqlMapsExecutor.parmas = nil
+		sqlMapsExecutor.err = ErrParamsType
+	}
+
+	if len(parmas) == 1 {
+		switch parmas[0].(type) {
+		case map[string]interface{}:
+			sqlMapsExecutor.parmas = parmas[0].(map[string]interface{})
+
+		case []map[string]interface{}:
+			sqlMapsExecutor.parmas = parmas[0].([]map[string]interface{})
+
+		case map[string]map[string]interface{}:
+			sqlMapsExecutor.parmas = parmas[0].(map[string]map[string]interface{})
+
+		}
+	}
+
+	sqlMapsExecutor.session = session
+
+	return sqlMapsExecutor
+}

+ 258 - 159
sql_executor.go

@@ -1,221 +1,320 @@
 package xorm
 package xorm
 
 
 import (
 import (
+	"database/sql"
 	"strings"
 	"strings"
 	"time"
 	"time"
 )
 )
 
 
-type SqlExecutor struct {
+type SqlsExecutor struct {
 	session *Session
 	session *Session
 	sqls    interface{}
 	sqls    interface{}
 	parmas  interface{}
 	parmas  interface{}
 	err     error
 	err     error
 }
 }
 
 
-func (sqlExecutor *SqlExecutor) Execute() ([][]map[string]interface{}, map[string][]map[string]interface{}, error) {
-	if sqlExecutor.err != nil {
-		return nil, nil, sqlExecutor.err
+func (sqlsExecutor *SqlsExecutor) Execute() ([][]map[string]interface{}, map[string][]map[string]interface{}, error) {
+	if sqlsExecutor.err != nil {
+		return nil, nil, sqlsExecutor.err
 	}
 	}
+	var model_1_results ResultMap
+	var model_2_results sql.Result
+	var err error
 
 
-	switch sqlExecutor.sqls.(type) {
+	sqlModel := 1
+
+	switch sqlsExecutor.sqls.(type) {
 	case string:
 	case string:
-		sqlstr := strings.TrimLeft(sqlExecutor.sqls.(string), " \n")
-		sqlCmd := strings.ToLower(strings.Split(sqlstr, " ")[0])
+		sqlStr := strings.TrimSpace(sqlsExecutor.sqls.(string))
+		sqlCmd := strings.ToLower(strings.Split(sqlStr, " ")[0])
 
 
-		if sqlExecutor.parmas == nil {
+		if sqlsExecutor.parmas == nil {
 			switch sqlCmd {
 			switch sqlCmd {
 			case "select", "desc":
 			case "select", "desc":
-				rsults := sqlExecutor.session.Sql(sqlstr).Query()
-				if rsults.Error != nil {
-					return nil, nil, rsults.Error
-				}
-				resultSlice := make([][]map[string]interface{}, 1)
-				resultSlice[0] = rsults.Results
-				return resultSlice, nil, nil
-			case "insert", "delete", "update":
-				rsults, err := sqlExecutor.session.Sql(sqlstr).Execute()
-				if err != nil {
-					return nil, nil, err
-				}
+				model_1_results = sqlsExecutor.session.Sql(sqlStr).Query()
 
 
-				resultSlice := make([][]map[string]interface{}, 1)
-				resultMap := make([]map[string]interface{}, 1)
-				resultMap[0] = make(map[string]interface{})
-
-				//todo all database support LastInsertId
-				LastInsertId, _ := rsults.LastInsertId()
-
-				resultMap[0]["LastInsertId"] = LastInsertId
-				RowsAffected, err := rsults.RowsAffected()
-				if err != nil {
-					return nil, nil, err
-				}
-				resultMap[0]["RowsAffected"] = RowsAffected
-				resultSlice[0] = resultMap
-				return resultSlice, nil, nil
+			case "insert", "delete", "update", "create":
+				model_2_results, err = sqlsExecutor.session.Sql(sqlStr).Execute()
+				sqlModel = 2
 			}
 			}
 		} else {
 		} else {
-			switch sqlExecutor.parmas.(type) {
+			switch sqlsExecutor.parmas.(type) {
 			case []map[string]interface{}:
 			case []map[string]interface{}:
-				parmaMap, ok := sqlExecutor.parmas.([]map[string]interface{})
+				parmaMap, ok := sqlsExecutor.parmas.([]map[string]interface{})
 				if !ok {
 				if !ok {
 					return nil, nil, ErrParamsType
 					return nil, nil, ErrParamsType
 				}
 				}
+				key := NewV4().String() + time.Now().String()
+				sqlsExecutor.session.Engine.AddSql(key, sqlStr)
 				switch sqlCmd {
 				switch sqlCmd {
 				case "select", "desc":
 				case "select", "desc":
-					rsults := sqlExecutor.session.Sql(sqlstr, &parmaMap[0]).Query()
-					if rsults.Error != nil {
-						return nil, nil, rsults.Error
-					}
-					resultSlice := make([][]map[string]interface{}, 1)
-					resultSlice[0] = rsults.Results
-					return resultSlice, nil, nil
-
-				case "insert", "delete", "update":
-					rsults, err := sqlExecutor.session.Sql(sqlstr, &parmaMap[0]).Execute()
-					if err != nil {
-						return nil, nil, err
-					}
+					model_1_results = sqlsExecutor.session.SqlMapClient(key, &parmaMap[0]).Query()
 
 
-					resultSlice := make([][]map[string]interface{}, 1)
-					resultMap := make([]map[string]interface{}, 1)
-					resultMap[0] = make(map[string]interface{})
-					LastInsertId, _ := rsults.LastInsertId()
+				case "insert", "delete", "update", "create":
+					model_2_results, err = sqlsExecutor.session.SqlMapClient(key, &parmaMap[0]).Execute()
+					sqlModel = 2
 
 
-					resultMap[0]["LastInsertId"] = LastInsertId
-					RowsAffected, err := rsults.RowsAffected()
-					if err != nil {
-						return nil, nil, err
-					}
-					resultMap[0]["RowsAffected"] = RowsAffected
-					resultSlice[0] = resultMap
-					return resultSlice, nil, nil
 				}
 				}
+				sqlsExecutor.session.Engine.RemoveSql(key)
 			case map[string]interface{}:
 			case map[string]interface{}:
-				parmaMap, ok := sqlExecutor.parmas.(map[string]interface{})
+				parmaMap, ok := sqlsExecutor.parmas.(map[string]interface{})
 				if !ok {
 				if !ok {
 					return nil, nil, ErrParamsType
 					return nil, nil, ErrParamsType
 				}
 				}
+				key := NewV4().String() + time.Now().String()
+				sqlsExecutor.session.Engine.AddSql(key, sqlStr)
 				switch sqlCmd {
 				switch sqlCmd {
 				case "select", "desc":
 				case "select", "desc":
-					key := NewV4().String() + time.Now().String()
-					sqlExecutor.session.Engine.AddSql(key, sqlstr)
+					model_1_results = sqlsExecutor.session.SqlMapClient(key, &parmaMap).Query()
+				case "insert", "delete", "update", "create":
+					model_2_results, err = sqlsExecutor.session.SqlMapClient(key, &parmaMap).Execute()
+					sqlModel = 2
+				}
+				sqlsExecutor.session.Engine.RemoveSql(key)
+			default:
+				return nil, nil, ErrParamsType
+			}
+		}
 
 
-					rsults := sqlExecutor.session.SqlMapClient(key, &parmaMap).Query()
-					sqlExecutor.session.Engine.RemoveSql(key)
+		resultSlice := make([][]map[string]interface{}, 1)
 
 
-					if rsults.Error != nil {
-						return nil, nil, rsults.Error
-					}
+		if sqlModel == 1 {
+			if model_1_results.Error != nil {
+				return nil, nil, model_1_results.Error
+			}
+
+			resultSlice[0] = make([]map[string]interface{}, len(model_1_results.Results))
+			resultSlice[0] = model_1_results.Results
+			return resultSlice, nil, nil
+		} else {
+			if err != nil {
+				return nil, nil, err
+			}
+
+			resultMap := make([]map[string]interface{}, 1)
+			resultMap[0] = make(map[string]interface{})
 
 
-					resultSlice := make([][]map[string]interface{}, 1)
-					resultSlice[0] = rsults.Results
-					return resultSlice, nil, nil
-				case "insert", "delete", "update":
-					rsults, err := sqlExecutor.session.Sql(sqlstr, &parmaMap).Execute()
-					if err != nil {
-						return nil, nil, err
+			//todo all database support LastInsertId
+			LastInsertId, _ := model_2_results.LastInsertId()
+
+			resultMap[0]["LastInsertId"] = LastInsertId
+			RowsAffected, err := model_2_results.RowsAffected()
+			if err != nil {
+				return nil, nil, err
+			}
+			resultMap[0]["RowsAffected"] = RowsAffected
+			resultSlice[0] = resultMap
+			return resultSlice, nil, nil
+		}
+	case []string:
+		if sqlsExecutor.session.IsSqlFuc == true {
+			err := sqlsExecutor.session.Begin()
+			if err != nil {
+				return nil, nil, err
+			}
+		}
+		sqlsSlice := sqlsExecutor.sqls.([]string)
+		n := len(sqlsSlice)
+		resultSlice := make([][]map[string]interface{}, n)
+		parmaSlice := make([]map[string]interface{}, n)
+		switch sqlsExecutor.parmas.(type) {
+		case []map[string]interface{}:
+			parmaSlice = sqlsExecutor.parmas.([]map[string]interface{})
+
+		default:
+			if sqlsExecutor.session.IsSqlFuc == true {
+				err := sqlsExecutor.session.Rollback()
+				if err != nil {
+					return nil, nil, err
+				}
+			}
+			return nil, nil, ErrParamsType
+		}
+
+		for i, _ := range sqlsSlice {
+			sqlStr := strings.TrimSpace(sqlsSlice[i])
+			sqlCmd := strings.ToLower(strings.Split(sqlStr, " ")[0])
+			if parmaSlice[i] == nil {
+				switch sqlCmd {
+				case "select", "desc":
+					model_1_results = sqlsExecutor.session.Sql(sqlStr).Query()
+
+				case "insert", "delete", "update", "create":
+					model_2_results, err = sqlsExecutor.session.Sql(sqlStr).Execute()
+					sqlModel = 2
+				}
+			} else {
+				key := NewV4().String() + time.Now().String()
+				sqlsExecutor.session.Engine.AddSql(key, sqlStr)
+				switch sqlCmd {
+				case "select", "desc":
+					model_1_results = sqlsExecutor.session.SqlMapClient(key, &parmaSlice[i]).Query()
+				case "insert", "delete", "update", "create":
+					model_2_results, err = sqlsExecutor.session.SqlMapClient(key, &parmaSlice[i]).Execute()
+					sqlModel = 2
+				}
+				sqlsExecutor.session.Engine.RemoveSql(key)
+			}
+
+			if sqlModel == 1 {
+				if model_1_results.Error != nil {
+					if sqlsExecutor.session.IsSqlFuc == true {
+						err := sqlsExecutor.session.Rollback()
+						if err != nil {
+							return nil, nil, err
+						}
 					}
 					}
+					return nil, nil, model_1_results.Error
+				}
 
 
-					resultSlice := make([][]map[string]interface{}, 1)
-					resultMap := make([]map[string]interface{}, 1)
-					resultMap[0] = make(map[string]interface{})
-					LastInsertId, _ := rsults.LastInsertId()
+				resultSlice[i] = make([]map[string]interface{}, len(model_1_results.Results))
+				resultSlice[i] = model_1_results.Results
 
 
-					resultMap[0]["LastInsertId"] = LastInsertId
-					RowsAffected, err := rsults.RowsAffected()
-					if err != nil {
-						return nil, nil, err
+			} else {
+				if err != nil {
+					if sqlsExecutor.session.IsSqlFuc == true {
+						err := sqlsExecutor.session.Rollback()
+						if err != nil {
+							return nil, nil, err
+						}
 					}
 					}
-					resultMap[0]["RowsAffected"] = RowsAffected
-					resultSlice[0] = resultMap
-					return resultSlice, nil, nil
+					return nil, nil, err
 				}
 				}
-			default:
-				return nil, nil, ErrParamsType
+
+				resultMap := make([]map[string]interface{}, 1)
+				resultMap[0] = make(map[string]interface{})
+
+				//todo all database support LastInsertId
+				LastInsertId, _ := model_2_results.LastInsertId()
+
+				resultMap[0]["LastInsertId"] = LastInsertId
+				RowsAffected, err := model_2_results.RowsAffected()
+				if err != nil {
+					return nil, nil, err
+				}
+				resultMap[0]["RowsAffected"] = RowsAffected
+				resultSlice[i] = make([]map[string]interface{}, 1)
+				resultSlice[i] = resultMap
+
 			}
 			}
 		}
 		}
-	case []string:
-		if sqlExecutor.session.IsSqlFuc == true {
-			err := sqlExecutor.session.Begin()
+
+		if sqlsExecutor.session.IsSqlFuc == true {
+			err := sqlsExecutor.session.Commit()
 			if err != nil {
 			if err != nil {
 				return nil, nil, err
 				return nil, nil, err
 			}
 			}
 		}
 		}
+		return resultSlice, nil, nil
 
 
 	case map[string]string:
 	case map[string]string:
-		if sqlExecutor.session.IsSqlFuc == true {
-			err := sqlExecutor.session.Begin()
+		if sqlsExecutor.session.IsSqlFuc == true {
+			err := sqlsExecutor.session.Begin()
 			if err != nil {
 			if err != nil {
 				return nil, nil, err
 				return nil, nil, err
 			}
 			}
 		}
 		}
+		sqlsMap := sqlsExecutor.sqls.(map[string]string)
+		n := len(sqlsMap)
+		resultsMap := make(map[string][]map[string]interface{}, n)
+		parmasMap := make(map[string]map[string]interface{}, n)
+		switch sqlsExecutor.parmas.(type) {
+		case map[string]map[string]interface{}:
+			parmasMap = sqlsExecutor.parmas.(map[string]map[string]interface{})
+
+		default:
+			if sqlsExecutor.session.IsSqlFuc == true {
+				err := sqlsExecutor.session.Rollback()
+				if err != nil {
+					return nil, nil, err
+				}
+			}
+			return nil, nil, ErrParamsType
+		}
+
+		for k, _ := range sqlsMap {
+			sqlStr := strings.TrimSpace(sqlsMap[k])
+			sqlCmd := strings.ToLower(strings.Split(sqlStr, " ")[0])
+			if parmasMap[k] == nil {
+				switch sqlCmd {
+				case "select", "desc":
+					model_1_results = sqlsExecutor.session.Sql(sqlStr).Query()
+
+				case "insert", "delete", "update", "create":
+					model_2_results, err = sqlsExecutor.session.Sql(sqlStr).Execute()
+					sqlModel = 2
+				}
+			} else {
+				key := NewV4().String() + time.Now().String()
+				sqlsExecutor.session.Engine.AddSql(key, sqlStr)
+				parmaMap := parmasMap[k]
+				switch sqlCmd {
+				case "select", "desc":
+					model_1_results = sqlsExecutor.session.SqlMapClient(key, &parmaMap).Query()
+				case "insert", "delete", "update", "create":
+					model_2_results, err = sqlsExecutor.session.SqlMapClient(key, &parmaMap).Execute()
+					sqlModel = 2
+				}
+				sqlsExecutor.session.Engine.RemoveSql(key)
+			}
+
+			if sqlModel == 1 {
+				if model_1_results.Error != nil {
+					if sqlsExecutor.session.IsSqlFuc == true {
+						err := sqlsExecutor.session.Rollback()
+						if err != nil {
+							return nil, nil, err
+						}
+					}
+					return nil, nil, model_1_results.Error
+				}
+
+				resultsMap[k] = make([]map[string]interface{}, len(model_1_results.Results))
+				resultsMap[k] = model_1_results.Results
+
+			} else {
+				if err != nil {
+					if sqlsExecutor.session.IsSqlFuc == true {
+						err := sqlsExecutor.session.Rollback()
+						if err != nil {
+							return nil, nil, err
+						}
+					}
+					return nil, nil, err
+				}
+
+				resultMap := make([]map[string]interface{}, 1)
+				resultMap[0] = make(map[string]interface{})
+
+				//todo all database support LastInsertId
+				LastInsertId, _ := model_2_results.LastInsertId()
+
+				resultMap[0]["LastInsertId"] = LastInsertId
+				RowsAffected, err := model_2_results.RowsAffected()
+				if err != nil {
+					if sqlsExecutor.session.IsSqlFuc == true {
+						err := sqlsExecutor.session.Rollback()
+						if err != nil {
+							return nil, nil, err
+						}
+					}
+					return nil, nil, err
+				}
+				resultMap[0]["RowsAffected"] = RowsAffected
+				resultsMap[k] = make([]map[string]interface{}, 1)
+				resultsMap[k] = resultMap
+
+			}
+		}
+		if sqlsExecutor.session.IsSqlFuc == true {
+			err := sqlsExecutor.session.Commit()
+			if err != nil {
+				return nil, nil, err
+			}
+		}
+		return nil, resultsMap, nil
 
 
 	}
 	}
 
 
 	return nil, nil, nil
 	return nil, nil, nil
 }
 }
-
-//func (sqlExecutor *SqlExecutor) Execute() (interface{}, error) {
-
-//	switch sqlExecutor.sqls.(type) {
-//	case string:
-//		sqlstr := strings.TrimLeft(sqlExecutor.sqls.(string), " \n")
-//		sqlCmd := strings.ToLower(strings.Split(sqlstr, " ")[0])
-//		switch sqlExecutor.parmasCount {
-//		case 0:
-//			switch sqlCmd {
-//			case "select", "desc":
-//				rsults := sqlExecutor.session.Sql(sqlstr).Query()
-//				if rsults.Error != nil {
-//					return nil, rsults.Error
-//				}
-//				return rsults.Results, nil
-//			case "insert", "delete", "update":
-//				return sqlExecutor.session.Sql(sqlstr).Execute()
-//			}
-//		case 1:
-//			switch sqlExecutor.parmas.(type) {
-//			case map[string]interface{}:
-//				switch sqlCmd {
-//				case "select", "desc":
-
-//				case "insert", "delete", "update":
-
-//				}
-//			default:
-//				switch sqlCmd {
-//				case "select", "desc":
-
-//				case "insert", "delete", "update":
-
-//				}
-//			}
-//		default:
-//			switch sqlCmd {
-//			case "select", "desc":
-
-//			case "insert", "delete", "update":
-
-//			}
-//		}
-//	case []string:
-//		if sqlExecutor.session.IsSqlFuc == true {
-//			err := sqlExecutor.session.Begin()
-//			if err != nil {
-//				return nil, err
-//			}
-//		}
-
-//	case map[string]string:
-//		if sqlExecutor.session.IsSqlFuc == true {
-//			err := sqlExecutor.session.Begin()
-//			if err != nil {
-//				return nil, err
-//			}
-//		}
-
-//	}
-
-//	return 1, nil
-//}

+ 80 - 0
sqlmap.go

@@ -266,3 +266,83 @@ func (sqlMap *SqlMap) batchRemoveSql(key []string) {
 		delete(sqlMap.Sql, v)
 		delete(sqlMap.Sql, v)
 	}
 	}
 }
 }
+
+func (engine *Engine) GetSql(key string) string {
+	return engine.sqlMap.getSql(key)
+}
+
+func (sqlMap *SqlMap) getSql(key string) string {
+	return sqlMap.Sql[key]
+}
+
+func (engine *Engine) GetSqlMap(keys ...interface{}) map[string]string {
+	return engine.sqlMap.getSqlMap(keys...)
+}
+
+func (sqlMap *SqlMap) getSqlMap(keys ...interface{}) map[string]string {
+	var resultSqlMap map[string]string
+	i := len(keys)
+	if i == 0 {
+		return sqlMap.Sql
+	}
+
+	if i == 1 {
+		switch keys[0].(type) {
+		case string:
+			resultSqlMap = make(map[string]string, 1)
+		case []string:
+			ks := keys[0].([]string)
+			n := len(ks)
+			resultSqlMap = make(map[string]string, n)
+		}
+	} else {
+		resultSqlMap = make(map[string]string, i)
+	}
+
+	for k, _ := range keys {
+		switch keys[k].(type) {
+		case string:
+			key := keys[k].(string)
+			resultSqlMap[key] = sqlMap.Sql[key]
+		case []string:
+			ks := keys[k].([]string)
+			for _, v := range ks {
+				resultSqlMap[v] = sqlMap.Sql[v]
+			}
+		}
+	}
+
+	return resultSqlMap
+}
+
+//	if i == 1 {
+//		switch keys[0].(type) {
+//		case string:
+//			key := keys[0].(string)
+//			resultSqlMap = make(map[string]string, 1)
+//			resultSqlMap[key] = sqlMap.Sql[key]
+//		case []string:
+//			ks := keys[0].([]string)
+//			l := len(ks)
+//			resultSqlMap = make(map[string]string, l)
+//			for _, v := range ks {
+//				resultSqlMap[v] = sqlMap.Sql[v]
+//			}
+//		}
+//	} else if i > 1 {
+//		resultSqlMap = make(map[string]string, i)
+//		for k, _ := range keys {
+//			switch keys[k].(type) {
+//			case string:
+//				key := keys[k].(string)
+//				resultSqlMap[key] = sqlMap.Sql[key]
+//			case []string:
+//				ks := keys[k].([]string)
+//				for _, v := range ks {
+//					resultSqlMap[v] = sqlMap.Sql[v]
+//				}
+
+//			}
+//		}
+
+//	}

+ 311 - 0
sqlmaps_executor.go

@@ -0,0 +1,311 @@
+package xorm
+
+import (
+	"database/sql"
+	"strings"
+)
+
+type SqlMapsExecutor struct {
+	session *Session
+	sqlkeys interface{}
+	parmas  interface{}
+	err     error
+}
+
+func (sqlMapsExecutor *SqlMapsExecutor) Execute() ([][]map[string]interface{}, map[string][]map[string]interface{}, error) {
+	if sqlMapsExecutor.err != nil {
+		return nil, nil, sqlMapsExecutor.err
+	}
+
+	var model_1_results ResultMap
+	var model_2_results sql.Result
+	var err error
+
+	sqlModel := 1
+
+	switch sqlMapsExecutor.sqlkeys.(type) {
+	case string:
+		sqlkey := strings.TrimSpace(sqlMapsExecutor.sqlkeys.(string))
+		sqlStr := sqlMapsExecutor.session.Engine.GetSql(sqlkey)
+		sqlCmd := strings.ToLower(strings.Split(sqlStr, " ")[0])
+
+		if sqlMapsExecutor.parmas == nil {
+			switch sqlCmd {
+			case "select", "desc":
+				model_1_results = sqlMapsExecutor.session.SqlMapClient(sqlkey).Query()
+			case "insert", "delete", "update", "create":
+				model_2_results, err = sqlMapsExecutor.session.SqlMapClient(sqlkey).Execute()
+				sqlModel = 2
+			}
+		} else {
+			switch sqlMapsExecutor.parmas.(type) {
+			case []map[string]interface{}:
+				parmaMap, ok := sqlMapsExecutor.parmas.([]map[string]interface{})
+				if !ok {
+					return nil, nil, ErrParamsType
+				}
+				switch sqlCmd {
+				case "select", "desc":
+					model_1_results = sqlMapsExecutor.session.SqlMapClient(sqlkey, &parmaMap[0]).Query()
+
+				case "insert", "delete", "update", "create":
+					model_2_results, err = sqlMapsExecutor.session.SqlMapClient(sqlkey, &parmaMap[0]).Execute()
+					sqlModel = 2
+				}
+
+			case map[string]interface{}:
+				parmaMap, ok := sqlMapsExecutor.parmas.(map[string]interface{})
+				if !ok {
+					return nil, nil, ErrParamsType
+				}
+
+				switch sqlCmd {
+				case "select", "desc":
+					model_1_results = sqlMapsExecutor.session.SqlMapClient(sqlkey, &parmaMap).Query()
+				case "insert", "delete", "update", "create":
+					model_2_results, err = sqlMapsExecutor.session.SqlMapClient(sqlkey, &parmaMap).Execute()
+					sqlModel = 2
+				}
+
+			default:
+				return nil, nil, ErrParamsType
+			}
+		}
+
+		resultSlice := make([][]map[string]interface{}, 1)
+
+		if sqlModel == 1 {
+			if model_1_results.Error != nil {
+				return nil, nil, model_1_results.Error
+			}
+
+			resultSlice[0] = make([]map[string]interface{}, len(model_1_results.Results))
+			resultSlice[0] = model_1_results.Results
+			return resultSlice, nil, nil
+		} else {
+			if err != nil {
+				return nil, nil, err
+			}
+
+			resultMap := make([]map[string]interface{}, 1)
+			resultMap[0] = make(map[string]interface{})
+
+			//todo all database support LastInsertId
+			LastInsertId, _ := model_2_results.LastInsertId()
+
+			resultMap[0]["LastInsertId"] = LastInsertId
+			RowsAffected, err := model_2_results.RowsAffected()
+			if err != nil {
+				return nil, nil, err
+			}
+			resultMap[0]["RowsAffected"] = RowsAffected
+			resultSlice[0] = resultMap
+			return resultSlice, nil, nil
+		}
+	case []string:
+		if sqlMapsExecutor.session.IsSqlFuc == true {
+			err := sqlMapsExecutor.session.Begin()
+			if err != nil {
+				return nil, nil, err
+			}
+		}
+		sqlkeysSlice := sqlMapsExecutor.sqlkeys.([]string)
+		n := len(sqlkeysSlice)
+		resultSlice := make([][]map[string]interface{}, n)
+		parmaSlice := make([]map[string]interface{}, n)
+		switch sqlMapsExecutor.parmas.(type) {
+		case []map[string]interface{}:
+			parmaSlice = sqlMapsExecutor.parmas.([]map[string]interface{})
+
+		default:
+			if sqlMapsExecutor.session.IsSqlFuc == true {
+				err := sqlMapsExecutor.session.Rollback()
+				if err != nil {
+					return nil, nil, err
+				}
+			}
+			return nil, nil, ErrParamsType
+		}
+
+		for i, _ := range sqlkeysSlice {
+			sqlkey := strings.TrimSpace(sqlkeysSlice[i])
+			sqlStr := sqlMapsExecutor.session.Engine.GetSql(sqlkey)
+			sqlCmd := strings.ToLower(strings.Split(sqlStr, " ")[0])
+			if parmaSlice[i] == nil {
+				switch sqlCmd {
+				case "select", "desc":
+					model_1_results = sqlMapsExecutor.session.SqlMapClient(sqlkey).Query()
+				case "insert", "delete", "update", "create":
+					model_2_results, err = sqlMapsExecutor.session.SqlMapClient(sqlkey).Execute()
+					sqlModel = 2
+				}
+			} else {
+				switch sqlCmd {
+				case "select", "desc":
+					model_1_results = sqlMapsExecutor.session.SqlMapClient(sqlkey, &parmaSlice[i]).Query()
+				case "insert", "delete", "update", "create":
+					model_2_results, err = sqlMapsExecutor.session.SqlMapClient(sqlkey, &parmaSlice[i]).Execute()
+					sqlModel = 2
+				}
+			}
+
+			if sqlModel == 1 {
+				if model_1_results.Error != nil {
+					if sqlMapsExecutor.session.IsSqlFuc == true {
+						err := sqlMapsExecutor.session.Rollback()
+						if err != nil {
+							return nil, nil, err
+						}
+					}
+					return nil, nil, model_1_results.Error
+				}
+
+				resultSlice[i] = make([]map[string]interface{}, len(model_1_results.Results))
+				resultSlice[i] = model_1_results.Results
+
+			} else {
+				if err != nil {
+					if sqlMapsExecutor.session.IsSqlFuc == true {
+						err := sqlMapsExecutor.session.Rollback()
+						if err != nil {
+							return nil, nil, err
+						}
+					}
+					return nil, nil, err
+				}
+
+				resultMap := make([]map[string]interface{}, 1)
+				resultMap[0] = make(map[string]interface{})
+
+				//todo all database support LastInsertId
+				LastInsertId, _ := model_2_results.LastInsertId()
+
+				resultMap[0]["LastInsertId"] = LastInsertId
+				RowsAffected, err := model_2_results.RowsAffected()
+				if err != nil {
+					return nil, nil, err
+				}
+				resultMap[0]["RowsAffected"] = RowsAffected
+				resultSlice[i] = make([]map[string]interface{}, 1)
+				resultSlice[i] = resultMap
+
+			}
+		}
+
+		if sqlMapsExecutor.session.IsSqlFuc == true {
+			err := sqlMapsExecutor.session.Commit()
+			if err != nil {
+				return nil, nil, err
+			}
+		}
+		return resultSlice, nil, nil
+
+	case map[string]string:
+		if sqlMapsExecutor.session.IsSqlFuc == true {
+			err := sqlMapsExecutor.session.Begin()
+			if err != nil {
+				return nil, nil, err
+			}
+		}
+		sqlkeysMap := sqlMapsExecutor.sqlkeys.(map[string]string)
+		n := len(sqlkeysMap)
+		resultsMap := make(map[string][]map[string]interface{}, n)
+		parmasMap := make(map[string]map[string]interface{}, n)
+		switch sqlMapsExecutor.parmas.(type) {
+		case map[string]map[string]interface{}:
+			parmasMap = sqlMapsExecutor.parmas.(map[string]map[string]interface{})
+
+		default:
+			if sqlMapsExecutor.session.IsSqlFuc == true {
+				err := sqlMapsExecutor.session.Rollback()
+				if err != nil {
+					return nil, nil, err
+				}
+			}
+			return nil, nil, ErrParamsType
+		}
+
+		for k, _ := range sqlkeysMap {
+			sqlkey := strings.TrimSpace(sqlkeysMap[k])
+			sqlStr := sqlMapsExecutor.session.Engine.GetSql(sqlkey)
+			sqlCmd := strings.ToLower(strings.Split(sqlStr, " ")[0])
+			if parmasMap[k] == nil {
+				switch sqlCmd {
+				case "select", "desc":
+					model_1_results = sqlMapsExecutor.session.SqlMapClient(sqlkey).Query()
+
+				case "insert", "delete", "update", "create":
+					model_2_results, err = sqlMapsExecutor.session.SqlMapClient(sqlkey).Execute()
+					sqlModel = 2
+				}
+			} else {
+				parmaMap := parmasMap[k]
+				switch sqlCmd {
+				case "select", "desc":
+					model_1_results = sqlMapsExecutor.session.SqlMapClient(sqlkey, &parmaMap).Query()
+				case "insert", "delete", "update", "create":
+					model_2_results, err = sqlMapsExecutor.session.SqlMapClient(sqlkey, &parmaMap).Execute()
+					sqlModel = 2
+				}
+			}
+
+			if sqlModel == 1 {
+				if model_1_results.Error != nil {
+					if sqlMapsExecutor.session.IsSqlFuc == true {
+						err := sqlMapsExecutor.session.Rollback()
+						if err != nil {
+							return nil, nil, err
+						}
+					}
+					return nil, nil, model_1_results.Error
+				}
+
+				resultsMap[k] = make([]map[string]interface{}, len(model_1_results.Results))
+				resultsMap[k] = model_1_results.Results
+
+			} else {
+				if err != nil {
+					if sqlMapsExecutor.session.IsSqlFuc == true {
+						err := sqlMapsExecutor.session.Rollback()
+						if err != nil {
+							return nil, nil, err
+						}
+					}
+					return nil, nil, err
+				}
+
+				resultMap := make([]map[string]interface{}, 1)
+				resultMap[0] = make(map[string]interface{})
+
+				//todo all database support LastInsertId
+				LastInsertId, _ := model_2_results.LastInsertId()
+
+				resultMap[0]["LastInsertId"] = LastInsertId
+				RowsAffected, err := model_2_results.RowsAffected()
+				if err != nil {
+					if sqlMapsExecutor.session.IsSqlFuc == true {
+						err := sqlMapsExecutor.session.Rollback()
+						if err != nil {
+							return nil, nil, err
+						}
+					}
+					return nil, nil, err
+				}
+				resultMap[0]["RowsAffected"] = RowsAffected
+				resultsMap[k] = make([]map[string]interface{}, 1)
+				resultsMap[k] = resultMap
+
+			}
+		}
+		if sqlMapsExecutor.session.IsSqlFuc == true {
+			err := sqlMapsExecutor.session.Commit()
+			if err != nil {
+				return nil, nil, err
+			}
+		}
+		return nil, resultsMap, nil
+
+	}
+
+	return nil, nil, nil
+}

+ 50 - 1
sqltemplate.go

@@ -184,7 +184,6 @@ func (sqlTemplate *SqlTemplate) paresSqlTemplate(filename string, filepath strin
 
 
 func (engine *Engine) AddSqlTemplate(key string, sqlTemplateStr string) error {
 func (engine *Engine) AddSqlTemplate(key string, sqlTemplateStr string) error {
 	return engine.sqlTemplate.addSqlTemplate(key, sqlTemplateStr)
 	return engine.sqlTemplate.addSqlTemplate(key, sqlTemplateStr)
-
 }
 }
 
 
 func (sqlTemplate *SqlTemplate) addSqlTemplate(key string, sqlTemplateStr string) error {
 func (sqlTemplate *SqlTemplate) addSqlTemplate(key string, sqlTemplateStr string) error {
@@ -193,6 +192,7 @@ func (sqlTemplate *SqlTemplate) addSqlTemplate(key string, sqlTemplateStr string
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
+
 	sqlTemplate.checkNilAndInit()
 	sqlTemplate.checkNilAndInit()
 	sqlTemplate.Template[key] = template
 	sqlTemplate.Template[key] = template
 
 
@@ -276,3 +276,52 @@ func (sqlTemplate *SqlTemplate) batchRemoveSqlTemplate(key []string) {
 		delete(sqlTemplate.Template, v)
 		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
+}

+ 103 - 0
test/xorm_test.go

@@ -10,6 +10,7 @@ import (
 	"github.com/xormplus/xorm"
 	"github.com/xormplus/xorm"
 
 
 	_ "github.com/lib/pq"
 	_ "github.com/lib/pq"
+	//	"gopkg.in/flosch/pongo2.v3"
 )
 )
 
 
 type Article struct {
 type Article struct {
@@ -479,3 +480,105 @@ func Test_Query(t *testing.T) {
 
 
 	t.Log("[Test_Query]->rows:\n", result)
 	t.Log("[Test_Query]->rows:\n", result)
 }
 }
+
+func Test_Sql_Execute(t *testing.T) {
+
+	result, err := db.Sql("INSERT INTO categories VALUES (?, ?, ?, ?, ?)", 18, "xiaozhang", 1, 1, 1).Execute()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	t.Log("[Test_Sql_Execute]->rows:\n", result)
+}
+
+func Test_SqlMapClient_Execute(t *testing.T) {
+	db.AddSql("Test_SqlMapClient_Execute", "INSERT INTO categories VALUES (?id, ?name, ?counts, ?orders, ?pid)")
+	result, err := db.SqlMapClient("Test_SqlMapClient_Execute", &map[string]interface{}{"id": 19, "name": "xiaowang", "counts": 1, "orders": 1, "pid": 1}).Execute()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	t.Log("[Test_SqlMapClient_Execute]->rows:\n", result)
+}
+
+func Test_SqlTemplateClientt_Execute(t *testing.T) {
+	db.AddSqlTemplate("Test_SqlTemplateClientt_Execute", "INSERT INTO categories VALUES (?id, ?name, ?counts, ?orders, ?pid)")
+	result, err := db.SqlTemplateClient("Test_SqlTemplateClientt_Execute", &map[string]interface{}{"id": 20, "name": "laowang", "counts": 1, "orders": 1, "pid": 1}).Execute()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	t.Log("[Test_SqlTemplateClientt_Execute]->rows:\n", result)
+}
+
+func Test_GetSQL(t *testing.T) {
+	db.AddSql("Test_GetSQL_1", "select * from Test_GetSQL_1")
+	t.Log("[Test_GetSQL]->Test_GetSQL_1:\n", db.GetSql("Test_GetSQL_1"))
+	t.Log("[Test_GetSQL]->Test_GetSQL_2:\n", db.GetSql("Test_GetSQL_1"))
+}
+
+func Test_GetSqlMap(t *testing.T) {
+
+	t.Log("[Test_GetSqlMap]->3:\n")
+	t.Log(xorm.JSONString(db.GetSqlMap(3), true))
+	sqlmap := db.GetSqlMap(3)
+	t.Log("[Test_GetSqlMap]->len(sqlmap):\n", len(sqlmap))
+
+	db.AddSql("Test_GetSqlMap_1", "select * from Test_GetSqlMap_1")
+	db.AddSql("Test_GetSqlMap_2", "select * from Test_GetSqlMap_2")
+	db.AddSql("Test_GetSqlMap_3", "select * from Test_GetSqlMap_3")
+	db.AddSql("Test_GetSqlMap_4", "select * from Test_GetSqlMap_4")
+	db.AddSql("Test_GetSqlMap_5", "select * from Test_GetSqlMap_5")
+	t.Log("[Test_GetSqlMap]->init->3:\n")
+	t.Log(xorm.JSONString(db.GetSqlMap(3), true))
+	sqlmap = db.GetSqlMap(3)
+	t.Log("[Test_GetSqlMap]->init->len(sqlmap):\n", len(sqlmap))
+	t.Log("[Test_GetSqlMap]->Test_GetSqlMap_null:\n")
+	t.Log(xorm.JSONString(db.GetSqlMap("Test_GetSqlMap_null"), true))
+	t.Log("[Test_GetSqlMap]->Test_GetSqlMap_1:\n")
+	t.Log(xorm.JSONString(db.GetSqlMap("Test_GetSqlMap_1"), true))
+	t.Log("[Test_GetSqlMap]->Test_GetSqlMap_1,Test_GetSqlMap_3:\n")
+	t.Log(xorm.JSONString(db.GetSqlMap("Test_GetSqlMap_1", "Test_GetSqlMap_3"), true))
+	t.Log("[Test_GetSqlMap]->Test_GetSqlMap_1,Test_GetSqlMap_3,3:\n")
+	t.Log(xorm.JSONString(db.GetSqlMap("Test_GetSqlMap_1", "Test_GetSqlMap_3", 3), true))
+	t.Log("[Test_GetSqlMap]->Test_GetSqlMap_1,Test_GetSqlMap_3,3,Test_GetSqlMap_null:\n")
+	t.Log(xorm.JSONString(db.GetSqlMap("Test_GetSqlMap_1", "Test_GetSqlMap_3", 3, "Test_GetSqlMap_null"), true))
+	t.Log("[Test_GetSqlMap]->Test_GetSqlMap_1,Test_GetSqlMap_3,[]string{Test_GetSqlMap_2, Test_GetSqlMap_4}:\n")
+	t.Log(xorm.JSONString(db.GetSqlMap("Test_GetSqlMap_1", "Test_GetSqlMap_3", []string{"Test_GetSqlMap_2", "Test_GetSqlMap_4"}), true))
+	t.Log("[Test_GetSqlMap]->Test_GetSqlMap_1,Test_GetSqlMap_3,[]string{Test_GetSqlMap_2, Test_GetSqlMap_4},2:\n")
+	t.Log(xorm.JSONString(db.GetSqlMap("Test_GetSqlMap_1", "Test_GetSqlMap_3", []string{"Test_GetSqlMap_2", "Test_GetSqlMap_4"}, 2), true))
+	t.Log("[Test_GetSqlMap]->Test_GetSqlMap_1,Test_GetSqlMap_3,[]string{Test_GetSqlMap_2, Test_GetSqlMap_4},2 ,Test_GetSqlMap_null:\n")
+	t.Log(xorm.JSONString(db.GetSqlMap("Test_GetSqlMap_1", "Test_GetSqlMap_3", []string{"Test_GetSqlMap_2", "Test_GetSqlMap_4"}, 2, "Test_GetSqlMap_null"), true))
+}
+
+func Test_GetSqlTemplates(t *testing.T) {
+	t.Log("[GetSqlTemplates]->Test_GetSqlTemplates_1:\n")
+	t.Log(xorm.JSONString(db.GetSqlTemplates("Test_GetSqlTemplates_1"), true))
+	Test_GetSqlTemplates_1 := db.GetSqlTemplates("Test_GetSqlTemplates_1")["Test_GetSqlTemplates_1"]
+	if Test_GetSqlTemplates_1 == nil {
+		t.Log("Test_GetSqlTemplates_1 is nil")
+	}
+
+	t.Log("[Test_GetSqlMap]->len(sqlmap):\n", len(db.GetSqlTemplates("Test_GetSqlTemplates_1")))
+	db.AddSqlTemplate("Test_GetSqlTemplates_1", "select * from Test_GetSqlTemplates_1")
+	db.AddSqlTemplate("Test_GetSqlTemplates_2", "select * from Test_GetSqlTemplates_2")
+	db.AddSqlTemplate("Test_GetSqlTemplates_3", "select * from Test_GetSqlTemplates_3")
+	db.AddSqlTemplate("Test_GetSqlTemplates_4", "select * from Test_GetSqlTemplates_4")
+	db.AddSqlTemplate("Test_GetSqlTemplates_5", "select * from Test_GetSqlTemplates_5")
+	t.Log("[Test_GetSqlTemplates]->Test_GetSqlTemplates_1:\n")
+	t.Log(xorm.JSONString(db.GetSqlTemplates("Test_GetSqlTemplates_1"), true))
+	t.Log("[Test_GetSqlTemplates]->Test_GetSqlTemplates_1,Test_GetSqlTemplates_3:\n")
+	t.Log(xorm.JSONString(db.GetSqlTemplates("Test_GetSqlTemplates_1", "Test_GetSqlTemplates_3"), true))
+	t.Log("[Test_GetSqlTemplates]->Test_GetSqlTemplates_1,Test_GetSqlTemplates_3,3:\n")
+	t.Log(xorm.JSONString(db.GetSqlTemplates("Test_GetSqlTemplates_1", "Test_GetSqlTemplates_3", 3), true))
+	t.Log("[Test_GetSqlTemplates]->Test_GetSqlTemplates_1,Test_GetSqlTemplates_3,[]string{Test_GetSqlTemplates_2, Test_GetSqlTemplates_4}:\n")
+	t.Log(xorm.JSONString(db.GetSqlTemplates("Test_GetSqlTemplates_1", "Test_GetSqlTemplates_3", []string{"Test_GetSqlTemplates_2", "Test_GetSqlTemplates_4"}), true))
+	t.Log("[Test_GetSqlTemplates]->Test_GetSqlTemplates_1,Test_GetSqlTemplates_3,[]string{Test_GetSqlTemplates_2, Test_GetSqlTemplates_4},2:\n")
+	t.Log(xorm.JSONString(db.GetSqlTemplates("Test_GetSqlTemplates_1", "Test_GetSqlTemplates_3", []string{"Test_GetSqlTemplates_2", "Test_GetSqlTemplates_4"}, 2), true))
+
+	strSqlTemplate, err := db.GetSqlTemplates("Test_GetSqlTemplates_1")["Test_GetSqlTemplates_1"].Execute(nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	t.Log("[Test_GetSqlTemplates]->Test_GetSqlTemplates_1->strSqlTemplate:\n", strSqlTemplate)
+}