@@ -45,23 +45,35 @@ const OUTFORMAT_TABLE = 8
4545const OUTFORMAT_BOX = 9
4646const OUTFORMAT_XML = 10
4747
48+ const ROWSET_TYPE_BASIC = 1
49+ const ROWSET_TYPE_METADATA_v1 = 2
50+ const ROWSET_TYPE_HEADER_ONLY = 3
51+ const ROWSET_TYPE_DATA_ONLY = 4
52+
4853// The Result is either a Literal or a RowSet
4954type Result struct {
5055 uncompressedChuckSizeSum uint64
5156
5257 value Value
58+ rows []ResultRow
59+
60+ // columns metadata
61+ Name []string
62+ Width []uint64
63+ DeclType []string
64+ DbName []string
65+ TblName []string
66+ OrigName []string
67+ Notnull []int32
68+ PriKey []int32
69+ Autoinc []int32
5370
54- rows []ResultRow
55- ColumnNames []string
56- ColumnWidth []uint64
5771 MaxHeaderWidth uint64
5872}
5973
6074var OKResult = Result {
6175 value : Value {Type : '+' , Buffer : []byte ("OK" )}, // This is an unset Value
6276 rows : nil ,
63- ColumnNames : nil ,
64- ColumnWidth : nil ,
6577 MaxHeaderWidth : 0 ,
6678 uncompressedChuckSizeSum : 0 ,
6779}
@@ -92,7 +104,7 @@ func (this *Result) GetNumberOfColumns() uint64 {
92104 case ! this .IsRowSet ():
93105 return 0
94106 default :
95- return uint64 (len (this .ColumnWidth ))
107+ return uint64 (len (this .Width ))
96108 }
97109}
98110
@@ -124,7 +136,7 @@ func (this *Result) GetMaxColumnWidth(Column uint64) (uint64, error) {
124136 case Column >= this .GetNumberOfColumns ():
125137 return 0 , errors .New ("Column Index out of bounds" )
126138 default :
127- return this .ColumnWidth [Column ], nil
139+ return this .Width [Column ], nil
128140 }
129141}
130142
@@ -137,7 +149,7 @@ func (this *Result) GetNameLength(Column uint64) (uint64, error) {
137149 case Column >= this .GetNumberOfColumns ():
138150 return 0 , errors .New ("Column Index out of bounds" )
139151 default :
140- return uint64 (len (this .ColumnNames [Column ])), nil
152+ return uint64 (len (this .Name [Column ])), nil
141153 }
142154}
143155
@@ -187,9 +199,9 @@ func (this *Result) IsRowSet() bool {
187199 return false
188200 case this .rows == nil :
189201 return false
190- case this .ColumnNames == nil :
202+ case this .Name == nil :
191203 return false
192- case this .ColumnWidth == nil :
204+ case this .Width == nil :
193205 return false
194206 case this .MaxHeaderWidth == 0 :
195207 return false
@@ -328,8 +340,16 @@ func (this *Result) GetErrorAsString() string {
328340func (this * Result ) Free () {
329341 this .value = Value {Type : 0 , Buffer : nil } // GC
330342 this .rows = []ResultRow {} // GC
331- this .ColumnNames = []string {} // GC
332- this .ColumnWidth = []uint64 {} // GC
343+ this .Name = []string {} // GC
344+ this .Width = []uint64 {} // GC
345+ this .DeclType = []string {} // GC
346+ this .DbName = []string {}
347+ this .TblName = []string {}
348+ this .OrigName = []string {}
349+ this .Notnull = []int32 {}
350+ this .PriKey = []int32 {}
351+ this .Autoinc = []int32 {}
352+
333353 this .MaxHeaderWidth = 0
334354}
335355
@@ -340,7 +360,7 @@ func (this *Result) GetName(Column uint64) (string, error) {
340360 case Column >= this .GetNumberOfColumns ():
341361 return "" , errors .New ("Column Index out of bounds" )
342362 default :
343- return this .ColumnNames [Column ], nil
363+ return this .Name [Column ], nil
344364 }
345365}
346366func (this * Result ) GetName_ (Column uint64 ) string {
@@ -520,14 +540,14 @@ func renderCenteredString(Buffer string, Width int) string {
520540
521541func (this * Result ) renderHorizontalTableLine (Left string , Fill string , Separator string , Right string ) string {
522542 outBuffer := ""
523- for _ , columnWidth := range this .ColumnWidth {
543+ for _ , columnWidth := range this .Width {
524544 outBuffer = fmt .Sprintf ("%s%s%s" , outBuffer , strings .Repeat (Fill , int (columnWidth + 2 )), Separator )
525545 }
526546 return fmt .Sprintf ("%s%s%s" , Left , strings .TrimRight (outBuffer , Separator ), Right )
527547}
528548func (this * Result ) renderTableColumnNames (Left string , Separator string , Right string ) string {
529549 outBuffer := ""
530- for forThisColumn , columnWidth := range this .ColumnWidth {
550+ for forThisColumn , columnWidth := range this .Width {
531551 columnName , _ := this .GetName (uint64 (forThisColumn ))
532552 outBuffer = fmt .Sprintf ("%s%s%s" , outBuffer , renderCenteredString (columnName , int (columnWidth + 2 )), Separator )
533553 }
@@ -713,14 +733,14 @@ func GetDefaultSeparatorForOutputFormat(Format int) (string, error) {
713733 }
714734}
715735
716- //////
736+ // ////
717737// is called from connection.Select
718738func (this * SQCloud ) readResult () (* Result , error ) {
719739 ErrorResult := Result {
720740 value : Value {Type : '-' , Buffer : []byte ("100000 Unknown internal error" )}, // This is an unset Value
721741 rows : nil ,
722- ColumnNames : nil ,
723- ColumnWidth : nil ,
742+ Name : nil ,
743+ Width : nil ,
724744 MaxHeaderWidth : 0 ,
725745 uncompressedChuckSizeSum : 0 ,
726746 }
@@ -874,8 +894,8 @@ func (this *SQCloud) readResult() (*Result, error) {
874894 offset += bytesRead
875895
876896 result .rows = make ([]ResultRow , int (N ))
877- result .ColumnNames = []string {"ARRAY" }
878- result .ColumnWidth = []uint64 {5 }
897+ result .Name = []string {"ARRAY" }
898+ result .Width = []uint64 {5 }
879899 result .MaxHeaderWidth = 0
880900
881901 for row := uint64 (0 ); row < N ; row ++ {
@@ -888,8 +908,8 @@ func (this *SQCloud) readResult() (*Result, error) {
888908 return nil , err
889909 default :
890910 columnLength := result .rows [row ].columns [0 ].GetLength ()
891- if result .ColumnWidth [0 ] < columnLength {
892- result .ColumnWidth [0 ] = columnLength
911+ if result .Width [0 ] < columnLength {
912+ result .Width [0 ] = columnLength
893913 }
894914 if result .MaxHeaderWidth < columnLength {
895915 result .MaxHeaderWidth = columnLength
@@ -954,30 +974,130 @@ func (this *SQCloud) readResult() (*Result, error) {
954974 // single chunk or first chunk of multiple chunks
955975 if IDX == 0 || IDX == 1 {
956976 result .rows = []ResultRow {}
957- result .ColumnNames = make ([]string , int (NCOLS ))
958- result .ColumnWidth = make ([]uint64 , int (NCOLS ))
959977 result .MaxHeaderWidth = 0
960978
961- for column := uint64 (0 ); column < NCOLS ; column ++ { // Read in the column names, use the result.value as scratch variable
962- switch val , bytesRead , err := chunk .readValueAt (offset ); {
963- case err != nil :
964- return nil , err
965- case ! val .IsString ():
966- return nil , errors .New ("Invalid Column name" )
967- default :
968- result .ColumnNames [column ] = val .GetString ()
969- result .ColumnWidth [column ] = val .GetLength ()
970- if result .MaxHeaderWidth < result .ColumnWidth [column ] {
971- result .MaxHeaderWidth = result .ColumnWidth [column ]
979+ if VERSION != ROWSET_TYPE_DATA_ONLY {
980+ // header is guarantee to contain column names
981+ result .Name = make ([]string , int (NCOLS ))
982+ result .Width = make ([]uint64 , int (NCOLS ))
983+ for column := uint64 (0 ); column < NCOLS ; column ++ { // Read in the column names, use the result.value as scratch variable
984+ switch val , bytesRead , err := chunk .readValueAt (offset ); {
985+ case err != nil :
986+ return nil , err
987+ case ! val .IsString ():
988+ return nil , errors .New ("Invalid Column name" )
989+ default :
990+ result .Name [column ] = val .GetString ()
991+ result .Width [column ] = val .GetLength ()
992+ if result .MaxHeaderWidth < result .Width [column ] {
993+ result .MaxHeaderWidth = result .Width [column ]
994+ }
995+ offset += bytesRead
972996 }
973- offset += bytesRead
974997 }
975- }
976- }
977998
978- if VERSION != 1 {
979- // not yet supported
980- return nil , fmt .Errorf ("Unsupported rowset version %d" , VERSION )
999+ // check if additional metadata is contained
1000+ if VERSION == ROWSET_TYPE_METADATA_v1 {
1001+ result .DeclType = make ([]string , int (NCOLS ))
1002+ result .DbName = make ([]string , int (NCOLS ))
1003+ result .TblName = make ([]string , int (NCOLS ))
1004+ result .OrigName = make ([]string , int (NCOLS ))
1005+ result .Notnull = make ([]int32 , int (NCOLS ))
1006+ result .PriKey = make ([]int32 , int (NCOLS ))
1007+ result .Autoinc = make ([]int32 , int (NCOLS ))
1008+
1009+ // column declared types
1010+ for column := uint64 (0 ); column < NCOLS ; column ++ {
1011+ switch val , bytesRead , err := chunk .readValueAt (offset ); {
1012+ case err != nil :
1013+ return nil , err
1014+ case ! val .IsString () && ! val .IsNULL ():
1015+ return nil , errors .New ("Invalid decltype value" )
1016+ default :
1017+ result .DeclType [column ] = val .GetString ()
1018+ offset += bytesRead
1019+ }
1020+ }
1021+
1022+ // column database names
1023+ for column := uint64 (0 ); column < NCOLS ; column ++ {
1024+ switch val , bytesRead , err := chunk .readValueAt (offset ); {
1025+ case err != nil :
1026+ return nil , err
1027+ case ! val .IsString () && ! val .IsNULL ():
1028+ return nil , errors .New ("Invalid dbname value" )
1029+ default :
1030+ result .DbName [column ] = val .GetString ()
1031+ offset += bytesRead
1032+ }
1033+ }
1034+
1035+ // column table names
1036+ for column := uint64 (0 ); column < NCOLS ; column ++ {
1037+ switch val , bytesRead , err := chunk .readValueAt (offset ); {
1038+ case err != nil :
1039+ return nil , err
1040+ case ! val .IsString () && ! val .IsNULL ():
1041+ return nil , errors .New ("Invalid tblname value" )
1042+ default :
1043+ result .TblName [column ] = val .GetString ()
1044+ offset += bytesRead
1045+ }
1046+ }
1047+
1048+ // column origin names
1049+ for column := uint64 (0 ); column < NCOLS ; column ++ {
1050+ switch val , bytesRead , err := chunk .readValueAt (offset ); {
1051+ case err != nil :
1052+ return nil , err
1053+ case ! val .IsString ():
1054+ return nil , errors .New ("Invalid origin name value" )
1055+ default :
1056+ result .OrigName [column ] = val .GetString ()
1057+ offset += bytesRead
1058+ }
1059+ }
1060+
1061+ // column not null flag
1062+ for column := uint64 (0 ); column < NCOLS ; column ++ {
1063+ switch val , bytesRead , err := chunk .readValueAt (offset ); {
1064+ case err != nil :
1065+ return nil , err
1066+ case ! val .IsInteger ():
1067+ return nil , errors .New ("Invalid not null value" )
1068+ default :
1069+ result .Notnull [column ], _ = val .GetInt32 ()
1070+ offset += bytesRead
1071+ }
1072+ }
1073+
1074+ // column primary key flag
1075+ for column := uint64 (0 ); column < NCOLS ; column ++ {
1076+ switch val , bytesRead , err := chunk .readValueAt (offset ); {
1077+ case err != nil :
1078+ return nil , err
1079+ case ! val .IsInteger ():
1080+ return nil , errors .New ("Invalid primary key value" )
1081+ default :
1082+ result .PriKey [column ], _ = val .GetInt32 ()
1083+ offset += bytesRead
1084+ }
1085+ }
1086+
1087+ // column autoincrement key flag
1088+ for column := uint64 (0 ); column < NCOLS ; column ++ {
1089+ switch val , bytesRead , err := chunk .readValueAt (offset ); {
1090+ case err != nil :
1091+ return nil , err
1092+ case ! val .IsInteger ():
1093+ return nil , errors .New ("Invalid autoinc value" )
1094+ default :
1095+ result .Autoinc [column ], _ = val .GetInt32 ()
1096+ offset += bytesRead
1097+ }
1098+ }
1099+ }
1100+ }
9811101 }
9821102
9831103 // read all the rows from this chunk
@@ -996,8 +1116,8 @@ func (this *SQCloud) readResult() (*Result, error) {
9961116 return nil , err
9971117 default :
9981118 columnLength := rows [row ].columns [column ].GetLength ()
999- if result .ColumnWidth [column ] < columnLength {
1000- result .ColumnWidth [column ] = columnLength
1119+ if result .Width [column ] < columnLength {
1120+ result .Width [column ] = columnLength
10011121 }
10021122 if result .MaxHeaderWidth < columnLength {
10031123 result .MaxHeaderWidth = columnLength
@@ -1014,9 +1134,6 @@ func (this *SQCloud) readResult() (*Result, error) {
10141134
10151135 if Type == CMD_ROWSET {
10161136 return & result , nil
1017- } // return if it is a rowset
1018- if _ , err := this .sendString ("OK" ); err != nil { // ask the server for the next chunk and loop (Thank's Andrea)
1019- return nil , err
10201137 }
10211138
10221139 case CMD_RAWJSON :
0 commit comments