func querySqlValues(db *sql.DB, query string) (chan map[string]string, []string) {
	rowChan := make(chan map[string]string)

	rows, err := db.Query(query)
	check("running query", err)
	columnNames, err := rows.Columns()
	check("getting column names", err)

	go func() {

		defer rows.Close()

		vals := make([]interface{}, len(columnNames))
		valPointers := make([]interface{}, len(columnNames))
		// Copy
		for i := 0; i < len(columnNames); i++ {
			valPointers[i] = &vals[i]
		}

		for rows.Next() {
			err = rows.Scan(valPointers...)
			check("scanning a row", err)

			row := make(map[string]string)
			// Convert each cell to a SQL-valid string representation
			for i, valPtr := range vals {
				//println(reflect.TypeOf(valPtr))
				switch valueType := valPtr.(type) {
				case nil:
					row[columnNames[i]] = "null"
				case []uint8:
					row[columnNames[i]] = "'" + strings.Replace(string(valPtr.([]byte)), "'", "''", -1) + "'"
				case string:
					row[columnNames[i]] = "'" + strings.Replace(valPtr.(string), "'", "''", -1) + "'"
				case int64:
					row[columnNames[i]] = fmt.Sprintf("%d", valPtr)
				case float64:
					row[columnNames[i]] = fmt.Sprintf("%f", valPtr)
				case bool:
					row[columnNames[i]] = fmt.Sprintf("%t", valPtr)
				case time.Time:
					row[columnNames[i]] = "'" + valPtr.(time.Time).Format(isoFormat) + "'"
				case fmt.Stringer:
					row[columnNames[i]] = fmt.Sprintf("%v", valPtr)
				default:
					row[columnNames[i]] = fmt.Sprintf("%v", valPtr)
					println("-- Warning, column %s is an unhandled type: %v", columnNames[i], valueType)
				}
			}
			rowChan <- row
		}
		close(rowChan)
	}()
	return rowChan, columnNames
}
/*
 * Returns row maps (keyed by the column name) in a channel.
 * Dynamically converts each column value to a SQL string value.
 * See http://stackoverflow.com/questions/23507531/is-golangs-sql-package-incapable-of-ad-hoc-exploratory-queries
 */
Returns row maps (keyed by the column name) in a channel.
Dynamically converts each column value to a SQL string value.
/ * * Returns row maps ( keyed by the column name ) in a channel . * Dynamically converts each column value to a SQL string value . * See http : // stackoverflow . com / questions / 23507531 / is - golangs - sql - package - incapable - of - ad - hoc - exploratory - queries * /
func querySqlValues(db *sql.DB, query string) (chan map[string]string, []string) {
	rowChan := make(chan map[string]string)
	rows, err := db.Query(query)
	check("running query", err)
	columnNames, err := rows.Columns()
	check("getting column names", err)
	go func() {
		defer rows.Close()
		vals := make([]interface{}, len(columnNames))
		valPointers := make([]interface{}, len(columnNames))
		for i := 0; i < len(columnNames); i++ {
			valPointers[i] = &vals[i]
		}
		for rows.Next() {
			err = rows.Scan(valPointers...)
			check("scanning a row", err)
			row := make(map[string]string)
			for i, valPtr := range vals {
				switch valueType := valPtr.(type) {
				case nil:
					row[columnNames[i]] = "null"
				case []uint8:
					row[columnNames[i]] = "'" + strings.Replace(string(valPtr.([]byte)), "'", "''", -1) + "'"
				case string:
					row[columnNames[i]] = "'" + strings.Replace(valPtr.(string), "'", "''", -1) + "'"
				case int64:
					row[columnNames[i]] = fmt.Sprintf("%d", valPtr)
				case float64:
					row[columnNames[i]] = fmt.Sprintf("%f", valPtr)
				case bool:
					row[columnNames[i]] = fmt.Sprintf("%t", valPtr)
				case time.Time:
					row[columnNames[i]] = "'" + valPtr.(time.Time).Format(isoFormat) + "'"
				case fmt.Stringer:
					row[columnNames[i]] = fmt.Sprintf("%v", valPtr)
				default:
					row[columnNames[i]] = fmt.Sprintf("%v", valPtr)
					println("-- Warning, column %s is an unhandled type: %v", columnNames[i], valueType)
				}
			}
			rowChan <- row
		}
		close(rowChan)
	}()
	return rowChan, columnNames
}
func querySqlValues ( db * sql . DB , query string ) ( chan map [ string ] string , [ ] string ) { rowChan := make ( chan map [ string ] string ) rows , err := db . Query ( query ) check ( " " , err ) columnNames , err := rows . Columns ( ) check ( " " , err ) go func ( ) { defer rows . Close ( ) vals := make ( [ ] interface { } , len ( columnNames ) ) valPointers := make ( [ ] interface { } , len ( columnNames ) ) for i := 0 ; i < len ( columnNames ) ; i ++ { valPointers [ i ] = & vals [ i ] } for rows . Next ( ) { err = rows . Scan ( valPointers ... ) check ( " " , err ) row := make ( map [ string ] string ) for i , valPtr := range vals { switch valueType := valPtr . ( type ) { case nil : row [ columnNames [ i ] ] = " " case [ ] uint8 : row [ columnNames [ i ] ] = " " + strings . Replace ( string ( valPtr . ( [ ] byte ) ) , " " , " " , - 1 ) + " " case string : row [ columnNames [ i ] ] = " " + strings . Replace ( valPtr . ( string ) , " " , " " , - 1 ) + " " case int64 : row [ columnNames [ i ] ] = fmt . Sprintf ( " " , valPtr ) case float64 : row [ columnNames [ i ] ] = fmt . Sprintf ( " " , valPtr ) case bool : row [ columnNames [ i ] ] = fmt . Sprintf ( " " , valPtr ) case time . Time : row [ columnNames [ i ] ] = " " + valPtr . ( time . Time ) . Format ( isoFormat ) + " " case fmt . Stringer : row [ columnNames [ i ] ] = fmt . Sprintf ( " " , valPtr ) default : row [ columnNames [ i ] ] = fmt . Sprintf ( " " , valPtr ) println ( " " , columnNames [ i ] , valueType ) } } rowChan <- row } close ( rowChan ) } ( ) return rowChan , columnNames }
Returns row maps (keyed by the column name) in a channel.
Returns row maps ( keyed by the column name ) in a channel .
// Copy // Convert each cell to a SQL-valid string representation //println(reflect.TypeOf(valPtr))