@@ -170,16 +170,19 @@ struct SQCloudResult {
170170 uint32_t nheader ; // number of character in the first part of the header (which is usually skipped)
171171
172172 // used in TYPE_ROWSET only
173- uint32_t flags ; // rowset flags
173+ uint32_t version ; // rowset version
174174 uint32_t nrows ; // number of rows
175175 uint32_t ncols ; // number of columns
176176 uint32_t ndata ; // number of items stores in data
177177 char * * data ; // data contained in the rowset
178178 char * * name ; // column names
179- char * * decltype ; // column declared types (sqlite mode only)
180- char * * dbname ; // column database names (sqlite mode only)
181- char * * tblname ; // column table names (sqlite mode only)
182- char * * origname ; // column origin names (sqlite mode only)
179+ char * * decltype ; // column declared types
180+ char * * dbname ; // column database names
181+ char * * tblname ; // column table names
182+ char * * origname ; // column origin names
183+ int * notnull ; // column is not null
184+ int * prikey ; // column is primary key
185+ int * autoinc ; // column is auto increment
183186 uint32_t * clen ; // max len for each column (used to display result)
184187 uint32_t maxlen ; // max len for each row/column
185188
@@ -801,12 +804,20 @@ static char *internal_get_rowset_header (SQCloudResult *result, char **header, u
801804 return internal_parse_value (header [col ], len , NULL );
802805}
803806
804- static bool internal_parse_rowset_header (SQCloudResult * rowset , char * * pbuffer , uint32_t * pblen , uint32_t ncols , uint32_t flags ) {
805- if (BITCHECK (flags , SQCLOUD_ROWSET_FLAG_DATAONLY )) return true;
807+ static int internal_get_rowset_header_int (SQCloudResult * result , int * header , uint32_t col ) {
808+ if (!result || result -> tag != RESULT_ROWSET ) return -1 ;
809+ if (col >= result -> ncols ) return -1 ;
810+ if (header == NULL ) return -1 ;
811+ return header [col ];
812+ }
813+
814+ static bool internal_parse_rowset_header (SQCloudResult * rowset , char * * pbuffer , uint32_t * pblen , uint32_t ncols , uint32_t version ) {
815+ if (version == ROWSET_TYPE_DATA_ONLY ) return true;
806816
807817 char * buffer = * pbuffer ;
808818 uint32_t blen = * pblen ;
809819
820+ /*
810821 if (BITCHECK(flags, SQCLOUD_ROWSET_FLAG_METAVM)) {
811822 uint32_t cstart1 = 0, cstart2 = 0, cstart3 = 0, cstart4 = 0, cstart5 = 0;
812823
@@ -838,8 +849,9 @@ static bool internal_parse_rowset_header (SQCloudResult *rowset, char **pbuffer,
838849 rowset->n4 = n4;
839850 rowset->n5 = n5;
840851 }
852+ */
841853
842- // header is guarantee to contains column names (1st)
854+ // header is guarantee to contain column names
843855 for (uint32_t i = 0 ; i < ncols ; ++ i ) {
844856 uint32_t cstart = 0 ;
845857 uint32_t len = internal_parse_number (& buffer [1 ], blen , & cstart );
@@ -850,7 +862,8 @@ static bool internal_parse_rowset_header (SQCloudResult *rowset, char **pbuffer,
850862 if (rowset -> maxlen < len ) rowset -> maxlen = len ;
851863 }
852864
853- if (BITCHECK (flags , SQCLOUD_ROWSET_FLAG_METACOLS )) {
865+ // check if additional metadata is contained
866+ if (version == ROWSET_TYPE_METADATA_v1 ) {
854867 rowset -> decltype = (char * * ) mem_alloc (ncols * sizeof (char * ));
855868 if (!rowset -> decltype ) return false;
856869 rowset -> dbname = (char * * ) mem_alloc (ncols * sizeof (char * ));
@@ -859,8 +872,14 @@ static bool internal_parse_rowset_header (SQCloudResult *rowset, char **pbuffer,
859872 if (!rowset -> tblname ) return false;
860873 rowset -> origname = (char * * ) mem_alloc (ncols * sizeof (char * ));
861874 if (!rowset -> origname ) return false;
862-
863- // in sqlite mode header contains column declared types (2nd)
875+ rowset -> notnull = (int * ) mem_alloc (ncols * sizeof (int ));
876+ if (!rowset -> notnull ) return false;
877+ rowset -> prikey = (int * ) mem_alloc (ncols * sizeof (int ));
878+ if (!rowset -> prikey ) return false;
879+ rowset -> autoinc = (int * ) mem_alloc (ncols * sizeof (int ));
880+ if (!rowset -> autoinc ) return false;
881+
882+ // column declared types
864883 for (uint32_t i = 0 ; i < ncols ; ++ i ) {
865884 uint32_t cstart = 0 ;
866885 uint32_t len = internal_parse_number (& buffer [1 ], blen , & cstart );
@@ -869,7 +888,7 @@ static bool internal_parse_rowset_header (SQCloudResult *rowset, char **pbuffer,
869888 blen -= cstart + len + 1 ;
870889 }
871890
872- // in sqlite mode header contains column database names (3rd)
891+ // column database names
873892 for (uint32_t i = 0 ; i < ncols ; ++ i ) {
874893 uint32_t cstart = 0 ;
875894 uint32_t len = internal_parse_number (& buffer [1 ], blen , & cstart );
@@ -878,7 +897,7 @@ static bool internal_parse_rowset_header (SQCloudResult *rowset, char **pbuffer,
878897 blen -= cstart + len + 1 ;
879898 }
880899
881- // in sqlite mode header contains column table names (4th)
900+ // column table names
882901 for (uint32_t i = 0 ; i < ncols ; ++ i ) {
883902 uint32_t cstart = 0 ;
884903 uint32_t len = internal_parse_number (& buffer [1 ], blen , & cstart );
@@ -887,14 +906,44 @@ static bool internal_parse_rowset_header (SQCloudResult *rowset, char **pbuffer,
887906 blen -= cstart + len + 1 ;
888907 }
889908
890- // in sqlite mode header contains column origin names (5th)
909+ // column origin names
891910 for (uint32_t i = 0 ; i < ncols ; ++ i ) {
892911 uint32_t cstart = 0 ;
893912 uint32_t len = internal_parse_number (& buffer [1 ], blen , & cstart );
894913 rowset -> origname [i ] = buffer ;
895914 buffer += cstart + len + 1 ;
896915 blen -= cstart + len + 1 ;
897916 }
917+
918+ // column not null flag
919+ for (uint32_t i = 0 ; i < ncols ; ++ i ) {
920+ uint32_t cstart = 0 ;
921+ uint32_t value = internal_parse_number (& buffer [1 ], blen , & cstart );
922+ rowset -> notnull [i ] = (int )value ;
923+ uint32_t len = 0 ;
924+ buffer += cstart + len + 1 ;
925+ blen -= cstart + len + 1 ;
926+ }
927+
928+ // column primary key flag
929+ for (uint32_t i = 0 ; i < ncols ; ++ i ) {
930+ uint32_t cstart = 0 ;
931+ uint32_t value = internal_parse_number (& buffer [1 ], blen , & cstart );
932+ rowset -> prikey [i ] = (int )value ;
933+ uint32_t len = 0 ;
934+ buffer += cstart + len + 1 ;
935+ blen -= cstart + len + 1 ;
936+ }
937+
938+ // column autoincrement key flag
939+ for (uint32_t i = 0 ; i < ncols ; ++ i ) {
940+ uint32_t cstart = 0 ;
941+ uint32_t value = internal_parse_number (& buffer [1 ], blen , & cstart );
942+ rowset -> autoinc [i ] = (int )value ;
943+ uint32_t len = 0 ;
944+ buffer += cstart + len + 1 ;
945+ blen -= cstart + len + 1 ;
946+ }
898947 }
899948
900949 * pbuffer = buffer ;
@@ -903,8 +952,8 @@ static bool internal_parse_rowset_header (SQCloudResult *rowset, char **pbuffer,
903952 return true;
904953}
905954
906- static bool internal_parse_rowset_values (SQCloudResult * rowset , char * * pbuffer , uint32_t * pblen , uint32_t index , uint32_t bound , uint32_t ncols , uint32_t flags ) {
907- if (BITCHECK ( flags , SQCLOUD_ROWSET_FLAG_HEADONLY ) ) return true;
955+ static bool internal_parse_rowset_values (SQCloudResult * rowset , char * * pbuffer , uint32_t * pblen , uint32_t index , uint32_t bound , uint32_t ncols , uint32_t version ) {
956+ if (version == ROWSET_TYPE_HEADER_ONLY ) return true;
908957
909958 char * buffer = * pbuffer ;
910959 uint32_t blen = * pblen ;
@@ -924,7 +973,7 @@ static bool internal_parse_rowset_values (SQCloudResult *rowset, char **pbuffer,
924973}
925974
926975static SQCloudResult * internal_parse_rowset (SQCloudConnection * connection , char * buffer , uint32_t blen , uint32_t bstart ,
927- uint32_t nrows , uint32_t ncols , uint32_t flags ) {
976+ uint32_t nrows , uint32_t ncols , uint32_t version ) {
928977 SQCloudResult * rowset = (SQCloudResult * )mem_zeroalloc (sizeof (SQCloudResult ));
929978 if (!rowset ) {
930979 internal_set_error (connection , INTERNAL_ERRCODE_MEMORY , "Unable to allocate memory for SQCloudResult: %d." , sizeof (SQCloudResult ));
@@ -937,7 +986,7 @@ static SQCloudResult *internal_parse_rowset (SQCloudConnection *connection, char
937986 rowset -> blen = blen ;
938987 rowset -> balloc = blen ;
939988 rowset -> nheader = bstart ;
940- rowset -> flags = flags ;
989+ rowset -> version = version ;
941990
942991 rowset -> nrows = nrows ;
943992 rowset -> ncols = ncols ;
@@ -950,10 +999,10 @@ static SQCloudResult *internal_parse_rowset (SQCloudConnection *connection, char
950999 blen -= bstart ;
9511000
9521001 // parse rowset header
953- if (!internal_parse_rowset_header (rowset , & buffer , & blen , ncols , flags )) goto abort_rowset ;
1002+ if (!internal_parse_rowset_header (rowset , & buffer , & blen , ncols , version )) goto abort_rowset ;
9541003
9551004 // parse values (buffer and blen was updated in internal_parse_rowset_header)
956- if (!internal_parse_rowset_values (rowset , & buffer , & blen , 0 , nrows * ncols , ncols , flags )) goto abort_rowset ;
1005+ if (!internal_parse_rowset_values (rowset , & buffer , & blen , 0 , nrows * ncols , ncols , version )) goto abort_rowset ;
9571006
9581007 return rowset ;
9591008
@@ -968,7 +1017,7 @@ static SQCloudResult *internal_parse_rowset (SQCloudConnection *connection, char
9681017}
9691018
9701019static SQCloudResult * internal_parse_rowset_chunck (SQCloudConnection * connection , char * buffer , uint32_t blen , uint32_t bstart , uint32_t idx ,
971- uint32_t nrows , uint32_t ncols , uint32_t flags ) {
1020+ uint32_t nrows , uint32_t ncols , uint32_t version ) {
9721021 SQCloudResult * rowset = connection -> _chunk ;
9731022 bool first_chunk = false;
9741023
@@ -997,7 +1046,7 @@ static SQCloudResult *internal_parse_rowset_chunck (SQCloudConnection *connectio
9971046
9981047 if (first_chunk ) {
9991048 rowset -> tag = RESULT_ROWSET ;
1000- rowset -> flags = flags ;
1049+ rowset -> version = version ;
10011050 rowset -> ischunk = true;
10021051
10031052 rowset -> buffers = (char * * )mem_zeroalloc ((sizeof (char * ) * DEFAULT_CHUCK_NBUFFERS ));
@@ -1030,7 +1079,7 @@ static SQCloudResult *internal_parse_rowset_chunck (SQCloudConnection *connectio
10301079 buffer += bstart ;
10311080
10321081 // parse rowset header
1033- if (!internal_parse_rowset_header (rowset , & buffer , & blen , ncols , flags )) goto abort_rowset ;
1082+ if (!internal_parse_rowset_header (rowset , & buffer , & blen , ncols , version )) goto abort_rowset ;
10341083 }
10351084
10361085 // update total buffer size
@@ -1092,14 +1141,16 @@ static SQCloudResult *internal_parse_rowset_chunck (SQCloudConnection *connectio
10921141 uint32_t bound = rowset -> ndata + (nrows * ncols );
10931142
10941143 // parse values
1095- if (!internal_parse_rowset_values (rowset , & buffer , & blen , index , bound , ncols , flags )) goto abort_rowset ;
1144+ if (!internal_parse_rowset_values (rowset , & buffer , & blen , index , bound , ncols , version )) goto abort_rowset ;
10961145
10971146 // this check is for internal usage only
10981147 if (connection -> fd == 0 ) return rowset ;
10991148
1100- // normal usage
1149+ #if 0
1150+ // January 24th, 2024 -> ACK disabled for Rowset in chunks
11011151 // send ACK
1102- if (!internal_socket_write (connection , "OK" , 2 , true, true)) goto abort_rowset ;
1152+ // if (!internal_socket_write(connection, "OK", 2, true, true)) goto abort_rowset;
1153+ #endif
11031154
11041155 // read next chunk
11051156 return internal_socket_read (connection , true);
@@ -1231,10 +1282,10 @@ static SQCloudResult *internal_parse_buffer (SQCloudConnection *connection, char
12311282 // CMD_ROWSET: *LEN 0:VERSION ROWS COLS DATA
12321283 // CMD_ROWSET_CHUNK: /LEN IDX:VERSION ROWS COLS DATA
12331284 uint32_t cstart1 = 0 , cstart2 = 0 , cstart3 = 0 , cstart4 = 0 ;
1234- uint32_t flags = 0 ;
1285+ uint32_t version = 0 ;
12351286
12361287 internal_parse_number (& buffer [1 ], blen - 1 , & cstart1 ); // parse len (already parsed in blen parameter)
1237- uint32_t idx = internal_parse_number_extended (& buffer [cstart1 + 1 ], blen - (cstart1 + 1 ), & cstart2 , & flags , NULL );
1288+ uint32_t idx = internal_parse_number_extended (& buffer [cstart1 + 1 ], blen - (cstart1 + 1 ), & cstart2 , & version , NULL );
12381289 uint32_t nrows = internal_parse_number (& buffer [cstart1 + cstart2 + 1 ], blen - (cstart1 + cstart2 + 1 ), & cstart3 );
12391290 uint32_t ncols = internal_parse_number (& buffer [cstart1 + cstart2 + + cstart3 + 1 ], blen - (cstart1 + cstart2 + + cstart3 + 1 ), & cstart4 );
12401291
@@ -1244,8 +1295,8 @@ static SQCloudResult *internal_parse_buffer (SQCloudConnection *connection, char
12441295 SQCloudResult * res = NULL ;
12451296 // the externalbuffer flag can change in case of compressed rowset when the end chunk is received
12461297 if (connection -> _chunk ) connection -> _chunk -> externalbuffer = externalbuffer ;
1247- if (buffer [0 ] == CMD_ROWSET ) res = internal_parse_rowset (connection , buffer , blen , bstart , nrows , ncols , flags );
1248- else res = internal_parse_rowset_chunck (connection , buffer , blen , bstart , idx , nrows , ncols , flags );
1298+ if (buffer [0 ] == CMD_ROWSET ) res = internal_parse_rowset (connection , buffer , blen , bstart , nrows , ncols , version );
1299+ else res = internal_parse_rowset_chunck (connection , buffer , blen , bstart , idx , nrows , ncols , version );
12491300 if (res ) {
12501301 res -> externalbuffer = externalbuffer ;
12511302 if (res -> ischunk && res -> bcount == 1 ) res -> bext [0 ] = externalbuffer ;
@@ -1589,10 +1640,6 @@ static bool internal_connect_apply_config (SQCloudConnection *connection, SQClou
15891640 len += snprintf (& buffer [len ], sizeof (buffer ) - len , "USE DATABASE %s;" , config -> database );
15901641 }
15911642
1592- if (config -> sqlite_mode ) {
1593- len += snprintf (& buffer [len ], sizeof (buffer ) - len , "SET CLIENT KEY SQLITE TO 1;" );
1594- }
1595-
15961643 if (config -> compression ) {
15971644 len += snprintf (& buffer [len ], sizeof (buffer ) - len , "SET CLIENT KEY COMPRESSION TO 1;" );
15981645 }
@@ -2450,10 +2497,6 @@ SQCloudConnection *SQCloudConnectWithString (const char *s, SQCloudConfig *pconf
24502497 int compression = (int )strtol (value , NULL , 0 );
24512498 config -> compression = (compression > 0 ) ? true : false;
24522499 }
2453- else if (strcasecmp (key , "sqlite" ) == 0 ) {
2454- int sqlite_mode = (int )strtol (value , NULL , 0 );
2455- config -> sqlite_mode = (sqlite_mode > 0 ) ? true : false;
2456- }
24572500 else if (strcasecmp (key , "zerotext" ) == 0 ) {
24582501 int zero_text = (int )strtol (value , NULL , 0 );
24592502 config -> zero_text = (zero_text > 0 ) ? true : false;
@@ -2505,7 +2548,6 @@ SQCloudConnection *SQCloudConnectWithString (const char *s, SQCloudConfig *pconf
25052548 if (pconfig ) {
25062549 if (pconfig -> timeout ) config -> timeout = pconfig -> timeout ;
25072550 if (pconfig -> compression ) config -> compression = pconfig -> compression ;
2508- if (pconfig -> sqlite_mode ) config -> sqlite_mode = pconfig -> sqlite_mode ;
25092551 if (pconfig -> zero_text ) config -> zero_text = pconfig -> zero_text ;
25102552 if (pconfig -> nonlinearizable ) config -> nonlinearizable = pconfig -> nonlinearizable ;
25112553 if (pconfig -> no_blob ) config -> no_blob = pconfig -> no_blob ;
@@ -2915,6 +2957,33 @@ char *SQCloudRowsetColumnOrigName (SQCloudResult *result, uint32_t col, uint32_t
29152957 return internal_get_rowset_header (result , result -> origname , col , len );
29162958}
29172959
2960+ uint32_t SQCloudRowSetColumnNotNULL (SQCloudResult * result , uint32_t col ) {
2961+ return internal_get_rowset_header_int (result , result -> notnull , col );
2962+ }
2963+
2964+ uint32_t SQCloudRowSetColumnPrimaryKey (SQCloudResult * result , uint32_t col ) {
2965+ return internal_get_rowset_header_int (result , result -> prikey , col );
2966+ }
2967+
2968+ uint32_t SQCloudRowSetColumnAutoIncrement (SQCloudResult * result , uint32_t col ) {
2969+ return internal_get_rowset_header_int (result , result -> autoinc , col );
2970+ }
2971+
2972+ bool SQCloudRowsetCanWrite (SQCloudResult * result ) {
2973+ // check if the rowset is not a JOIN (must have the same table)
2974+ char * keytable = result -> tblname [0 ];
2975+ for (int i = 1 ; i < result -> ncols ; ++ i ) {
2976+ if (strcmp (keytable , result -> tblname [i ]) != 0 ) return false;
2977+ }
2978+
2979+ // check if contains at least a primary key
2980+ for (int i = 0 ; i < result -> ncols ; ++ i ) {
2981+ if (result -> prikey [i ] == 1 ) return true;
2982+ }
2983+
2984+ return false;
2985+ }
2986+
29182987uint32_t SQCloudRowsetRows (SQCloudResult * result ) {
29192988 if (!SQCloudRowsetSanityCheck (result , 0 , 0 )) return 0 ;
29202989 return result -> nrows ;
0 commit comments