/* * Delete Pool record, must also delete all associated * Media records. * * Returns: false on error * true on success * PoolId = number of Pools deleted (should be 1) * NumVols = number of Media records deleted */ bool db_delete_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr) { bool retval = false; SQL_ROW row; int num_rows; char esc[MAX_ESCAPE_NAME_LENGTH]; db_lock(mdb); mdb->db_escape_string(jcr, esc, pr->Name, strlen(pr->Name)); Mmsg(mdb->cmd, "SELECT PoolId FROM Pool WHERE Name='%s'", esc); Dmsg1(10, "selectpool: %s\n", mdb->cmd); pr->PoolId = pr->NumVols = 0; if (QUERY_DB(jcr, mdb, mdb->cmd)) { num_rows = sql_num_rows(mdb); if (num_rows == 0) { Mmsg(mdb->errmsg, _("No pool record %s exists\n"), pr->Name); sql_free_result(mdb); goto bail_out; } else if (num_rows != 1) { Mmsg(mdb->errmsg, _("Expecting one pool record, got %d\n"), num_rows); sql_free_result(mdb); goto bail_out; } if ((row = sql_fetch_row(mdb)) == NULL) { Mmsg1(mdb->errmsg, _("Error fetching row %s\n"), sql_strerror(mdb)); goto bail_out; } pr->PoolId = str_to_int64(row[0]); sql_free_result(mdb); } /* Delete Media owned by this pool */ Mmsg(mdb->cmd, "DELETE FROM Media WHERE Media.PoolId = %d", pr->PoolId); pr->NumVols = DELETE_DB(jcr, mdb, mdb->cmd); Dmsg1(200, "Deleted %d Media records\n", pr->NumVols); /* Delete Pool */ Mmsg(mdb->cmd, "DELETE FROM Pool WHERE Pool.PoolId = %d", pr->PoolId); pr->PoolId = DELETE_DB(jcr, mdb, mdb->cmd); Dmsg1(200, "Deleted %d Pool records\n", pr->PoolId); retval = true; bail_out: db_unlock(mdb); return retval; }
void db_list_copies_records(JCR *jcr, B_DB *mdb, uint32_t limit, char *JobIds, OUTPUT_FORMATTER *send, e_list_type type) { POOL_MEM str_limit(PM_MESSAGE); POOL_MEM str_jobids(PM_MESSAGE); if (limit > 0) { Mmsg(str_limit, " LIMIT %d", limit); } if (JobIds && JobIds[0]) { Mmsg(str_jobids, " AND (Job.PriorJobId IN (%s) OR Job.JobId IN (%s)) ", JobIds, JobIds); } db_lock(mdb); Mmsg(mdb->cmd, "SELECT DISTINCT Job.PriorJobId AS JobId, Job.Job, " "Job.JobId AS CopyJobId, Media.MediaType " "FROM Job " "JOIN JobMedia USING (JobId) " "JOIN Media USING (MediaId) " "WHERE Job.Type = '%c' %s ORDER BY Job.PriorJobId DESC %s", (char) JT_JOB_COPY, str_jobids.c_str(), str_limit.c_str()); if (!QUERY_DB(jcr, mdb, mdb->cmd)) { goto bail_out; } if (sql_num_rows(mdb)) { if (JobIds && JobIds[0]) { send->decoration(_("These JobIds have copies as follows:\n")); } else { send->decoration(_("The catalog contains copies as follows:\n")); } send->object_start("copies"); list_result(jcr, mdb, send, type); send->object_end("copies"); } sql_free_result(mdb); bail_out: db_unlock(mdb); }
/* * If full_list is set, we list vertically, otherwise, we * list on one line horizontally. * Return number of rows */ int list_result(JCR *jcr, B_DB *mdb, OUTPUT_FORMATTER *send, e_list_type type) { SQL_FIELD *field; SQL_ROW row; int i, col_len, max_len = 0; int num_fields; char ewc[30]; POOL_MEM key; POOL_MEM value; Dmsg0(800, "list_result starts\n"); if (sql_num_rows(mdb) == 0) { send->decoration(_("No results to list.\n")); send->object_end("table"); return sql_num_rows(mdb); } num_fields = sql_num_fields(mdb); switch (type) { case NF_LIST: case RAW_LIST: /* * No need to calculate things like column widths for * unformated or raw output. */ break; case HORZ_LIST: case VERT_LIST: Dmsg1(800, "list_result starts looking at %d fields\n", num_fields); /* * Determine column display widths */ sql_field_seek(mdb, 0); for (i = 0; i < num_fields; i++) { Dmsg1(800, "list_result processing field %d\n", i); field = sql_fetch_field(mdb); if (!field) { break; } col_len = cstrlen(field->name); if (type == VERT_LIST) { if (col_len > max_len) { max_len = col_len; } } else { if (sql_field_is_numeric(mdb, field->type) && (int)field->max_length > 0) { /* fixup for commas */ field->max_length += (field->max_length - 1) / 3; } if (col_len < (int)field->max_length) { col_len = field->max_length; } if (col_len < 4 && !sql_field_is_not_null(mdb, field->flags)) { col_len = 4; /* 4 = length of the word "NULL" */ } field->max_length = col_len; /* reset column info */ } } break; } Dmsg0(800, "list_result finished first loop\n"); switch (type) { case NF_LIST: case RAW_LIST: Dmsg1(800, "list_result starts second loop looking at %d fields\n", num_fields); while ((row = sql_fetch_row(mdb)) != NULL) { send->object_start(row[0]); sql_field_seek(mdb, 0); for (i = 0; i < num_fields; i++) { field = sql_fetch_field(mdb); if (!field) { break; } if (row[i] == NULL) { value.bsprintf(" %s", "NULL"); } else { value.bsprintf(" %s", row[i]); } send->object_key_value(field->name, value.c_str(), "%s"); } if (type != RAW_LIST) { send->decoration("\n"); } send->object_end(row[0]); } break; case HORZ_LIST: Dmsg1(800, "list_result starts second loop looking at %d fields\n", num_fields); list_dashes(mdb, send); send->decoration("|"); sql_field_seek(mdb, 0); for (i = 0; i < num_fields; i++) { Dmsg1(800, "list_result looking at field %d\n", i); field = sql_fetch_field(mdb); if (!field) { break; } max_len = max_length(field->max_length); send->decoration(" %-*s |", max_len, field->name); } send->decoration("\n"); list_dashes(mdb, send); Dmsg1(800, "list_result starts third loop looking at %d fields\n", num_fields); while ((row = sql_fetch_row(mdb)) != NULL) { send->object_start(row[0]); sql_field_seek(mdb, 0); send->decoration("|"); for (i = 0; i < num_fields; i++) { field = sql_fetch_field(mdb); if (!field) { break; } max_len = max_length(field->max_length); if (row[i] == NULL) { value.bsprintf(" %-*s |", max_len, "NULL"); } else if (sql_field_is_numeric(mdb, field->type) && !jcr->gui && is_an_integer(row[i])) { value.bsprintf(" %*s |", max_len, add_commas(row[i], ewc)); } else { value.bsprintf(" %-*s |", max_len, row[i]); } if (i == num_fields-1) { value.strcat("\n"); } /* use value format string to send preformated value */ send->object_key_value(field->name, row[i], value.c_str()); } send->object_end(row[0]); } list_dashes(mdb, send); break; case VERT_LIST: Dmsg1(800, "list_result starts vertical list at %d fields\n", num_fields); while ((row = sql_fetch_row(mdb)) != NULL) { send->object_start(row[0]); sql_field_seek(mdb, 0); for (i = 0; i < num_fields; i++) { field = sql_fetch_field(mdb); if (!field) { break; } if (row[i] == NULL) { key.bsprintf(" %*s: ", max_len, field->name); value.bsprintf("%s\n", "NULL"); } else if (sql_field_is_numeric(mdb, field->type) && !jcr->gui && is_an_integer(row[i])) { key.bsprintf(" %*s: ", max_len, field->name); value.bsprintf("%s\n", add_commas(row[i], ewc)); } else { key.bsprintf(" %*s: ", max_len, field->name); value.bsprintf("%s\n", row[i]); } /* use value format string to send preformated value */ send->object_key_value(field->name, key.c_str(), row[i], value.c_str()); } send->decoration("\n"); send->object_end(row[0]); } break; } return sql_num_rows(mdb); }
/* * Find Available Media (Volume) for Pool * * Find a Volume for a given PoolId, MediaType, and Status. * The unwanted_volumes variable lists the VolumeNames which we should skip if any. * * Returns: 0 on failure * numrows on success */ int db_find_next_volume(JCR *jcr, B_DB *mdb, int item, bool InChanger, MEDIA_DBR *mr, const char *unwanted_volumes) { char ed1[50]; int num_rows = 0; SQL_ROW row = NULL; bool find_oldest = false; bool found_candidate = false; char esc_type[MAX_ESCAPE_NAME_LENGTH]; char esc_status[MAX_ESCAPE_NAME_LENGTH]; db_lock(mdb); mdb->db_escape_string(jcr, esc_type, mr->MediaType, strlen(mr->MediaType)); mdb->db_escape_string(jcr, esc_status, mr->VolStatus, strlen(mr->VolStatus)); if (item == -1) { find_oldest = true; item = 1; } retry_fetch: if (find_oldest) { /* * Find oldest volume(s) */ Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks," "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes," "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs," "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger," "EndFile,EndBlock,LabelType,LabelDate,StorageId," "Enabled,LocationId,RecycleCount,InitialWrite," "ScratchPoolId,RecyclePoolId,VolReadTime,VolWriteTime," "ActionOnPurge,EncryptionKey,MinBlocksize,MaxBlocksize " "FROM Media WHERE PoolId=%s AND MediaType='%s' AND VolStatus IN ('Full'," "'Recycle','Purged','Used','Append') AND Enabled=1 " "ORDER BY LastWritten LIMIT %d", edit_int64(mr->PoolId, ed1), esc_type, item); } else { POOL_MEM changer(PM_FNAME); const char *order; /* * Find next available volume */ if (InChanger) { Mmsg(changer, "AND InChanger=1 AND StorageId=%s", edit_int64(mr->StorageId, ed1)); } if (bstrcmp(mr->VolStatus, "Recycle") || bstrcmp(mr->VolStatus, "Purged")) { order = "AND Recycle=1 ORDER BY LastWritten ASC,MediaId"; /* take oldest that can be recycled */ } else { order = sql_media_order_most_recently_written[db_get_type_index(mdb)]; /* take most recently written */ } Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks," "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes," "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs," "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger," "EndFile,EndBlock,LabelType,LabelDate,StorageId," "Enabled,LocationId,RecycleCount,InitialWrite," "ScratchPoolId,RecyclePoolId,VolReadTime,VolWriteTime," "ActionOnPurge,EncryptionKey,MinBlocksize,MaxBlocksize " "FROM Media WHERE PoolId=%s AND MediaType='%s' AND Enabled=1 " "AND VolStatus='%s' " "%s " "%s LIMIT %d", edit_int64(mr->PoolId, ed1), esc_type, esc_status, changer.c_str(), order, item); } Dmsg1(100, "fnextvol=%s\n", mdb->cmd); if (!QUERY_DB(jcr, mdb, mdb->cmd)) { goto bail_out; } num_rows = sql_num_rows(mdb); if (item > num_rows || item < 1) { Dmsg2(050, "item=%d got=%d\n", item, num_rows); Mmsg2(&mdb->errmsg, _("Request for Volume item %d greater than max %d or less than 1\n"), item, num_rows); num_rows = 0; goto bail_out; } for (int i = 0 ; i < item; i++) { if ((row = sql_fetch_row(mdb)) == NULL) { Dmsg1(050, "Fail fetch item=%d\n", i); Mmsg1(&mdb->errmsg, _("No Volume record found for item %d.\n"), i); sql_free_result(mdb); num_rows = 0; goto bail_out; } /* * See if this is not on the unwanted volumes list. */ if (unwanted_volumes && is_on_unwanted_volumes_list(row[1], unwanted_volumes)) { continue; } /* * Return fields in Media Record */ mr->MediaId = str_to_int64(row[0]); bstrncpy(mr->VolumeName, (row[1] != NULL) ? row[1] : "", sizeof(mr->VolumeName)); mr->VolJobs = str_to_int64(row[2]); mr->VolFiles = str_to_int64(row[3]); mr->VolBlocks = str_to_int64(row[4]); mr->VolBytes = str_to_uint64(row[5]); mr->VolMounts = str_to_int64(row[6]); mr->VolErrors = str_to_int64(row[7]); mr->VolWrites = str_to_int64(row[8]); mr->MaxVolBytes = str_to_uint64(row[9]); mr->VolCapacityBytes = str_to_uint64(row[10]); bstrncpy(mr->MediaType, (row[11] != NULL) ? row[11] : "", sizeof(mr->MediaType)); bstrncpy(mr->VolStatus, (row[12] != NULL) ? row[12] : "", sizeof(mr->VolStatus)); mr->PoolId = str_to_int64(row[13]); mr->VolRetention = str_to_uint64(row[14]); mr->VolUseDuration = str_to_uint64(row[15]); mr->MaxVolJobs = str_to_int64(row[16]); mr->MaxVolFiles = str_to_int64(row[17]); mr->Recycle = str_to_int64(row[18]); mr->Slot = str_to_int64(row[19]); bstrncpy(mr->cFirstWritten, (row[20] != NULL) ? row[20] : "", sizeof(mr->cFirstWritten)); mr->FirstWritten = (time_t)str_to_utime(mr->cFirstWritten); bstrncpy(mr->cLastWritten, (row[21] != NULL) ? row[21] : "", sizeof(mr->cLastWritten)); mr->LastWritten = (time_t)str_to_utime(mr->cLastWritten); mr->InChanger = str_to_uint64(row[22]); mr->EndFile = str_to_uint64(row[23]); mr->EndBlock = str_to_uint64(row[24]); mr->LabelType = str_to_int64(row[25]); bstrncpy(mr->cLabelDate, (row[26] != NULL) ? row[26] : "", sizeof(mr->cLabelDate)); mr->LabelDate = (time_t)str_to_utime(mr->cLabelDate); mr->StorageId = str_to_int64(row[27]); mr->Enabled = str_to_int64(row[28]); mr->LocationId = str_to_int64(row[29]); mr->RecycleCount = str_to_int64(row[30]); bstrncpy(mr->cInitialWrite, (row[31] != NULL) ? row[31] : "", sizeof(mr->cInitialWrite)); mr->InitialWrite = (time_t)str_to_utime(mr->cInitialWrite); mr->ScratchPoolId = str_to_int64(row[32]); mr->RecyclePoolId = str_to_int64(row[33]); mr->VolReadTime = str_to_int64(row[34]); mr->VolWriteTime = str_to_int64(row[35]); mr->ActionOnPurge = str_to_int64(row[36]); bstrncpy(mr->EncrKey, (row[37] != NULL) ? row[37] : "", sizeof(mr->EncrKey)); mr->MinBlocksize = str_to_int32(row[38]); mr->MaxBlocksize = str_to_int32(row[39]); sql_free_result(mdb); found_candidate = true; break; } if (!found_candidate && find_oldest) { item++; goto retry_fetch; } bail_out: db_unlock(mdb); Dmsg1(050, "Rtn numrows=%d\n", num_rows); return num_rows; }
/************************************************************************* * * Function: sql_affected_rows * * Purpose: Return the number of rows affected by the query (update, * or insert) * *************************************************************************/ static int sql_affected_rows(SQLSOCK *sqlsocket, SQL_CONFIG *config) { return sql_num_rows(sqlsocket, config); }
/* * Find Available Media (Volume) for Pool * * Find a Volume for a given PoolId, MediaType, and Status. * * Returns: 0 on failure * numrows on success */ int BDB::bdb_find_next_volume(JCR *jcr, int item, bool InChanger, MEDIA_DBR *mr) { SQL_ROW row = NULL; int numrows; const char *order; char esc_type[MAX_ESCAPE_NAME_LENGTH]; char esc_status[MAX_ESCAPE_NAME_LENGTH]; char ed1[50]; bdb_lock(); bdb_escape_string(jcr, esc_type, mr->MediaType, strlen(mr->MediaType)); bdb_escape_string(jcr, esc_status, mr->VolStatus, strlen(mr->VolStatus)); if (item == -1) { /* find oldest volume */ /* Find oldest volume */ Mmsg(cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks," "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes," "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs," "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger," "EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId," "Enabled,LocationId,RecycleCount,InitialWrite," "ScratchPoolId,RecyclePoolId,VolReadTime,VolWriteTime,ActionOnPurge " "FROM Media WHERE PoolId=%s AND MediaType='%s' AND VolStatus IN ('Full'," "'Recycle','Purged','Used','Append') AND Enabled=1 " "ORDER BY LastWritten LIMIT 1", edit_int64(mr->PoolId, ed1), esc_type); item = 1; } else { POOL_MEM changer(PM_FNAME); POOL_MEM voltype(PM_FNAME); POOL_MEM exclude(PM_FNAME); /* Find next available volume */ if (InChanger) { Mmsg(changer, " AND InChanger=1 AND StorageId=%s ", edit_int64(mr->StorageId, ed1)); } /* Volumes will be automatically excluded from the query, we just take the * first one of the list */ if (mr->exclude_list && *mr->exclude_list) { item = 1; Mmsg(exclude, " AND MediaId NOT IN (%s) ", mr->exclude_list); } if (strcmp(mr->VolStatus, "Recycle") == 0 || strcmp(mr->VolStatus, "Purged") == 0) { order = "AND Recycle=1 ORDER BY LastWritten ASC,MediaId"; /* take oldest that can be recycled */ } else { order = sql_media_order_most_recently_written[bdb_get_type_index()]; /* take most recently written */ } Mmsg(cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks," "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes," "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs," "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger," "EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId," "Enabled,LocationId,RecycleCount,InitialWrite," "ScratchPoolId,RecyclePoolId,VolReadTime,VolWriteTime,ActionOnPurge " "FROM Media WHERE PoolId=%s AND MediaType='%s' AND Enabled=1 " "AND VolStatus='%s' " "%s " "%s " "%s " "%s LIMIT %d", edit_int64(mr->PoolId, ed1), esc_type, esc_status, voltype.c_str(), changer.c_str(), exclude.c_str(), order, item); } Dmsg1(100, "fnextvol=%s\n", cmd); if (!QueryDB(jcr, cmd)) { bdb_unlock(); return 0; } numrows = sql_num_rows(); if (item > numrows || item < 1) { Dmsg2(050, "item=%d got=%d\n", item, numrows); Mmsg2(&errmsg, _("Request for Volume item %d greater than max %d or less than 1\n"), item, numrows); bdb_unlock(); return 0; } /* Note, we previously seeked to the row using: * sql_data_seek(item-1); * but this failed on PostgreSQL, so now we loop * over all the records. This should not be too horrible since * the maximum Volumes we look at in any case is 20. */ while (item-- > 0) { if ((row = sql_fetch_row()) == NULL) { Dmsg1(050, "Fail fetch item=%d\n", item+1); Mmsg1(&errmsg, _("No Volume record found for item %d.\n"), item); sql_free_result(); bdb_unlock(); return 0; } } /* Return fields in Media Record */ mr->MediaId = str_to_int64(row[0]); bstrncpy(mr->VolumeName, row[1]!=NULL?row[1]:"", sizeof(mr->VolumeName)); mr->VolJobs = str_to_int64(row[2]); mr->VolFiles = str_to_int64(row[3]); mr->VolBlocks = str_to_int64(row[4]); mr->VolBytes = str_to_uint64(row[5]); mr->VolMounts = str_to_int64(row[6]); mr->VolErrors = str_to_int64(row[7]); mr->VolWrites = str_to_int64(row[8]); mr->MaxVolBytes = str_to_uint64(row[9]); mr->VolCapacityBytes = str_to_uint64(row[10]); bstrncpy(mr->MediaType, row[11]!=NULL?row[11]:"", sizeof(mr->MediaType)); bstrncpy(mr->VolStatus, row[12]!=NULL?row[12]:"", sizeof(mr->VolStatus)); mr->PoolId = str_to_int64(row[13]); mr->VolRetention = str_to_uint64(row[14]); mr->VolUseDuration = str_to_uint64(row[15]); mr->MaxVolJobs = str_to_int64(row[16]); mr->MaxVolFiles = str_to_int64(row[17]); mr->Recycle = str_to_int64(row[18]); mr->Slot = str_to_int64(row[19]); bstrncpy(mr->cFirstWritten, row[20]!=NULL?row[20]:"", sizeof(mr->cFirstWritten)); mr->FirstWritten = (time_t)str_to_utime(mr->cFirstWritten); bstrncpy(mr->cLastWritten, row[21]!=NULL?row[21]:"", sizeof(mr->cLastWritten)); mr->LastWritten = (time_t)str_to_utime(mr->cLastWritten); mr->InChanger = str_to_uint64(row[22]); mr->EndFile = str_to_uint64(row[23]); mr->EndBlock = str_to_uint64(row[24]); mr->VolType = str_to_int64(row[25]); /* formerly VolParts */ mr->LabelType = str_to_int64(row[26]); bstrncpy(mr->cLabelDate, row[27]!=NULL?row[27]:"", sizeof(mr->cLabelDate)); mr->LabelDate = (time_t)str_to_utime(mr->cLabelDate); mr->StorageId = str_to_int64(row[28]); mr->Enabled = str_to_int64(row[29]); mr->LocationId = str_to_int64(row[30]); mr->RecycleCount = str_to_int64(row[31]); bstrncpy(mr->cInitialWrite, row[32]!=NULL?row[32]:"", sizeof(mr->cInitialWrite)); mr->InitialWrite = (time_t)str_to_utime(mr->cInitialWrite); mr->ScratchPoolId = str_to_int64(row[33]); mr->RecyclePoolId = str_to_int64(row[34]); mr->VolReadTime = str_to_int64(row[35]); mr->VolWriteTime = str_to_int64(row[36]); mr->ActionOnPurge = str_to_int64(row[37]); sql_free_result(); bdb_unlock(); Dmsg1(050, "Rtn numrows=%d\n", numrows); return numrows; }
/* * If full_list is set, we list vertically, otherwise, we * list on one line horizontally. * Return number of rows */ int list_result(JCR *jcr, B_DB *mdb, DB_LIST_HANDLER *send, void *ctx, e_list_type type) { SQL_FIELD *field; SQL_ROW row; int i, col_len, max_len = 0; int num_fields; char buf[2000], ewc[30]; Dmsg0(800, "list_result starts\n"); if (sql_num_rows(mdb) == 0) { send(ctx, _("No results to list.\n")); return sql_num_rows(mdb); } num_fields = sql_num_fields(mdb); switch (type) { case NF_LIST: case RAW_LIST: /* * No need to calculate things like column widths for * unformated or raw output. */ break; case HORZ_LIST: case VERT_LIST: Dmsg1(800, "list_result starts looking at %d fields\n", num_fields); /* * Determine column display widths */ sql_field_seek(mdb, 0); for (i = 0; i < num_fields; i++) { Dmsg1(800, "list_result processing field %d\n", i); field = sql_fetch_field(mdb); if (!field) { break; } col_len = cstrlen(field->name); if (type == VERT_LIST) { if (col_len > max_len) { max_len = col_len; } } else { if (sql_field_is_numeric(mdb, field->type) && (int)field->max_length > 0) { /* fixup for commas */ field->max_length += (field->max_length - 1) / 3; } if (col_len < (int)field->max_length) { col_len = field->max_length; } if (col_len < 4 && !sql_field_is_not_null(mdb, field->flags)) { col_len = 4; /* 4 = length of the word "NULL" */ } field->max_length = col_len; /* reset column info */ } } break; } Dmsg0(800, "list_result finished first loop\n"); switch (type) { case NF_LIST: case RAW_LIST: Dmsg1(800, "list_result starts second loop looking at %d fields\n", num_fields); while ((row = sql_fetch_row(mdb)) != NULL) { sql_field_seek(mdb, 0); for (i = 0; i < num_fields; i++) { field = sql_fetch_field(mdb); if (!field) { break; } if (row[i] == NULL) { bsnprintf(buf, sizeof(buf), " %s", "NULL"); } else { bsnprintf(buf, sizeof(buf), " %s", row[i]); } send(ctx, buf); } if (type != RAW_LIST) { send(ctx, "\n"); } } break; case HORZ_LIST: Dmsg1(800, "list_result starts second loop looking at %d fields\n", num_fields); list_dashes(mdb, send, ctx); send(ctx, "|"); sql_field_seek(mdb, 0); for (i = 0; i < num_fields; i++) { Dmsg1(800, "list_result looking at field %d\n", i); field = sql_fetch_field(mdb); if (!field) { break; } max_len = max_length(field->max_length); bsnprintf(buf, sizeof(buf), " %-*s |", max_len, field->name); send(ctx, buf); } send(ctx, "\n"); list_dashes(mdb, send, ctx); Dmsg1(800, "list_result starts third loop looking at %d fields\n", num_fields); while ((row = sql_fetch_row(mdb)) != NULL) { sql_field_seek(mdb, 0); send(ctx, "|"); for (i = 0; i < num_fields; i++) { field = sql_fetch_field(mdb); if (!field) { break; } max_len = max_length(field->max_length); if (row[i] == NULL) { bsnprintf(buf, sizeof(buf), " %-*s |", max_len, "NULL"); } else if (sql_field_is_numeric(mdb, field->type) && !jcr->gui && is_an_integer(row[i])) { bsnprintf(buf, sizeof(buf), " %*s |", max_len, add_commas(row[i], ewc)); } else { bsnprintf(buf, sizeof(buf), " %-*s |", max_len, row[i]); } send(ctx, buf); } send(ctx, "\n"); } list_dashes(mdb, send, ctx); break; case VERT_LIST: Dmsg1(800, "list_result starts vertical list at %d fields\n", num_fields); while ((row = sql_fetch_row(mdb)) != NULL) { sql_field_seek(mdb, 0); for (i = 0; i < num_fields; i++) { field = sql_fetch_field(mdb); if (!field) { break; } if (row[i] == NULL) { bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, "NULL"); } else if (sql_field_is_numeric(mdb, field->type) && !jcr->gui && is_an_integer(row[i])) { bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, add_commas(row[i], ewc)); } else { bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, row[i]); } send(ctx, buf); } send(ctx, "\n"); } break; } return sql_num_rows(mdb); }
/************************************************************************* * * Function: sql_affected_rows * * Purpose: Return the number of rows affected by the query (update, * or insert) * *************************************************************************/ static int sql_affected_rows(rlm_sql_handle_t *handle, rlm_sql_config_t *config) { return sql_num_rows(handle, config); }