@@ -784,9 +784,6 @@ type JSONEncoder struct {
784784 // formatter handles formatting values prior to output.
785785 formatter Formatter
786786
787- // title is the title value.
788- title * Value
789-
790787 // empty is the empty value.
791788 empty * Value
792789}
@@ -979,9 +976,6 @@ type CSVEncoder struct {
979976 // formatter handles formatting values prior to output.
980977 formatter Formatter
981978
982- // title is the title value.
983- title * Value
984-
985979 // empty is the empty value.
986980 empty * Value
987981}
@@ -1124,6 +1118,16 @@ type TemplateEncoder struct {
11241118
11251119 // empty is the empty value.
11261120 empty * Value
1121+
1122+ // template is the parsed template
1123+ template Executor
1124+
1125+ // attributes are extra table attributes
1126+ attributes string
1127+ }
1128+
1129+ type Executor interface {
1130+ Execute (io.Writer , interface {}) error
11271131}
11281132
11291133// NewTemplateEncoder creates a new template encoder using the provided options.
@@ -1134,7 +1138,7 @@ func NewTemplateEncoder(resultSet ResultSet, opts ...Option) (Encoder, error) {
11341138 newline : newline ,
11351139 formatter : NewEscapeFormatter (),
11361140 empty : & Value {
1137- Tabs : make ([][][ 2 ] int , 1 ),
1141+ Buf : [] byte ( "" ),
11381142 },
11391143 }
11401144 for _ , o := range opts {
@@ -1151,7 +1155,73 @@ func (enc *TemplateEncoder) Encode(w io.Writer) error {
11511155 if enc .resultSet == nil {
11521156 return ErrResultSetIsNil
11531157 }
1154- return nil
1158+
1159+ // get and check columns
1160+ cols , err := enc .resultSet .Columns ()
1161+ if err != nil {
1162+ return err
1163+ }
1164+ clen := len (cols )
1165+ if clen == 0 {
1166+ return ErrResultSetHasNoColumns
1167+ }
1168+
1169+ headers , err := enc .formatter .Header (cols )
1170+ if err != nil {
1171+ return err
1172+ }
1173+
1174+ title := enc .title
1175+ if title == nil {
1176+ title = enc .empty
1177+ }
1178+
1179+ stop := make (chan struct {})
1180+ data := struct {
1181+ Title * Value
1182+ Attributes string
1183+ Headers []* Value
1184+ Rows <- chan []cell
1185+ }{
1186+ Title : title ,
1187+ Attributes : enc .attributes ,
1188+ Headers : headers ,
1189+ Rows : enc .rows (headers , stop ),
1190+ }
1191+ err = enc .template .Execute (w , data )
1192+ close (stop )
1193+ return err
1194+ }
1195+
1196+ type cell struct {
1197+ Name string
1198+ Value * Value
1199+ }
1200+
1201+ func (enc * TemplateEncoder ) rows (headers []* Value , stop <- chan struct {}) chan []cell {
1202+ // set up storage for results
1203+ r := make ([]interface {}, len (headers ))
1204+ for i := range headers {
1205+ r [i ] = new (interface {})
1206+ }
1207+ result := make (chan []cell )
1208+ go func () {
1209+ defer close (result )
1210+ for enc .resultSet .Next () {
1211+ row := make ([]cell , len (headers ))
1212+ err := enc .scanAndFormat (headers , r , row )
1213+ if err != nil {
1214+ return
1215+ }
1216+ select {
1217+ case result <- row :
1218+ // sent successfully
1219+ case <- stop :
1220+ return
1221+ }
1222+ }
1223+ }()
1224+ return result
11551225}
11561226
11571227// EncodeAll encodes all result sets to the writer using the encoder settings.
@@ -1179,13 +1249,25 @@ func (enc *TemplateEncoder) EncodeAll(w io.Writer) error {
11791249}
11801250
11811251// scanAndFormat scans and formats values from the result set.
1182- func (enc * TemplateEncoder ) scanAndFormat (vals []interface {}) ([]* Value , error ) {
1252+ // vals and result are passed as args to avoid allocation
1253+ func (enc * TemplateEncoder ) scanAndFormat (headers []* Value , buf []interface {}, row []cell ) error {
11831254 var err error
11841255 if err = enc .resultSet .Err (); err != nil {
1185- return nil , err
1256+ return err
11861257 }
1187- if err = enc .resultSet .Scan (vals ... ); err != nil {
1188- return nil , err
1258+ if err = enc .resultSet .Scan (buf ... ); err != nil {
1259+ return err
11891260 }
1190- return enc .formatter .Format (vals )
1261+ vals , err := enc .formatter .Format (buf )
1262+ if err != nil {
1263+ return err
1264+ }
1265+ for i , h := range headers {
1266+ v := vals [i ]
1267+ if v == nil {
1268+ v = enc .empty
1269+ }
1270+ row [i ] = cell {Name : string (h .Buf ), Value : v }
1271+ }
1272+ return nil
11911273}
0 commit comments