调试通过,增加 message
diff --git a/message.go b/message.go
new file mode 100644
index 0000000..725155d
--- /dev/null
+++ b/message.go
@@ -0,0 +1,300 @@
+// message.go
+package swservice
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ // "reflect"
+ "strconv"
+)
+
+type MessageWriter struct {
+ FuncNo int `json: "funcno"`
+ Attributes map[string]interface{}
+ ColumnNames []string
+ ColumnDescs []string
+ RowData []map[string]interface{}
+ Row map[string]interface{}
+}
+
+func NewMessageWriter(funcno int) *MessageWriter {
+ return &MessageWriter{
+ FuncNo: funcno,
+ Attributes: make(map[string]interface{}),
+ ColumnNames: make([]string, 0),
+ ColumnDescs: make([]string, 0),
+ RowData: make([]map[string]interface{}, 0)}
+}
+func (m *MessageWriter) SetAttr(name string, value interface{}) {
+ m.Attributes[name] = value
+}
+func (m *MessageWriter) AddCol(name string, value interface{}) {
+ if m.Row == nil {
+ m.Row = make(map[string]interface{})
+ }
+ m.Row[name] = value
+}
+
+func is_contains(k string, slice []string) bool {
+ for _, v := range slice {
+ if k == v {
+ return true
+ }
+ }
+ return false
+}
+
+func (m *MessageWriter) AddRow() {
+ if m.Row == nil {
+ return
+ }
+ // data := make([]interface{}, 0)
+ // if len(m.ColumnNames) == 0 {
+ // for k, v := range m.Row {
+ // m.ColumnNames = append(m.ColumnNames, k)
+ // data = append(data, v)
+ // }
+ // } else {
+ // for _, n := range m.ColumnNames {
+ // if v, ok := m.Row[n]; !ok {
+ // data = append(data, nil)
+ // } else {
+ // data = append(data, v)
+ // }
+ // }
+ // for k, v := range m.Row {
+ // if !is_contains(k, m.ColumnNames) {
+ // m.ColumnNames = append(m.ColumnNames, k)
+ // data = append(data, v)
+ // }
+ // }
+ // }
+ // m.RowData = append(m.RowData, data)
+ m.RowData = append(m.RowData, m.Row)
+ m.Row = nil
+}
+
+func (m *MessageWriter) serialize_rowdata() {
+ m.ColumnNames = make([]string, 0)
+ for _, row := range m.RowData {
+ for k, _ := range row {
+ if !is_contains(k, m.ColumnNames) {
+ m.ColumnNames = append(m.ColumnNames, k)
+ }
+ }
+ }
+ rows := make([][]interface{}, 0)
+ for _, row := range m.RowData {
+ data := make([]interface{}, 0)
+ for _, k := range m.ColumnNames {
+ if v, ok := row[k]; !ok {
+ data = append(data, nil)
+ } else {
+ data = append(data, v)
+ }
+ }
+ rows = append(rows, data)
+ }
+ m.Attributes["rowdata"] = rows
+ m.Attributes["rowcnt"] = len(rows)
+}
+
+func (m *MessageWriter) Serialize() string {
+ m.Attributes["funcno"] = m.FuncNo
+ m.serialize_rowdata()
+ m.Attributes["colnames"] = m.ColumnNames
+ m.Attributes["coldescs"] = m.ColumnNames
+ m.Attributes["colcnt"] = len(m.ColumnNames)
+ r, _ := json.Marshal(m.Attributes)
+ return string(r)
+}
+
+//////////////////////////////////////////////////////////////////////
+type MessageReader struct {
+ FuncNo int
+ RetCode int
+ RetMsg string
+ DBMsg string
+ ErrName string
+ ColumnNames []string
+ ColumnDescs []string
+ Attributes map[string]interface{}
+ RowData []map[string]interface{}
+ RowIndex int
+}
+
+func get_value_as_int(value interface{}) int {
+ // vtype := reflect.TypeOf(value)
+ switch value.(type) {
+ case int:
+ return value.(int)
+ case float64:
+ return int(value.(float64))
+ case string:
+ i, _ := strconv.Atoi(value.(string))
+ return i
+ default:
+ panic("Error")
+ }
+}
+
+func get_column_names(data interface{}) (result []string) {
+ if data == nil {
+ return nil
+ }
+ names := data.([]interface{})
+ result = make([]string, 0)
+ for _, v := range names {
+ result = append(result, v.(string))
+ }
+ return
+}
+
+func convert_to_int(value interface{}) int {
+ if value == nil {
+ return 0
+ }
+ switch value.(type) {
+ case int:
+ return value.(int)
+ case float64:
+ return int(value.(float64))
+ case string:
+ i, _ := strconv.Atoi(value.(string))
+ return i
+ default:
+ return 0
+ }
+}
+
+func convert_to_string(value interface{}) string {
+ if value == nil {
+ return ""
+ }
+ return fmt.Sprintf("%v", value)
+}
+
+func NewMessageReader(data []byte) *MessageReader {
+ var s interface{}
+ err := json.Unmarshal(data, &s)
+ if err != nil {
+ return nil
+ }
+ obj := s.(map[string]interface{})
+
+ m := &MessageReader{Attributes: make(map[string]interface{}),
+ RowData: make([]map[string]interface{}, 0)}
+ m.FuncNo = convert_to_int(obj["funcno"])
+ m.RetCode = convert_to_int(obj["retcode"])
+ m.RetMsg = convert_to_string(obj["retmsg"])
+ m.DBMsg = convert_to_string(obj["dbmsg"])
+ m.ErrName = convert_to_string(obj["errname"])
+
+ m.ColumnNames = get_column_names(obj["colnames"])
+ m.ColumnDescs = get_column_names(obj["coldescs"])
+
+ if rowdata, err := obj["rowdata"]; err {
+ if rowdata != nil {
+ for _, raw := range rowdata.([]interface{}) {
+ row := raw.([]interface{})
+ data := make(map[string]interface{})
+ for idx, v := range row {
+ data[m.ColumnNames[idx]] = v
+ }
+ m.RowData = append(m.RowData, data)
+ }
+ }
+ }
+ reverseKey := map[string]bool{
+ "funcno": true,
+ "colnames": true,
+ "coldescs": true,
+ "rowcnt": true,
+ "colcnt": true,
+ "rowdata": true,
+ "retcode": true,
+ "retmsg": true,
+ "dbmsg": true,
+ "errname": true}
+
+ for k, v := range obj {
+ if _, ok := reverseKey[k]; ok {
+ continue
+ }
+ m.Attributes[k] = v
+ }
+ return m
+}
+
+func (m *MessageReader) RowCount() int {
+ return len(m.RowData)
+}
+
+func (m *MessageReader) HasMore() bool {
+ return m.RowIndex < m.RowCount()
+}
+
+func (m *MessageReader) NextRow() error {
+ m.RowIndex++
+ if m.RowIndex > m.RowCount() {
+ return errors.New("Eof of row")
+ }
+ return nil
+}
+
+func (m *MessageReader) GetCol(name string) interface{} {
+ idx := m.RowIndex - 1
+ if v, ok := m.RowData[idx][name]; !ok {
+ return nil
+ } else {
+ return v
+ }
+}
+
+func (m *MessageReader) GetColAsInt(name string) int {
+ v := m.GetCol(name)
+ switch v.(type) {
+ case float32:
+ return int(v.(float32))
+ case float64:
+ return int(v.(float64))
+ case int:
+ return v.(int)
+ case string:
+ i, _ := strconv.Atoi(v.(string))
+ return i
+ default:
+ return 0
+ }
+}
+
+func (m *MessageReader) GetColAsString(name string) string {
+ v := m.GetCol(name)
+ return fmt.Sprintf("%v", v)
+}
+
+func (m *MessageReader) GetColAsDouble(name string) float64 {
+ v := m.GetCol(name)
+ switch v.(type) {
+ case float32:
+ return float64(v.(float32))
+ case float64:
+ return v.(float64)
+ case int:
+ return float64(v.(int))
+ case string:
+ i, _ := strconv.ParseFloat(v.(string), 64)
+ return i
+ default:
+ return 0
+ }
+}
+
+func (m *MessageReader) GetAttr(name string) interface{} {
+ if v, ok := m.Attributes[name]; !ok {
+ return nil
+ } else {
+ return v
+ }
+}