@@ -15,6 +15,13 @@ int cson_extract_int(cson_object *cson_obj, const char *param,
1515 struct errstat * err );
1616cson_array * cson_extract_array (cson_object * cson_obj , const char * param ,
1717 struct errstat * err );
18+ int views_sqlite_del_view (const char * view_name , sqlite3 * db ,
19+ struct errstat * err );
20+ char * describe_row (const char * tblname , const char * prefix ,
21+ enum views_trigger_op op_type , struct errstat * err );
22+
23+
24+
1825int gen_shard_serialize_shard (const char * tablename , uint32_t numdbs , char * * dbnames , uint32_t numcols ,
1926 char * * columns , char * * shardnames , uint32_t * outLen , char * * out )
2027{
@@ -165,11 +172,11 @@ int gen_shard_llmeta_read(void *tran, const char *name, char **pstr)
165172 return rc ;
166173}
167174
168- int gen_shard_deserialize_shard (uint32_t * numdbs , char * * * dbnames , uint32_t * numcols , char * * * columns , char * * * shardnames , char * serializedStr ) {
175+ int gen_shard_deserialize_shard (char * * genshard_name , uint32_t * numdbs , char * * * dbnames , uint32_t * numcols , char * * * columns , char * * * shardnames , char * serializedStr ) {
169176 cson_object * rootObj = NULL ;
170177 cson_value * rootVal = NULL , * arrVal = NULL ;
171178 cson_array * dbs_arr = NULL , * cols_arr = NULL , * shards_arr = NULL ;
172- const char * tablename = NULL ;
179+ char * tablename = NULL ;
173180 char * * dbs = NULL , * * cols = NULL , * * shards = NULL ;
174181 char * err_str = NULL ;
175182 int num_dbs = 0 , num_cols = 0 ;
@@ -186,7 +193,7 @@ int gen_shard_deserialize_shard(uint32_t *numdbs, char ***dbnames, uint32_t *num
186193 rc = cson_value_is_object (rootVal );
187194 rootObj = cson_value_get_object (rootVal );
188195
189- tablename = cson_extract_str (rootObj , "TABLENAME" , & err );
196+ tablename = ( char * ) cson_extract_str (rootObj , "TABLENAME" , & err );
190197 if (!tablename ) {
191198 err_str = "INVALID CSON. Couldn't find 'TABLENAME' key" ;
192199 goto error ;
@@ -262,7 +269,7 @@ int gen_shard_deserialize_shard(uint32_t *numdbs, char ***dbnames, uint32_t *num
262269 }
263270 shards [i ] = strdup (cson_value_get_cstr (arrVal ));
264271 }
265-
272+ * genshard_name = tablename ;
266273 * numdbs = num_dbs ;
267274 * dbnames = dbs ;
268275 * numcols = num_cols ;
@@ -308,21 +315,22 @@ int gen_shard_deserialize_shard(uint32_t *numdbs, char ***dbnames, uint32_t *num
308315int gen_shard_update_inmem_db (void * tran , struct dbtable * db , const char * name ) {
309316 char * serializedStr = NULL ;
310317 uint32_t numdbs = 0 , numcols = 0 ;
311- char * * dbnames = NULL , * * columns = NULL , * * shardnames = NULL ;
318+ char * * dbnames = NULL , * * columns = NULL , * * shardnames = NULL , * genshard_name = NULL ;
312319 int rc = 0 ;
313320 rc = gen_shard_llmeta_read (tran , name , & serializedStr );
314321 if (rc ) {
315322 logmsg (LOGMSG_ERROR , "Failed to read from llmeta for table %s\n" , name );
316323 goto done ;
317324 }
318325
319- rc = gen_shard_deserialize_shard (& numdbs , & dbnames , & numcols , & columns , & shardnames , serializedStr );
326+ rc = gen_shard_deserialize_shard (& genshard_name , & numdbs , & dbnames , & numcols , & columns , & shardnames , serializedStr );
320327 if (rc ) {
321328 logmsg (LOGMSG_ERROR , "Failed to deserialized llmeta str for table %s\n" , name );
322329 goto done ;
323330 }
324331
325332 /*update the table object*/
333+ db -> genshard_name = genshard_name ;
326334 db -> numdbs = numdbs ;
327335 db -> dbnames = dbnames ;
328336 db -> numcols = numcols ;
@@ -335,4 +343,159 @@ int gen_shard_update_inmem_db(void *tran, struct dbtable *db, const char *name)
335343 return rc ;
336344}
337345
346+ char * gen_shard_create_view_query (struct dbtable * tbl , sqlite3 * db , struct errstat * err )
347+ {
348+ char * select_str = NULL ;
349+ char * cols_str = NULL ;
350+ char * tmp_str = NULL ;
351+ char * ret_str = NULL ;
352+ int numshards = tbl -> numdbs ;
353+ const char * viewname = tbl -> genshard_name ;
354+ char * * dbnames = tbl -> dbnames ;
355+ char * * shardnames = tbl -> shardnames ;
356+ int i ;
357+ cols_str = sqlite3_mprintf ("rowid as __hidden__rowid, " );
358+ if (!cols_str ) {
359+ goto malloc ;
360+ }
361+
362+ cols_str = describe_row (tbl -> tablename , cols_str , VIEWS_TRIGGER_QUERY , err );
363+ if (!cols_str ) {
364+ /* preserve error, if any */
365+ if (err -> errval != VIEW_NOERR )
366+ return NULL ;
367+ goto malloc ;
368+ } else {
369+ logmsg (LOGMSG_USER , "GOT cols_str as %s\n" , cols_str );
370+ }
371+
372+ select_str = sqlite3_mprintf ("" );
373+ i = 0 ;
374+ logmsg (LOGMSG_USER , "num shards is : %d\n" , numshards );
375+ for (;i < numshards ;i ++ ){
376+ tmp_str = sqlite3_mprintf ("%s%sSELECT %s FROM %s.'\%s'" , select_str , (i > 0 ) ? " UNION ALL " : "" , cols_str ,
377+ dbnames [i ], shardnames [i ]);
378+ sqlite3_free (select_str );
379+ if (!tmp_str ) {
380+ sqlite3_free (cols_str );
381+ goto malloc ;
382+ }
383+ select_str = tmp_str ;
384+ }
385+
386+ ret_str = sqlite3_mprintf ("CREATE VIEW %w AS %s" , viewname , select_str );
387+ if (!ret_str ) {
388+ sqlite3_free (select_str );
389+ sqlite3_free (cols_str );
390+ goto malloc ;
391+ }
392+
393+ sqlite3_free (select_str );
394+ sqlite3_free (cols_str );
395+
396+ logmsg (LOGMSG_USER , "THE GENERATED VIEW QUERY IS %s\n" , ret_str );
397+ //dbg_verbose_sqlite("Generated:\n\"%s\"\n", ret_str);
398+
399+ return ret_str ;
400+
401+ malloc :
402+ err -> errval = VIEW_ERR_MALLOC ;
403+ snprintf (err -> errstr , sizeof (err -> errstr ), "View %s out of memory\n" , viewname );
404+ return NULL ;
405+ }
406+
407+ int gen_shard_run_sql (sqlite3 * db , char * stmt , struct errstat * err )
408+ {
409+ char * errstr = NULL ;
410+ int rc ;
411+
412+ /* create the view */
413+ rc = sqlite3_exec (db , stmt , NULL , NULL , & errstr );
414+ if (rc != SQLITE_OK ) {
415+ err -> errval = VIEW_ERR_BUG ;
416+ snprintf (err -> errstr , sizeof (err -> errstr ), "Sqlite error \"%s\"" , errstr );
417+ /* can't control sqlite errors */
418+ err -> errstr [sizeof (err -> errstr ) - 1 ] = '\0' ;
419+
420+ logmsg (LOGMSG_USER , "%s: sqlite error \"%s\" sql \"%s\"\n" , __func__ , errstr , stmt );
421+
422+ if (errstr )
423+ sqlite3_free (errstr );
424+ return err -> errval ;
425+ }
426+
427+ return VIEW_NOERR ;
428+ }
429+
430+ int gen_shard_add_view (struct dbtable * tbl , sqlite3 * db , struct errstat * err )
431+ {
432+ char * stmt_str ;
433+ int rc ;
434+
435+ /* create the statement */
436+ stmt_str = gen_shard_create_view_query (tbl , db , err );
437+ if (!stmt_str ) {
438+ return err -> errval ;
439+ }
440+
441+ rc = gen_shard_run_sql (db , stmt_str , err );
442+
443+ logmsg (LOGMSG_USER , "+++++++++++sql: %s, rc: %d\n" , stmt_str , rc );
444+ /* free the statement */
445+ sqlite3_free (stmt_str );
446+
447+ if (rc != VIEW_NOERR ) {
448+ return err -> errval ;
449+ }
450+ return rc ;
451+ }
452+
453+ int gen_shard_delete_view (struct dbtable * tbl , sqlite3 * db , struct errstat * err )
454+ {
455+ return views_sqlite_del_view (tbl -> genshard_name , db , err );
456+ }
457+
458+ int gen_shard_update_sqlite (sqlite3 * db , struct errstat * err )
459+ {
460+ Table * tab ;
461+ int rc ;
462+ for (int tbl_idx = 0 ; tbl_idx < thedb -> num_dbs ; ++ tbl_idx ) {
463+ struct dbtable * tbl = thedb -> dbs [tbl_idx ];
464+ if (tbl -> genshard_name ) {
465+ /* this table is a component shard of a genshard table*/
466+ tab = sqlite3FindTableCheckOnly (db , tbl -> genshard_name , NULL );
467+ if (tab ) {
468+ /* found view, is it the same version ? */
469+ if (tbl -> tableversion != tab -> version ) {
470+ /* older version, destroy current view */
471+ rc = gen_shard_delete_view (tbl , db , err );
472+ if (rc != VIEW_NOERR ) {
473+ logmsg (LOGMSG_ERROR , "%s: failed to remove old view\n" , __func__ );
474+ goto done ;
475+ }
476+ } else {
477+ /* up to date, nothing to do */
478+ continue ;
479+ }
480+ }
481+ rc = gen_shard_add_view (tbl , db , err );
482+ if (rc != VIEW_NOERR ) {
483+ goto done ;
484+ }
485+ }
486+ }
487+ rc = VIEW_NOERR ;
488+ done :
489+ return rc ;
490+ }
491+
492+ int is_gen_shard (const char * tablename ) {
493+ for (int i = 0 ;i < thedb -> num_dbs ;i ++ ) {
494+ struct dbtable * tbl = thedb -> dbs [i ];
495+ if (tbl -> genshard_name && strcmp (tbl -> genshard_name , tablename )== 0 ) {
496+ return 1 ;
497+ }
498+ }
499+ return 0 ;
500+ }
338501
0 commit comments