diff --git a/src/msgs/facilities2.sql b/src/msgs/facilities2.sql index e234c97ff4..4ebae7b317 100644 --- a/src/msgs/facilities2.sql +++ b/src/msgs/facilities2.sql @@ -28,7 +28,7 @@ set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUM ('2009-02-12 21:16:16', 'GSEC', 18, 101) ('2002-03-05 02:30:12', 'LICENSE', 19, 60) ('2002-03-05 02:31:54', 'DOS', 20, 74) -('2007-04-07 13:11:00', 'GSTAT', 21, 38) +('2009-06-22 05:57:59', 'GSTAT', 21, 46) ('2008-09-16 16:51:42', 'FBSVCMGR', 22, 51) ('2007-12-21 19:03:07', 'UTL', 23, 2) stop diff --git a/src/msgs/history2.sql b/src/msgs/history2.sql index 31e2bbc4ca..06f5f98164 100644 --- a/src/msgs/history2.sql +++ b/src/msgs/history2.sql @@ -1202,6 +1202,9 @@ Fetches = !f', NULL, NULL, 'c_pg'); (1197, 'asfernandes', '2009-04-21 11:18:00', 17, 38, ' = CHECK, DATABASE, DOMAIN, EXCEPTION, FILTER, FUNCTION, GENERATOR,', NULL, NULL, 'c_pg') (1198, 'asfernandes', '2009-04-21 11:19:00', 17, 64, ' GRANT, INDEX, PROCEDURE, ROLE, SQL DIALECT, SYSTEM, TABLE,', NULL, NULL, 'c_pg') (1199, 'asfernandes', '2009-04-21 11:20:00', 17, 102, ' TRIGGER, VERSION, USERS, VIEW', NULL, NULL, 'c_pg') +(1200, 'cvc', '2009-06-22 05:53:30', 21, 27, ' -s analyze system relations', NULL, NULL, 'c_pg') +(1201, 'cvc', '2009-06-22 05:54:50', 21, 24, ' -h analyze header page', NULL, NULL, 'c_pg') +(1202, 'cvc', '2009-06-22 05:56:20', 21, 35, ' -t tablename', NULL, NULL, 'c_pg') stop COMMIT WORK; diff --git a/src/msgs/messages2.sql b/src/msgs/messages2.sql index dbb4c73e8d..1c9aa449b6 100644 --- a/src/msgs/messages2.sql +++ b/src/msgs/messages2.sql @@ -3333,10 +3333,10 @@ Analyzing database pages ...', NULL, NULL); (NULL, 'main', 'dba.e', NULL, 21, 21, NULL, 'Available switches:', NULL, NULL); (NULL, 'main', 'dba.e', NULL, 21, 22, NULL, ' -a analyze data and index pages', NULL, NULL); (NULL, 'main', 'dba.e', NULL, 21, 23, NULL, ' -d analyze data pages', NULL, NULL); -(NULL, 'main', 'dba.e', NULL, 21, 24, NULL, ' -h analyze header page', NULL, NULL); +(NULL, 'main', 'dba.e', NULL, 21, 24, NULL, ' -h analyze header page ONLY', NULL, NULL); (NULL, 'main', 'dba.e', NULL, 21, 25, NULL, ' -i analyze index leaf pages', NULL, NULL); (NULL, 'main', 'dba.e', NULL, 21, 26, NULL, ' -l analyze log page', NULL, NULL); -(NULL, 'main', 'dba.e', NULL, 21, 27, NULL, ' -s analyze system relations', NULL, NULL); +(NULL, 'main', 'dba.e', NULL, 21, 27, NULL, ' -s analyze system relations in addition to user tables', NULL, NULL); (NULL, 'main', 'dba.e', NULL, 21, 28, NULL, ' -z display version number', NULL, NULL); ('gstat_open_err', 'db_open', 'dba.e', NULL, 21, 29, NULL, 'Can''t open database file @1', NULL, NULL); ('gstat_read_err', 'db_read', 'dba.e', NULL, 21, 30, NULL, 'Can''t read a database page', NULL, NULL); @@ -3344,11 +3344,19 @@ Analyzing database pages ...', NULL, NULL); ('gstat_username', NULL, 'dba.e', NULL, 21, 32, NULL, ' -u username', NULL, NULL); ('gstat_password', NULL, 'dba.e', NULL, 21, 33, NULL, ' -p password', NULL, NULL); (NULL, 'main', 'dba.e', NULL, 21, 34, NULL, ' -r analyze average record and version length', NULL, NULL); -(NULL, 'main', 'dba.e', NULL, 21, 35, NULL, ' -t tablename', NULL, NULL); +(NULL, 'main', 'dba.e', NULL, 21, 35, NULL, ' -t tablename (case sensitive)', NULL, NULL); -- Do not change the arguments of the previous GSTAT messages. -- Write the new GSTAT messages here. (NULL, 'main', 'dba.epp', NULL, 21, 36, NULL, ' -tr use trusted authentication', NULL, NULL); (NULL, 'main', 'dba.epp', NULL, 21, 37, NULL, ' -fetch fetch password from file', NULL, NULL); +(NULL, 'main', 'dba.epp', NULL, 21, 38, NULL, 'option -h is incompatible with options -a, -d, -i, -r, -s and -t', NULL, NULL) +(NULL, 'main', 'dba.epp', NULL, 21, 39, NULL, 'usage: gstat [options] or gstat [options]', NULL, NULL) +(NULL, 'main', 'dba.epp', NULL, 21, 40, NULL, 'database name was already specified', NULL, NULL) +(NULL, 'main', 'dba.epp', NULL, 21, 41, NULL, 'option -t needs a table name', NULL, NULL) +(NULL, 'main', 'dba.epp', NULL, 21, 42, NULL, 'option -t got a too long table name @1', NULL, NULL) +(NULL, 'main', 'dba.epp', NULL, 21, 43, NULL, 'option -t accepts several table names only if used after ', NULL, NULL) +(NULL, 'main', 'dba.epp', NULL, 21, 44, NULL, 'table "@1" not found', NULL, NULL) +(NULL, 'main', 'dba.epp', NULL, 21, 45, NULL, 'use gstat -? to get help', NULL, NULL) -- FBSVCMGR -- All messages use the new format. ('fbsvcmgr_bad_am', 'putAccessMode', 'fbsvcmgr.cpp', NULL, 22, 1, NULL, 'Wrong value for access mode', NULL, NULL); diff --git a/src/utilities/gstat/dba.epp b/src/utilities/gstat/dba.epp index 78af3e4d89..b21ee2947e 100644 --- a/src/utilities/gstat/dba.epp +++ b/src/utilities/gstat/dba.epp @@ -152,9 +152,11 @@ static void db_close(void* file_desc); #else static void db_close(int); #endif -static void print_distribution(const SCHAR*, const ULONG*); static void dba_error(USHORT, const SafeArg& arg = SafeArg()); static void dba_print(USHORT, const SafeArg& arg = SafeArg()); +static void print_distribution(const SCHAR*, const ULONG*); +static void print_help(); + #include "../jrd/db_alias.h" @@ -287,16 +289,6 @@ int gstat(Firebird::UtilSvc* uSvc) * of a database. * **************************************/ - SCHAR temp[1024]; - bool sw_system = false; - bool sw_data = false; - bool sw_index = false; - bool sw_version = false; - bool sw_header = false; - //bool sw_log = false; - bool sw_record = false; - bool sw_relation = false; - bool sw_nocreation = false; isc_db_handle db_handle = 0; TEXT pass_buff[128], user_buff[128], *password = pass_buff, *username = user_buff; @@ -325,6 +317,22 @@ int gstat(Firebird::UtilSvc* uSvc) tddba->dba_status = tddba->dba_status_vector; status_vector = tddba->dba_status; + if (argc == 1) // no parameters at all. + { + tddba->uSvc->setServiceStatus(GSTAT_MSG_FAC, 45, SafeArg()); + dba_error(45); // use gstat -? to get help' + } + + bool sw_system = false; + bool sw_data = false; + bool sw_index = false; + bool sw_version = false; + bool sw_header = false; + //bool sw_log = false; + bool sw_record = false; + bool sw_relation = false; + bool sw_nocreation = false; + const char* name = NULL; const TEXT* const* const end = argv + argc; @@ -334,6 +342,12 @@ int gstat(Firebird::UtilSvc* uSvc) const TEXT* str = *argv++; if (*str != '-') { + if (name) + { + tddba->uSvc->setServiceStatus(GSTAT_MSG_FAC, 40, SafeArg()); + dba_error(40); // database name was already specified + } + name = str; continue; } @@ -353,21 +367,19 @@ int gstat(Firebird::UtilSvc* uSvc) if (!c) break; } - //in_sw_tab->in_sw_state = true; switch (in_sw_tab->in_sw) { - case 0: + case IN_SW_DBA_0: dba_print(20, SafeArg() << (str + 1)); // msg 20: unknown switch "%s" - dba_print(21); // msg 21: Available switches: - for (in_sw_tab = dba_in_sw_table; in_sw_tab->in_sw; in_sw_tab++) - { - if (in_sw_tab->in_sw_msg) - dba_print(in_sw_tab->in_sw_msg); - } - tddba->uSvc->setServiceStatus(GSTAT_MSG_FAC, 1, SafeArg()); + print_help(); + tddba->uSvc->setServiceStatus(GSTAT_MSG_FAC, 1, SafeArg() << (str + 1)); dba_error(1); // msg 1: found unknown switch break; + case IN_SW_DBA_HELP: + print_help(); + dba_exit(FINI_OK, tddba); + break; case IN_SW_DBA_USERNAME: if (argv < end) fb_utils::copy_terminate(username, *argv++, sizeof(user_buff)); @@ -433,9 +445,14 @@ int gstat(Firebird::UtilSvc* uSvc) { if (strlen(*argv) > MAX_SQL_IDENTIFIER_LEN) { - argv++; - continue; + char tbname[MAX_SQL_IDENTIFIER_LEN + 5]; + fb_utils::copy_terminate(tbname, *argv, MAX_SQL_IDENTIFIER_SIZE); + memcpy(tbname + MAX_SQL_IDENTIFIER_LEN, "...\0", 4); + tddba->uSvc->setServiceStatus(GSTAT_MSG_FAC, 42, SafeArg() << tbname); + dba_error(42, SafeArg() << tbname); // option -t got a too long table name @1 + break; } + dba_rel* relation = (dba_rel*) alloc(sizeof(struct dba_rel)); strcpy(relation->rel_name, *argv++); fb_utils::exact_name(relation->rel_name); @@ -445,6 +462,11 @@ int gstat(Firebird::UtilSvc* uSvc) next = &(*next)->rel_next; } *next = relation; + + // CVC: If the db name wasn't given yet, only one table name can be specified + // after -t to avoid ambiguity. + if (!name) + break; } break; case IN_SW_DBA_NOCREATION: @@ -456,12 +478,24 @@ int gstat(Firebird::UtilSvc* uSvc) if (sw_version) dba_print(5, SafeArg() << GDS_VERSION); // msg 5: gstat version %s + if (sw_header && (sw_system || sw_data || sw_index || sw_record || sw_relation)) + { + tddba->uSvc->setServiceStatus(GSTAT_MSG_FAC, 38, SafeArg()); + dba_error(38); //option -h is incompatible with options -a, -d, -i, -r, -s and -t + } + if (!name) { tddba->uSvc->setServiceStatus(GSTAT_MSG_FAC, 2, SafeArg()); dba_error(2); // msg 2: please retry, giving a database name } + if (sw_relation && !tddba->relations) + { + tddba->uSvc->setServiceStatus(GSTAT_MSG_FAC, 41, SafeArg()); + dba_error(41); // option -t needs a table name. + } + if (!sw_data && !sw_index) sw_data = sw_index = true; @@ -494,6 +528,8 @@ int gstat(Firebird::UtilSvc* uSvc) } dba_fil* current = db_open(fileName.c_str(), fileName.length()); + + SCHAR temp[1024]; tddba->page_size = sizeof(temp); tddba->global_buffer = (pag*) temp; tddba->page_number = -1; @@ -632,6 +668,12 @@ int gstat(Firebird::UtilSvc* uSvc) if (!X.RDB$VIEW_BLR.NULL || !X.RDB$EXTERNAL_FILE.NULL) { continue; } + //rel_virtual, rel_global_temp_preserve, rel_global_temp_delete + if (!X.RDB$SYSTEM_FLAG.NULL && X.RDB$SYSTEM_FLAG == fb_sysflag_system && + X.RDB$RELATION_TYPE >= rel_virtual && X.RDB$RELATION_TYPE <= rel_global_temp_delete) + { + continue; + } dba_rel* relation; if (sw_relation) @@ -716,14 +758,32 @@ int gstat(Firebird::UtilSvc* uSvc) dba_exit(FINI_ERROR, tddba); END_ERROR + if (sw_relation) + { + for (const dba_rel* relation = tddba->relations; relation; relation = relation->rel_next) + { + if (relation->rel_id == -1) + { + tddba->uSvc->setServiceStatus(GSTAT_MSG_FAC, 44, SafeArg() << relation->rel_name); + dba_error(44, SafeArg() << relation->rel_name); + // msg 44: table "@1" not found + } + } + } + + dba_print(10); // msg 10: \nAnalyzing database pages ...\n for (dba_rel* relation = tddba->relations; relation; relation = relation->rel_next) { - if (relation->rel_id == -1) { + // This condition should never happen because relations not found cause an error before. + if (relation->rel_id == -1) + { + fb_assert(sw_relation && relation->rel_id >= 0); continue; } + if (sw_data) { analyze_data(relation, sw_record); } @@ -820,6 +880,7 @@ int gstat(Firebird::UtilSvc* uSvc) } // if there still exists a database handle, disconnect from the server + // This is isc_detach_database FINISH; uSvc->started(); @@ -1641,3 +1702,17 @@ static void print_distribution(const SCHAR* prefix, const ULONG* vector) prefix, n * 100 / BUCKETS, (n + 1) * 100 / BUCKETS - 1, vector[n]); } } + + +// Print the help explanation +static void print_help() +{ + dba_print(39); // msg 39: usage: gstat [options] or gstat [options] + dba_print(21); // msg 21: Available switches: + for (const in_sw_tab_t* in_sw_tab = dba_in_sw_table; in_sw_tab->in_sw; in_sw_tab++) + { + if (in_sw_tab->in_sw_msg) + dba_print(in_sw_tab->in_sw_msg); + } + dba_print(43); // option -t accepts... +} diff --git a/src/utilities/gstat/dbaswi.h b/src/utilities/gstat/dbaswi.h index 628704a765..eea6f130dc 100644 --- a/src/utilities/gstat/dbaswi.h +++ b/src/utilities/gstat/dbaswi.h @@ -50,29 +50,31 @@ const int IN_SW_DBA_TRUSTEDROLE = 14; // use predefined trusted role const int IN_SW_DBA_TRUSTEDAUTH = 15; // trusted user name #endif const int IN_SW_DBA_FETCH_PASS = 16; // fetch password from file +const int IN_SW_DBA_HELP = 17; // show help -const static struct in_sw_tab_t dba_in_sw_table [] = +const static struct in_sw_tab_t dba_in_sw_table[] = { - {IN_SW_DBA_DATAIDX, 0, "ALL", 0,0,0, false, 22, 0, NULL}, // msg 22: -a analyze data and index pages + {IN_SW_DBA_DATAIDX, 0, "ALL", 0,0,0, false, 22, 0, NULL}, // msg 22: -a analyze data and index pages {IN_SW_DBA_DATA, isc_spb_sts_data_pages, "DATA", 0,0,0, false, 23, 0, NULL}, // msg 23: -d analyze data pages {IN_SW_DBA_HEADER, isc_spb_sts_hdr_pages, "HEADER", 0,0,0, false, 24, 0, NULL}, // msg 24: -h analyze header page {IN_SW_DBA_INDEX, isc_spb_sts_idx_pages, "INDEX", 0,0,0, false, 25, 0, NULL}, // msg 25: -i analyze index leaf pages -// {IN_SW_DBA_LOG, isc_spb_sts_db_log, "LOG", 0,0,0, false, 26, 0, NULL}, msg 26: -l analyze log page +// {IN_SW_DBA_LOG, isc_spb_sts_db_log, "LOG", 0,0,0, false, 26, 0, NULL}, // msg 26: -l analyze log page {IN_SW_DBA_SYSTEM, isc_spb_sts_sys_relations, "SYSTEM", 0,0,0, false, 27, 0, NULL}, // msg 27: -s analyze system relations - {IN_SW_DBA_USERNAME, 0, "USERNAME", 0,0,0, false, 32, 0, NULL}, // msg 32: -u username - {IN_SW_DBA_PASSWORD, 0, "PASSWORD", 0,0,0, false, 33, 0, NULL}, // msg 33: -p password - {IN_SW_DBA_FETCH_PASS, 0, "FETCH_PASSWORD", 0,0,0, false, 37, 0, NULL}, // msg 37: -fetch fetch password from file - {IN_SW_DBA_RECORD, isc_spb_sts_record_versions, "RECORD", 0,0,0, false, 34, 0, NULL}, // msg 34: -r analyze average record and version length - {IN_SW_DBA_RELATION, isc_spb_sts_table, "TABLE", 0,0,0, false, 35, 0, NULL}, // msg 35: -t tablename - {IN_SW_DBA_VERSION, 0, "Z", 0,0,0, false, 28, 0, NULL}, // msg 28: -z display version number + {IN_SW_DBA_USERNAME, 0, "USERNAME", 0,0,0, false, 32, 0, NULL}, // msg 32: -u username + {IN_SW_DBA_PASSWORD, 0, "PASSWORD", 0,0,0, false, 33, 0, NULL}, // msg 33: -p password + {IN_SW_DBA_FETCH_PASS, 0, "FETCH_PASSWORD", 0,0,0, false, 37, 0, NULL}, // msg 37: -fetch fetch password from file + {IN_SW_DBA_RECORD, isc_spb_sts_record_versions,"RECORD", 0,0,0, false, 34, 0, NULL}, // msg 34: -r analyze average record and version length + {IN_SW_DBA_RELATION, isc_spb_sts_table, "TABLE", 0,0,0, false, 35, 0, NULL}, // msg 35: -t tablename + {IN_SW_DBA_VERSION, 0, "Z", 0,0,0, false, 28, 0, NULL}, // msg 28: -z display version number // special switch to avoid including creation date, only for tests (no message) {IN_SW_DBA_NOCREATION, isc_spb_sts_nocreation, "NOCREATION", 0,0,0, false, 0, 0, NULL}, // msg (ignored) -n suppress creation date - {IN_SW_DBA_TRUSTEDUSER, 0, TRUSTED_USER_SWITCH, 0,0,0, false, 0, 0, NULL}, // msg 0 - ignored - {IN_SW_DBA_TRUSTEDROLE, 0, TRUSTED_ROLE_SWITCH, 0,0,0, false, 0, 0, NULL}, // msg 0 - ignored + {IN_SW_DBA_TRUSTEDUSER, 0, TRUSTED_USER_SWITCH, 0,0,0, false, 0, 0, NULL}, // msg 0 - ignored + {IN_SW_DBA_TRUSTEDROLE, 0, TRUSTED_ROLE_SWITCH, 0,0,0, false, 0, 0, NULL}, // msg 0 - ignored #ifdef TRUSTED_AUTH - {IN_SW_DBA_TRUSTEDAUTH, 0, "TRUSTED", 0,0,0, false, 36, 0, NULL}, // msg 36: -tr use trusted authentication + {IN_SW_DBA_TRUSTEDAUTH, 0, "TRUSTED", 0,0,0, false, 36, 0, NULL}, // msg 36: -tr use trusted authentication #endif - {IN_SW_DBA_0, 0, NULL, 0,0,0, false, 0, 0, NULL} // End of List + {IN_SW_DBA_HELP, 0, "?", 0,0,0, false, 0, 0, NULL}, // Help + {IN_SW_DBA_0, 0, NULL, 0,0,0, false, 0, 0, NULL} // End of List }; #endif // DBA_DBASWI_H