// 2019 Rackspace, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"): you may // not use this file except in compliance with the License. You may obtain // a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations // under the License. package raxSQL import ( "bytes" "database/sql" "strconv" "time" "github.com/sirupsen/logrus" ) // Query method takes a MySql client receiver and returns a list of maps containing the // query response values func (c *Client) Query(qryValue string) (table []map[string]string, err error) { // Execute the query rows, err := c.DB.Query(qryValue) if err != nil { return } // Get column names columns, err := rows.Columns() if err != nil { return } // Make a slice for the values values := make([]sql.RawBytes, len(columns)) // rows.Scan wants '[]interface{}' as an argument, so we must copy the // references into such a slice // See http://code.google.com/p/go-wiki/wiki/InterfaceSlice for details scanArgs := make([]interface{}, len(values)) for i := range values { scanArgs[i] = &values[i] } // Iterate through the rows, gathering data for rows.Next() { // get RawBytes from data err = rows.Scan(scanArgs...) if err != nil { return } // Iterate through the row values and map them // to the associated column name var value string var column map[string]string for i, col := range values { value = string(col) // If this is the first column, set the map values if column == nil { column = map[string]string{columns[i]: value} continue } column[columns[i]] = value } // Add the column to the table table = append(table, column) } // If any errors occurred during the iteration process, // return an error here if err = rows.Err(); err != nil { return } return } // QueryMigrations method takes a MySql client receiver and returns a list of maps containing the // query response values func (c *Client) QueryInterface(qryValue string) (table []map[string]string, err error) { // Execute the query rows, err := c.DB.Query(qryValue) if err != nil { return } // Get column names columns, err := rows.Columns() if err != nil { return } scanValues := make([]interface{}, len(columns)) // rows.Scan wants '[]interface{}' as an argument, so we must copy the // references into such a slice // See http://code.google.com/p/go-wiki/wiki/InterfaceSlice for details scanArgs := make([]interface{}, len(scanValues)) for i := range scanValues { scanArgs[i] = &scanValues[i] } // Iterate through the rows, gathering data for rows.Next() { // get RawBytes from data err = rows.Scan(scanArgs...) if err != nil { return } // Iterate through the row values and map them // to the associated column name var value string var column map[string]string for i, col := range scanValues { switch t := col.(type) { case time.Time: value = time.Time(t).String() case string: value = string(t) case int: value = strconv.Itoa(t) case int64: value = strconv.FormatInt(t, 10) case []uint8: value = bytes.NewBuffer(t).String() case nil: value = "" default: logrus.Warnf("unable to convert type: %T:%v", col, col) } // If this is the first column, set the map values if column == nil { column = map[string]string{columns[i]: value} continue } column[columns[i]] = value } // Add the column to the table table = append(table, column) } // If any errors occurred during the iteration process, // return an error here if err = rows.Err(); err != nil { return } return }