gboolean gc_db_check_boards() { SUPPORT_OR_RETURN(FALSE); #ifdef USE_SQLITE char *zErrMsg; char **result; int rc; int nrow; int ncolumn; gboolean ret_value; rc = sqlite3_get_table(gcompris_db, BOARDS_CHECK, &result, &nrow, &ncolumn, &zErrMsg ); if( rc!=SQLITE_OK ){ g_error("SQL error: %s\n", zErrMsg); } ret_value = (strcmp(result[2],VERSION)==0) && (result[3] != NULL); sqlite3_free_table(result); return ret_value; #endif }
/* --- functions --- */ gboolean g_module_supported (void) { SUPPORT_OR_RETURN (FALSE); return TRUE; }
gboolean gc_db_set_version(gchar *version) { SUPPORT_OR_RETURN(FALSE); #ifdef USE_SQLITE char *zErrMsg; char **result; int rc; int nrow; int ncolumn; gchar *request; request = g_strdup_printf(BOARDS_UPDATE_VERSION(version)); rc = sqlite3_get_table(gcompris_db, request, &result, &nrow, &ncolumn, &zErrMsg ); if( rc!=SQLITE_OK ){ g_error("SQL error: %s\n", zErrMsg); } g_free(request); sqlite3_free_table(result); return TRUE; #endif }
GcomprisProfile *gc_db_get_profile() { SUPPORT_OR_RETURN(NULL); #ifdef USE_SQLITE char *zErrMsg; char **result; int rc; int nrow; int ncolumn; int profile_id; rc = sqlite3_get_table(gcompris_db, GET_ACTIVE_PROFILE_ID, &result, &nrow, &ncolumn, &zErrMsg ); if( rc!=SQLITE_OK ){ g_error("SQL error: %s\n", zErrMsg); } profile_id = atoi(result[1]); sqlite3_free_table(result); return gc_db_get_profile_from_id(profile_id); #endif }
gboolean gc_db_exit() { SUPPORT_OR_RETURN(FALSE); #ifdef USE_SQLITE sqlite3_close(gcompris_db); g_message("Database closed"); return TRUE; #endif }
gboolean g_module_close (GModule *module) { SUPPORT_OR_RETURN (FALSE); g_return_val_if_fail (module != NULL, FALSE); g_return_val_if_fail (module->ref_count > 0, FALSE); g_static_rec_mutex_lock (&g_module_global_lock); module->ref_count--; if (!module->ref_count && !module->is_resident && module->unload) { GModuleUnload unload; unload = module->unload; module->unload = NULL; unload (module); } if (!module->ref_count && !module->is_resident) { GModule *last; GModule *node; last = NULL; node = modules; while (node) { if (node == module) { if (last) last->next = node->next; else modules = node->next; break; } last = node; node = last->next; } module->next = NULL; _g_module_close (module->handle, FALSE); g_free (module->file_name); #ifdef G_OS_WIN32 g_free (module->cp_file_name); #endif g_free (module); } g_static_rec_mutex_unlock (&g_module_global_lock); return g_module_error() == NULL; }
GList *gc_db_users_from_group_get(gint group_id) { SUPPORT_OR_RETURN(NULL); #ifdef USE_SQLITE char *zErrMsg; char **result; int rc; int nrow; int ncolumn; gchar *request; int i; GList *users = NULL; request = g_strdup_printf(USERS_FROM_GROUP(group_id)); rc = sqlite3_get_table(gcompris_db, request, &result, &nrow, &ncolumn, &zErrMsg ); if( rc!=SQLITE_OK ){ g_error("SQL error: %s\n", zErrMsg); } g_free(request); if (nrow == 0){ g_message("No users in the group id %d", group_id); } else { i = ncolumn; while (i < (nrow +1)*ncolumn) { GcomprisUser *user = g_malloc0(sizeof(GcomprisUser)); user->user_id = atoi(result[i++]); user->login = g_strdup(result[i++]); user->lastname = g_strdup(result[i++]); user->firstname = g_strdup(result[i++]); user->birthdate = g_strdup(result[i++]); user->class_id = atoi(result[i++]); users = g_list_append(users, user); } } return users; #else return NULL; #endif }
GcomprisUser *gc_db_get_user_from_id(gint user_id) { SUPPORT_OR_RETURN(NULL); #ifdef USE_SQLITE char *zErrMsg; char **result; int rc; int nrow; int ncolumn; gchar *request; int i; GcomprisUser *user = NULL; request = g_strdup_printf(USER_FROM_ID(user_id)); rc = sqlite3_get_table(gcompris_db, request, &result, &nrow, &ncolumn, &zErrMsg ); if( rc!=SQLITE_OK ){ g_error("SQL error: %s\n", zErrMsg); } g_free(request); if (nrow == 0){ g_message("No user with id %d", user_id); return NULL; } else { i = ncolumn; user = g_malloc0(sizeof(GcomprisUser)); user->user_id = user_id; user->login = g_strdup(result[i++]); user->lastname = g_strdup(result[i++]); user->firstname = g_strdup(result[i++]); user->birthdate = g_strdup(result[i++]); user->class_id = atoi(result[i++]); } return user ; #endif }
/** \brief Given a profile name, return a GcomprisProfile struct * * \param profile_name: the profile to retrieve. * * \return *GcomprisProfile */ GcomprisProfile * gc_db_profile_from_name_get(gchar *profile_name) { SUPPORT_OR_RETURN(FALSE); #ifdef USE_SQLITE GcomprisProfile *profile = NULL; char *zErrMsg; char **result; int rc; int nrow; int ncolumn; gchar *request; /* get section_id */ request = g_strdup_printf(GET_PROFILE_FROM_NAME(profile_name)); rc = sqlite3_get_table(gcompris_db, request, &result, &nrow, &ncolumn, &zErrMsg ); if( rc!=SQLITE_OK ){ g_error("SQL error: %s\n", zErrMsg); } if (nrow != 0){ gint profile_id; profile_id = atoi(result[3]); g_free(request); profile = gc_db_get_profile_from_id(profile_id); } return profile; #endif }
gboolean g_module_symbol (GModule *module, const gchar *symbol_name, gpointer *symbol) { const gchar *module_error; if (symbol) *symbol = NULL; SUPPORT_OR_RETURN (FALSE); g_return_val_if_fail (module != NULL, FALSE); g_return_val_if_fail (symbol_name != NULL, FALSE); g_return_val_if_fail (symbol != NULL, FALSE); g_static_rec_mutex_lock (&g_module_global_lock); #ifdef G_MODULE_NEED_USCORE { gchar *name; name = g_strconcat ("_", symbol_name, NULL); *symbol = _g_module_symbol (module->handle, name); g_free (name); } #else /* !G_MODULE_NEED_USCORE */ *symbol = _g_module_symbol (module->handle, symbol_name); #endif /* !G_MODULE_NEED_USCORE */ module_error = g_module_error (); if (module_error) { gchar *error; error = g_strconcat ("`", symbol_name, "': ", module_error, NULL); g_module_set_error (error); g_free (error); *symbol = NULL; } g_static_rec_mutex_unlock (&g_module_global_lock); return !module_error; }
GList *gc_db_get_board_id(GList *list) { SUPPORT_OR_RETURN(NULL); #ifdef USE_SQLITE GList *board_id_list = list; char *zErrMsg; char **result; int rc; int nrow; int ncolumn; int i; rc = sqlite3_get_table(gcompris_db, GC_BOARD_ID_READ, &result, &nrow, &ncolumn, &zErrMsg ); if( rc!=SQLITE_OK ){ g_error("SQL error: %s\n", zErrMsg); } /* first ncolumns are columns labels. */ i = ncolumn; while (i < (nrow +1)*ncolumn) { int *board_id = g_malloc(sizeof(int)); *board_id = atoi(result[i++]); board_id_list = g_list_append(board_id_list, board_id); } return board_id_list; #endif }
GList *gc_menu_load_db(GList *boards_list) { SUPPORT_OR_RETURN(NULL); #ifdef USE_SQLITE GList *boards = boards_list; char *zErrMsg; char **result; int rc; int nrow; int ncolumn; int i; rc = sqlite3_get_table(gcompris_db, BOARDS_READ, &result, &nrow, &ncolumn, &zErrMsg ); if( rc!=SQLITE_OK ){ g_error("SQL error: %s\n", zErrMsg); } /* first ncolumns are columns labels. */ i = ncolumn; while (i < (nrow +1)*ncolumn) { GcomprisBoard *gcomprisBoard = NULL; gcomprisBoard = g_malloc0 (sizeof (GcomprisBoard)); gcomprisBoard->plugin=NULL; gcomprisBoard->previous_board=NULL; gcomprisBoard->board_ready=FALSE; gcomprisBoard->canvas=gc_get_canvas(); gcomprisBoard->gmodule = NULL; gcomprisBoard->gmodule_file = NULL; gcomprisBoard->board_id = atoi(result[i++]); gcomprisBoard->name = g_strdup(result[i++]); gcomprisBoard->section_id = atoi(result[i++]); gcomprisBoard->section = g_strdup(result[i++]); gcomprisBoard->author = g_strdup(result[i++]); gcomprisBoard->type = g_strdup(result[i++]); gcomprisBoard->mode = g_strdup(result[i++]); gcomprisBoard->difficulty = g_strdup(result[i++]); gcomprisBoard->icon_name = g_strdup(result[i++]); gcomprisBoard->boarddir = g_strdup(result[i++]); gcomprisBoard->mandatory_sound_file = g_strdup(result[i++]); gcomprisBoard->mandatory_sound_dataset = g_strdup(result[i++]); gcomprisBoard->filename = g_strdup(result[i++]); gcomprisBoard->title = reactivate_newline(gettext(result[i++])); gcomprisBoard->description = reactivate_newline(gettext(result[i++])); gcomprisBoard->prerequisite = reactivate_newline(gettext(result[i++])); gcomprisBoard->goal = reactivate_newline(gettext(result[i++])); gcomprisBoard->manual = reactivate_newline(gettext(result[i++])); gcomprisBoard->credit = reactivate_newline(gettext(result[i++])); gcomprisBoard->demo = atoi(result[i++]); boards = g_list_append(boards, gcomprisBoard); gchar *msg = g_strdup_printf(_("Loading activity from database:\n%s"), gettext(gcomprisBoard->title)); gc_status_set_msg(msg); g_free(msg); } sqlite3_free_table(result); return boards; #endif }
gboolean gc_db_board_update(guint *board_id, guint *section_id, gchar *name, gchar *section, gchar *author, gchar *type, gchar *mode, int difficulty, gchar *icon, gchar *boarddir, gchar *mandatory_sound_file, gchar *mandatory_sound_dataset, gchar *filename, gchar *title, gchar *description, gchar *prerequisite, gchar *goal, gchar *manual, gchar *credit, int demo ) { SUPPORT_OR_RETURN(FALSE); #ifdef USE_SQLITE char *zErrMsg; char **result; int rc; int nrow; int ncolumn; gchar *request; if (gcompris_db == NULL) g_error("Database is closed !!!"); if (*board_id==0){ /* board not yet registered */ /* assume name is unique */ request = g_strdup_printf(CHECK_BOARD(name)); rc = sqlite3_get_table(gcompris_db, request, &result, &nrow, &ncolumn, &zErrMsg ); if( rc!=SQLITE_OK ){ g_error("SQL error: %s\n", zErrMsg); } g_free(request); if (nrow != 0){ *board_id = atoi(result[1]); sqlite3_free_table(result); } else { /* get last board_id written */ rc = sqlite3_get_table(gcompris_db, MAX_GC_BOARD_ID, &result, &nrow, &ncolumn, &zErrMsg ); if( rc!=SQLITE_OK ){ g_error("SQL error: %s\n", zErrMsg); } if (result[1] == NULL) *board_id = 1; else *board_id = atoi(result[1]) + 1; sqlite3_free_table(result); } } /* get section_id */ request = g_strdup_printf(SECTION_ID(section)); rc = sqlite3_get_table(gcompris_db, request, &result, &nrow, &ncolumn, &zErrMsg ); g_free(request); if( rc!=SQLITE_OK ){ g_error("SQL error: %s\n", zErrMsg); } if (nrow == 0){ /* get max section_id */ rc = sqlite3_get_table(gcompris_db, MAX_SECTION_ID, &result, &nrow, &ncolumn, &zErrMsg ); if( rc!=SQLITE_OK ){ g_error("SQL error: %s\n", zErrMsg); } if (result[1] == NULL){ *section_id = 1; } else { *section_id = atoi(result[1]) + 1; } sqlite3_free_table(result); } else { *section_id = atoi(result[1]); sqlite3_free_table(result); } request = sqlite3_mprintf( GC_BOARD_INSERT, *board_id, name, *section_id, section, author, type, mode, difficulty, icon, boarddir, mandatory_sound_file, mandatory_sound_dataset, filename, title, description, prerequisite, goal, manual, credit, demo ); rc = sqlite3_get_table(gcompris_db, request, &result, &nrow, &ncolumn, &zErrMsg ); if( rc!=SQLITE_OK ){ g_error("SQL error: %s\n", zErrMsg); } sqlite3_free_table(result); sqlite3_free(request); return TRUE; #endif }
gboolean gc_db_init(gboolean disable_database_) { #ifdef USE_SQLITE disable_database = disable_database_; SUPPORT_OR_RETURN(FALSE); gboolean creation = FALSE; char *zErrMsg; char **result; int rc; int nrow; int ncolumn; GcomprisProperties *properties = gc_prop_get(); if (!g_file_test(properties->database, G_FILE_TEST_EXISTS)) creation = TRUE; rc = sqlite3_open(properties->database, &gcompris_db); if( rc ){ g_message("Can't open database %s : %s\n", properties->database, sqlite3_errmsg(gcompris_db)); sqlite3_close(gcompris_db); disable_database = TRUE; return FALSE; } g_message("Database %s opened", properties->database); if (creation){ _create_db(); } else { if ( ! _check_db_integrity() || _gc_boards_count() == 0 ) { // We failed to load the database, let's // backup it and re create it. sqlite3_close(gcompris_db); gchar *backup = g_strdup_printf("%s.broken", properties->database); g_rename(properties->database, backup); g_message("Database is broken, it is copyed in %s", backup); g_free(backup); rc = sqlite3_open(properties->database, &gcompris_db); if( rc ){ g_message("Can't open database %s : %s\n", properties->database, sqlite3_errmsg(gcompris_db)); sqlite3_close(gcompris_db); disable_database = TRUE; return FALSE; } _create_db(); if ( ! _check_db_integrity() ) { disable_database = TRUE; return FALSE; } } g_message("Database Integrity ok"); rc = sqlite3_get_table(gcompris_db, CHECK_VERSION, &result, &nrow, &ncolumn, &zErrMsg ); if( rc!=SQLITE_OK ){ g_error("SQL error: %s\n", zErrMsg); } if (strcmp(result[1],VERSION)!=0) g_message("Running GCompris is %s, but database version is %s", VERSION, result[1]); sqlite3_free_table(result); /* Schema upgrade */ rc = sqlite3_get_table(gcompris_db, PRAGMA_SCHEMA_VERSION, &result, &nrow, &ncolumn, &zErrMsg ); if( rc!=SQLITE_OK ){ g_error("SQL error: %s\n", zErrMsg); } int version = atoi(result[1]); sqlite3_free_table(result); if(version <= 16) { g_message("Upgrading from <16 schema version\n"); rc = sqlite3_exec(gcompris_db,CREATE_TABLE_LOGS, NULL, 0, &zErrMsg); if( rc!=SQLITE_OK ) { g_error("SQL error: %s\n", zErrMsg); } } if ( _get_user_version() == 0) { g_message("Upgrading schema based on user version = 0\n"); rc = sqlite3_exec(gcompris_db,"DROP TABLE boards;", NULL, 0, &zErrMsg); if( rc!=SQLITE_OK ) { g_error("SQL error: %s\n", zErrMsg); } rc = sqlite3_exec(gcompris_db,CREATE_TABLE_BOARDS, NULL, 0, &zErrMsg); if( rc!=SQLITE_OK ) { g_error("SQL error: %s\n", zErrMsg); } // We just dropped the boards table, force a reread properties->reread_menu = TRUE; _set_user_version(1); } } return TRUE; #else return FALSE; #endif }
GModule* g_module_open (const gchar *file_name, GModuleFlags flags) { GModule *module; gpointer handle = NULL; gchar *name = NULL; SUPPORT_OR_RETURN (NULL); g_static_rec_mutex_lock (&g_module_global_lock); if (G_UNLIKELY (!module_debug_initialized)) _g_module_debug_init (); if (module_debug_flags & G_MODULE_DEBUG_BIND_NOW_MODULES) flags &= ~G_MODULE_BIND_LAZY; if (!file_name) { if (!main_module) { handle = _g_module_self (); if (handle) { main_module = g_new (GModule, 1); main_module->file_name = NULL; #ifdef G_OS_WIN32 main_module->cp_file_name = NULL; #endif main_module->handle = handle; main_module->ref_count = 1; main_module->is_resident = TRUE; main_module->unload = NULL; main_module->next = NULL; } } else main_module->ref_count++; g_static_rec_mutex_unlock (&g_module_global_lock); return main_module; } /* we first search the module list by name */ module = g_module_find_by_name (file_name); if (module) { module->ref_count++; g_static_rec_mutex_unlock (&g_module_global_lock); return module; } /* check whether we have a readable file right away */ if (g_file_test (file_name, G_FILE_TEST_IS_REGULAR)) name = g_strdup (file_name); /* try completing file name with standard library suffix */ if (!name) { name = g_strconcat (file_name, "." G_MODULE_SUFFIX, NULL); if (!g_file_test (name, G_FILE_TEST_IS_REGULAR)) { g_free (name); name = NULL; } } /* try completing by appending libtool suffix */ if (!name) { name = g_strconcat (file_name, ".la", NULL); if (!g_file_test (name, G_FILE_TEST_IS_REGULAR)) { g_free (name); name = NULL; } } /* we can't access() the file, lets hope the platform backends finds * it via library paths */ if (!name) { gchar *dot = strrchr (file_name, '.'); gchar *slash = strrchr (file_name, G_DIR_SEPARATOR); /* make sure the name has a suffix */ if (!dot || dot < slash) name = g_strconcat (file_name, "." G_MODULE_SUFFIX, NULL); else name = g_strdup (file_name); } /* ok, try loading the module */ if (name) { /* if it's a libtool archive, figure library file to load */ if (str_check_suffix (name, ".la")) /* libtool archive? */ { gchar *real_name = parse_libtool_archive (name); /* real_name might be NULL, but then module error is already set */ if (real_name) { g_free (name); name = real_name; } } if (name) handle = _g_module_open (name, (flags & G_MODULE_BIND_LAZY) != 0, (flags & G_MODULE_BIND_LOCAL) != 0); } else { gchar *display_file_name = g_filename_display_name (file_name); g_module_set_error_unduped (g_strdup_printf ("unable to access file \"%s\"", display_file_name)); g_free (display_file_name); } g_free (name); if (handle) { gchar *saved_error; GModuleCheckInit check_init; const gchar *check_failed = NULL; /* search the module list by handle, since file names are not unique */ module = g_module_find_by_handle (handle); if (module) { _g_module_close (module->handle, TRUE); module->ref_count++; g_module_set_error (NULL); g_static_rec_mutex_unlock (&g_module_global_lock); return module; } saved_error = g_strdup (g_module_error ()); g_module_set_error (NULL); module = g_new (GModule, 1); module->file_name = g_strdup (file_name); #ifdef G_OS_WIN32 module->cp_file_name = g_locale_from_utf8 (file_name, -1, NULL, NULL, NULL); #endif module->handle = handle; module->ref_count = 1; module->is_resident = FALSE; module->unload = NULL; module->next = modules; modules = module; /* check initialization */ if (g_module_symbol (module, "g_module_check_init", (gpointer) &check_init) && check_init != NULL) check_failed = check_init (module); /* we don't call unload() if the initialization check failed. */ if (!check_failed) g_module_symbol (module, "g_module_unload", (gpointer) &module->unload); if (check_failed) { gchar *error; error = g_strconcat ("GModule (", file_name ? file_name : "NULL", ") initialization check failed: ", check_failed, NULL); g_module_close (module); module = NULL; g_module_set_error (error); g_free (error); } else g_module_set_error (saved_error); g_free (saved_error); } if (module != NULL && (module_debug_flags & G_MODULE_DEBUG_RESIDENT_MODULES)) g_module_make_resident (module); g_static_rec_mutex_unlock (&g_module_global_lock); return module; }
GcomprisProfile *gc_db_get_profile_from_id(gint profile_id) { SUPPORT_OR_RETURN(FALSE); #ifdef USE_SQLITE GcomprisProfile *profile = NULL; char *zErrMsg; char **result; int rc; int nrow; int ncolumn; gchar *request; int i; GList *ids; /* get section_id */ request = g_strdup_printf(GET_PROFILE(profile_id)); rc = sqlite3_get_table(gcompris_db, request, &result, &nrow, &ncolumn, &zErrMsg ); if( rc!=SQLITE_OK ){ g_error("SQL error: %s\n", zErrMsg); } if (nrow != 0){ profile = g_malloc0(sizeof(GcomprisProfile)); profile->profile_id = profile_id; profile->name = g_strdup(result[3]); profile->directory = g_strdup(result[4]); profile->description = g_strdup(result[5]); sqlite3_free_table(result); g_free(request); request = g_strdup_printf(GET_GROUPS_IN_PROFILE(profile->profile_id)); rc = sqlite3_get_table(gcompris_db, request, &result, &nrow, &ncolumn, &zErrMsg ); if( rc!=SQLITE_OK ){ g_error("SQL error: %s\n", zErrMsg); } g_free(request); if (nrow == 0){ g_message("No users' groups for profile %s", profile->name); profile->group_ids = NULL; } else { ids = NULL; i = ncolumn; while (i < (nrow +1)*ncolumn) { int *group_id = g_malloc(sizeof(int)); *group_id = atoi(result[i++]); ids = g_list_append(ids, group_id); } profile->group_ids = ids; } sqlite3_free_table(result); request = g_strdup_printf(GET_ACTIVITIES_OUT_OF_PROFILE(profile->profile_id)); rc = sqlite3_get_table(gcompris_db, request, &result, &nrow, &ncolumn, &zErrMsg ); if( rc!=SQLITE_OK ){ g_error("SQL error: %s\n", zErrMsg); } g_free(request); if (nrow == 0){ g_message("No activities for profile %s", profile->name); profile->activities = NULL; } else { ids = NULL; i = ncolumn; while (i < (nrow +1)*ncolumn) { int *board_id = g_malloc(sizeof(int)); *board_id = atoi(result[i++]); ids = g_list_append(ids, board_id); } profile->activities = ids; } sqlite3_free_table(result); } return profile; #endif }
gboolean gc_db_remove_board(int board_id) { SUPPORT_OR_RETURN(FALSE); #ifdef USE_SQLITE char *zErrMsg; char **result; int rc; int nrow; int ncolumn; gchar *request; /* get section_id */ request = g_strdup_printf(DELETE_BOARD("boards",board_id)); rc = sqlite3_get_table(gcompris_db, request, &result, &nrow, &ncolumn, &zErrMsg ); if( rc!=SQLITE_OK ){ g_error("SQL error: %s\n", zErrMsg); } g_free(request); /* get section_id */ request = g_strdup_printf(DELETE_BOARD("board_profile_conf",board_id)); rc = sqlite3_get_table(gcompris_db, request, &result, &nrow, &ncolumn, &zErrMsg ); if( rc!=SQLITE_OK ){ g_error("SQL error: %s\n", zErrMsg); } g_free(request); /* get section_id */ request = g_strdup_printf(DELETE_BOARD("activities_out",board_id)); rc = sqlite3_get_table(gcompris_db, request, &result, &nrow, &ncolumn, &zErrMsg ); if( rc!=SQLITE_OK ){ g_error("SQL error: %s\n", zErrMsg); } g_free(request); return TRUE; #endif }
GcomprisClass *gc_db_get_class_from_id(gint class_id) { SUPPORT_OR_RETURN(NULL); #ifdef USE_SQLITE char *zErrMsg; char **result; int rc; int nrow; int ncolumn; gchar *request; int i; GcomprisClass *class = NULL; request = g_strdup_printf(CLASS_FROM_ID(class_id)); rc = sqlite3_get_table(gcompris_db, request, &result, &nrow, &ncolumn, &zErrMsg ); if( rc!=SQLITE_OK ){ g_error("SQL error: %s\n", zErrMsg); } g_free(request); if (nrow == 0){ g_message("No class with id %d", class_id); return NULL; return NULL; } else { i = ncolumn; class = g_malloc0(sizeof(GcomprisClass)); class->class_id = class_id; class->name = g_strdup(result[i++]); class->description = g_strdup(result[i++]); class->wholegroup_id = atoi(result[i++]); } /* Group _ids */ GList *group_ids = NULL; request = g_strdup_printf(GROUPS_IN_CLASS(class_id)); rc = sqlite3_get_table(gcompris_db, request, &result, &nrow, &ncolumn, &zErrMsg ); if( rc!=SQLITE_OK ){ g_error("SQL error: %s\n", zErrMsg); } g_free(request); if (nrow == 0){ g_error("No groups found for class id %d: there must be at least one for the whole class with id (%d)", class_id, class->wholegroup_id); g_free(class); class = NULL; } else {