From 44deace06f33232a55e49f09bd6550ff8c15d3d2 Mon Sep 17 00:00:00 2001 From: xormplus Date: Sun, 24 Jun 2018 05:06:45 +0800 Subject: [PATCH] add QueryResult function --- engine.go | 7 ++++ interface.go | 2 + session_plus.go | 86 ++++++++++++++++++++++++++++++---------- session_query.go | 15 +++++++ session_raw.go | 53 +++++++++++++++++++++++++ sql_executor.go | 12 +++--- sqlmap.go | 2 +- sqlmap_xml.go | 2 +- sqlmaps_executor.go | 11 +++-- sqltemplates_executor.go | 10 ++--- xorm.go | 2 +- 11 files changed, 161 insertions(+), 41 deletions(-) diff --git a/engine.go b/engine.go index 1ffa534..3f3c5e4 100644 --- a/engine.go +++ b/engine.go @@ -1362,6 +1362,13 @@ func (engine *Engine) QueryValue(sqlorArgs ...interface{}) (resultsSlice []map[s return session.QueryValue(sqlorArgs...) } +// Query a raw sql and return records as Result +func (engine *Engine) QueryResult(sqlorArgs ...interface{}) (result *ResultValue) { + session := engine.NewSession() + defer session.Close() + return session.QueryResult(sqlorArgs...) +} + // QueryString runs a raw sql and return records as []map[string]string func (engine *Engine) QueryString(sqlorArgs ...interface{}) ([]map[string]string, error) { session := engine.NewSession() diff --git a/interface.go b/interface.go index 51e0244..e0038d4 100644 --- a/interface.go +++ b/interface.go @@ -52,6 +52,8 @@ type Interface interface { QueryBytes(sqlOrAgrs ...interface{}) (resultsSlice []map[string][]byte, err error) QueryInterface(sqlorArgs ...interface{}) ([]map[string]interface{}, error) QueryString(sqlorArgs ...interface{}) ([]map[string]string, error) + QueryValue(sqlorArgs ...interface{}) ([]map[string]Value, error) + QueryResult(sqlorArgs ...interface{}) (result *ResultValue) Rows(bean interface{}) (*Rows, error) SetExpr(string, string) *Session SQL(interface{}, ...interface{}) *Session diff --git a/session_plus.go b/session_plus.go index 6b37439..d224efa 100644 --- a/session_plus.go +++ b/session_plus.go @@ -17,6 +17,50 @@ import ( "github.com/xormplus/core" ) +type Record map[string]Value +type Result []Record + +type ResultValue struct { + Result Result + Error error +} + +func (resultValue *ResultValue) List() (Result, error) { + return resultValue.Result, resultValue.Error +} + +func (resultValue *ResultValue) Count() (int, error) { + if resultValue.Error != nil { + return 0, resultValue.Error + } + if resultValue.Result == nil { + return 0, nil + } + return len(resultValue.Result), nil +} + +func (resultValue *ResultValue) ListPage(firstResult int, maxResults int) (Result, error) { + if resultValue.Error != nil { + return nil, resultValue.Error + } + if resultValue.Result == nil { + return nil, nil + } + if firstResult > maxResults { + return nil, ErrParamsFormat + } + if firstResult < 0 { + return nil, ErrParamsFormat + } + if maxResults < 0 { + return nil, ErrParamsFormat + } + if maxResults > len(resultValue.Result) { + return nil, ErrParamsFormat + } + return resultValue.Result[(firstResult - 1):maxResults], resultValue.Error +} + type ResultBean struct { Has bool Result interface{} @@ -102,29 +146,29 @@ func (resultBean *ResultBean) XmlIndent(prefix string, indent string, recordTag } type ResultMap struct { - Results []map[string]interface{} - Error error + Result []map[string]interface{} + Error error } func (resultMap *ResultMap) List() ([]map[string]interface{}, error) { - return resultMap.Results, resultMap.Error + return resultMap.Result, resultMap.Error } func (resultMap *ResultMap) Count() (int, error) { if resultMap.Error != nil { return 0, resultMap.Error } - if resultMap.Results == nil { + if resultMap.Result == nil { return 0, nil } - return len(resultMap.Results), nil + return len(resultMap.Result), nil } func (resultMap *ResultMap) ListPage(firstResult int, maxResults int) ([]map[string]interface{}, error) { if resultMap.Error != nil { return nil, resultMap.Error } - if resultMap.Results == nil { + if resultMap.Result == nil { return nil, nil } if firstResult > maxResults { @@ -136,10 +180,10 @@ func (resultMap *ResultMap) ListPage(firstResult int, maxResults int) ([]map[str if maxResults < 0 { return nil, ErrParamsFormat } - if maxResults > len(resultMap.Results) { + if maxResults > len(resultMap.Result) { return nil, ErrParamsFormat } - return resultMap.Results[(firstResult - 1):maxResults], resultMap.Error + return resultMap.Result[(firstResult - 1):maxResults], resultMap.Error } func (resultMap *ResultMap) Json() (string, error) { @@ -147,14 +191,14 @@ func (resultMap *ResultMap) Json() (string, error) { if resultMap.Error != nil { return "", resultMap.Error } - return JSONString(resultMap.Results, true) + return JSONString(resultMap.Result, true) } func (resultMap *ResultMap) Xml() (string, error) { if resultMap.Error != nil { return "", resultMap.Error } - results, err := anyxml.Xml(resultMap.Results) + results, err := anyxml.Xml(resultMap.Result) if err != nil { return "", err } @@ -166,7 +210,7 @@ func (resultMap *ResultMap) XmlIndent(prefix string, indent string, recordTag st return "", resultMap.Error } - results, err := anyxml.XmlIndent(resultMap.Results, prefix, indent, recordTag) + results, err := anyxml.XmlIndent(resultMap.Result, prefix, indent, recordTag) if err != nil { return "", err } @@ -178,7 +222,7 @@ func (resultMap *ResultMap) SaveAsCSV(filename string, headers []string, perm os return resultMap.Error } - dataset, err := NewDatasetWithData(headers, resultMap.Results, true) + dataset, err := NewDatasetWithData(headers, resultMap.Result, true) if err != nil { return err } @@ -196,7 +240,7 @@ func (resultMap *ResultMap) SaveAsTSV(filename string, headers []string, perm os return resultMap.Error } - dataset, err := NewDatasetWithData(headers, resultMap.Results, true) + dataset, err := NewDatasetWithData(headers, resultMap.Result, true) if err != nil { return err } @@ -214,7 +258,7 @@ func (resultMap *ResultMap) SaveAsHTML(filename string, headers []string, perm o return resultMap.Error } - dataset, err := NewDatasetWithData(headers, resultMap.Results, true) + dataset, err := NewDatasetWithData(headers, resultMap.Result, true) if err != nil { return err } @@ -229,7 +273,7 @@ func (resultMap *ResultMap) SaveAsXML(filename string, headers []string, perm os return resultMap.Error } - dataset, err := NewDatasetWithData(headers, resultMap.Results, false) + dataset, err := NewDatasetWithData(headers, resultMap.Result, false) if err != nil { return err } @@ -247,7 +291,7 @@ func (resultMap *ResultMap) SaveAsXMLWithTagNamePrefixIndent(tagName string, pri return resultMap.Error } - dataset, err := NewDatasetWithData(headers, resultMap.Results, false) + dataset, err := NewDatasetWithData(headers, resultMap.Result, false) if err != nil { return err } @@ -265,7 +309,7 @@ func (resultMap *ResultMap) SaveAsYAML(filename string, headers []string, perm o return resultMap.Error } - dataset, err := NewDatasetWithData(headers, resultMap.Results, false) + dataset, err := NewDatasetWithData(headers, resultMap.Result, false) if err != nil { return err } @@ -283,7 +327,7 @@ func (resultMap *ResultMap) SaveAsJSON(filename string, headers []string, perm o return resultMap.Error } - dataset, err := NewDatasetWithData(headers, resultMap.Results, false) + dataset, err := NewDatasetWithData(headers, resultMap.Result, false) if err != nil { return err } @@ -301,7 +345,7 @@ func (resultMap *ResultMap) SaveAsXLSX(filename string, headers []string, perm o return resultMap.Error } - dataset, err := NewDatasetWithData(headers, resultMap.Results, true) + dataset, err := NewDatasetWithData(headers, resultMap.Result, true) if err != nil { return err } @@ -504,7 +548,7 @@ func (session *Session) Query() *ResultMap { } } } - r := &ResultMap{Results: result, Error: err} + r := &ResultMap{Result: result, Error: err} return r } @@ -548,7 +592,7 @@ func (session *Session) QueryWithDateFormat(dateFormat string) *ResultMap { } } } - r := &ResultMap{Results: result, Error: err} + r := &ResultMap{Result: result, Error: err} return r } diff --git a/session_query.go b/session_query.go index b5ede0f..789d461 100644 --- a/session_query.go +++ b/session_query.go @@ -121,6 +121,21 @@ func (session *Session) QueryValue(sqlorArgs ...interface{}) ([]map[string]Value } +// Query runs a raw sql and return records as ResultValue +func (session *Session) QueryResult(sqlorArgs ...interface{}) *ResultValue { + if session.isAutoClose { + defer session.Close() + } + + sqlStr, args, err := session.genQuerySQL(sqlorArgs...) + if err != nil { + return &ResultValue{Error: err} + } + + result, err := session.queryResult(sqlStr, args...) + return &ResultValue{Result: result, Error: err} +} + // Query runs a raw sql and return records as []map[string][]byte func (session *Session) QueryBytes(sqlorArgs ...interface{}) ([]map[string][]byte, error) { if session.isAutoClose { diff --git a/session_raw.go b/session_raw.go index 17d4bd1..27d9f4c 100644 --- a/session_raw.go +++ b/session_raw.go @@ -158,6 +158,33 @@ func row2mapValue(rows *core.Rows, fields []string) (resultsMap map[string]Value return result, nil } +func row2Record(rows *core.Rows, fields []string) (record Record, err error) { + record = make(Record) + scanResultContainers := make([]interface{}, len(fields)) + for i := 0; i < len(fields); i++ { + var scanResultContainer interface{} + scanResultContainers[i] = &scanResultContainer + } + if err := rows.Scan(scanResultContainers...); err != nil { + return nil, err + } + + for ii, key := range fields { + rawValue := reflect.Indirect(reflect.ValueOf(scanResultContainers[ii])) + if rawValue.Interface() == nil { + record[key] = nil + continue + } + + if data, err := value2Value(&rawValue); err == nil { + record[key] = data + } else { + return nil, err // !nashtsai! REVIEW, should return err or just error log? + } + } + return record, nil +} + func rows2maps(rows *core.Rows) (resultsSlice []map[string][]byte, err error) { fields, err := rows.Columns() if err != nil { @@ -190,6 +217,22 @@ func rows2mapsValue(rows *core.Rows) (resultsSlice []map[string]Value, err error return resultsSlice, nil } +func rows2Result(rows *core.Rows) (result Result, err error) { + fields, err := rows.Columns() + if err != nil { + return nil, err + } + for rows.Next() { + r, err := row2mapValue(rows, fields) + if err != nil { + return nil, err + } + result = append(result, r) + } + + return result, nil +} + func (session *Session) queryBytes(sqlStr string, args ...interface{}) ([]map[string][]byte, error) { rows, err := session.queryRows(sqlStr, args...) if err != nil { @@ -210,6 +253,16 @@ func (session *Session) queryValue(sqlStr string, args ...interface{}) ([]map[st return rows2mapsValue(rows) } +func (session *Session) queryResult(sqlStr string, args ...interface{}) (Result, error) { + rows, err := session.queryRows(sqlStr, args...) + if err != nil { + return nil, err + } + defer rows.Close() + + return rows2Result(rows) +} + func (session *Session) exec(sqlStr string, args ...interface{}) (sql.Result, error) { defer session.resetStatement() diff --git a/sql_executor.go b/sql_executor.go index e0fb009..525dad7 100644 --- a/sql_executor.go +++ b/sql_executor.go @@ -108,8 +108,8 @@ func (sqlsExecutor *SqlsExecutor) Execute() ([][]map[string]interface{}, map[str return nil, nil, model_1_results.Error } - resultSlice[0] = make([]map[string]interface{}, len(model_1_results.Results)) - resultSlice[0] = model_1_results.Results + resultSlice[0] = make([]map[string]interface{}, len(model_1_results.Result)) + resultSlice[0] = model_1_results.Result if sqlsExecutor.session.isSqlFunc == true { err1 := sqlsExecutor.session.Commit() if err1 != nil { @@ -185,7 +185,7 @@ func (sqlsExecutor *SqlsExecutor) Execute() ([][]map[string]interface{}, map[str return nil, nil, model_1_results.Error } - resultSlice[i] = model_1_results.Results + resultSlice[i] = model_1_results.Result } else if sqlModel == 2 { if err != nil { @@ -282,7 +282,7 @@ func (sqlsExecutor *SqlsExecutor) Execute() ([][]map[string]interface{}, map[str return nil, nil, model_1_results.Error } - resultSlice[i] = model_1_results.Results + resultSlice[i] = model_1_results.Result } else if sqlModel == 2 { if err != nil { @@ -368,7 +368,7 @@ func (sqlsExecutor *SqlsExecutor) Execute() ([][]map[string]interface{}, map[str return nil, nil, model_1_results.Error } - resultsMap[k] = model_1_results.Results + resultsMap[k] = model_1_results.Result } else if sqlModel == 2 { if err != nil { @@ -471,7 +471,7 @@ func (sqlsExecutor *SqlsExecutor) Execute() ([][]map[string]interface{}, map[str return nil, nil, model_1_results.Error } - resultsMap[k] = model_1_results.Results + resultsMap[k] = model_1_results.Result } else if sqlModel == 2 { if err != nil { diff --git a/sqlmap.go b/sqlmap.go index 40cc5c0..32eed53 100644 --- a/sqlmap.go +++ b/sqlmap.go @@ -72,7 +72,7 @@ func (sqlMap *SqlMap) paresSql(filepath string) error { sqlMap.checkNilAndInit() if strings.HasSuffix(filepath, sqlMap.Extension["xml"]) { - var result Result + var result XmlSql err = xml.Unmarshal(content, &result) if err != nil { return err diff --git a/sqlmap_xml.go b/sqlmap_xml.go index aae1ec4..611e0aa 100644 --- a/sqlmap_xml.go +++ b/sqlmap_xml.go @@ -5,7 +5,7 @@ type XmlSqlMap struct { extension string } -type Result struct { +type XmlSql struct { Sql []Sql `xml:"sql"` } diff --git a/sqlmaps_executor.go b/sqlmaps_executor.go index ffe6a91..ccedf02 100644 --- a/sqlmaps_executor.go +++ b/sqlmaps_executor.go @@ -105,7 +105,7 @@ func (sqlMapsExecutor *SqlMapsExecutor) Execute() ([][]map[string]interface{}, m return nil, nil, model_1_results.Error } - resultSlice[0] = model_1_results.Results + resultSlice[0] = model_1_results.Result if sqlMapsExecutor.session.isSqlFunc == true { err1 := sqlMapsExecutor.session.Commit() @@ -152,7 +152,6 @@ func (sqlMapsExecutor *SqlMapsExecutor) Execute() ([][]map[string]interface{}, m resultSlice[0] = nil } - case []string: sqlkeysSlice := sqlMapsExecutor.sqlkeys.([]string) n := len(sqlkeysSlice) @@ -188,7 +187,7 @@ func (sqlMapsExecutor *SqlMapsExecutor) Execute() ([][]map[string]interface{}, m return nil, nil, model_1_results.Error } - resultSlice[i] = model_1_results.Results + resultSlice[i] = model_1_results.Result } else if sqlModel == 2 { if err != nil { @@ -283,7 +282,7 @@ func (sqlMapsExecutor *SqlMapsExecutor) Execute() ([][]map[string]interface{}, m return nil, nil, model_1_results.Error } - resultSlice[i] = model_1_results.Results + resultSlice[i] = model_1_results.Result } else if sqlModel == 2 { if err != nil { @@ -367,7 +366,7 @@ func (sqlMapsExecutor *SqlMapsExecutor) Execute() ([][]map[string]interface{}, m return nil, nil, model_1_results.Error } - resultsMap[k] = model_1_results.Results + resultsMap[k] = model_1_results.Result } else if sqlModel == 2 { if err != nil { @@ -463,7 +462,7 @@ func (sqlMapsExecutor *SqlMapsExecutor) Execute() ([][]map[string]interface{}, m return nil, nil, model_1_results.Error } - resultsMap[k] = model_1_results.Results + resultsMap[k] = model_1_results.Result } else if sqlModel == 2 { if err != nil { diff --git a/sqltemplates_executor.go b/sqltemplates_executor.go index b2c97ec..682ebab 100644 --- a/sqltemplates_executor.go +++ b/sqltemplates_executor.go @@ -128,7 +128,7 @@ func (sqlTemplatesExecutor *SqlTemplatesExecutor) Execute() ([][]map[string]inte return nil, nil, model_1_results.Error } - resultSlice[0] = model_1_results.Results + resultSlice[0] = model_1_results.Result if sqlTemplatesExecutor.session.isSqlFunc == true { err1 := sqlTemplatesExecutor.session.Commit() if err1 != nil { @@ -209,7 +209,7 @@ func (sqlTemplatesExecutor *SqlTemplatesExecutor) Execute() ([][]map[string]inte return nil, nil, model_1_results.Error } - resultSlice[i] = model_1_results.Results + resultSlice[i] = model_1_results.Result } else if sqlModel == 2 { if err != nil { @@ -315,7 +315,7 @@ func (sqlTemplatesExecutor *SqlTemplatesExecutor) Execute() ([][]map[string]inte return nil, nil, model_1_results.Error } - resultSlice[i] = model_1_results.Results + resultSlice[i] = model_1_results.Result } else if sqlModel == 2 { if err != nil { @@ -410,7 +410,7 @@ func (sqlTemplatesExecutor *SqlTemplatesExecutor) Execute() ([][]map[string]inte return nil, nil, model_1_results.Error } - resultsMap[k] = model_1_results.Results + resultsMap[k] = model_1_results.Result } else if sqlModel == 2 { if err != nil { @@ -516,7 +516,7 @@ func (sqlTemplatesExecutor *SqlTemplatesExecutor) Execute() ([][]map[string]inte return nil, nil, model_1_results.Error } - resultsMap[k] = model_1_results.Results + resultsMap[k] = model_1_results.Result } else if sqlModel == 2 { if err != nil { diff --git a/xorm.go b/xorm.go index 5dd2897..b9b93e2 100644 --- a/xorm.go +++ b/xorm.go @@ -17,7 +17,7 @@ import ( const ( // Version show the xorm's version - Version string = "0.7.0.0608" + Version string = "0.7.0.0624" ) func regDrvsNDialects() bool {