_Using Locators to Manipulate Large Objects_ by Gary Bist Listing One // A program to get an opinion from a large object text file - Gary Bist #include #include #include EXEC SQL INCLUDE SQLCA; class Any_Opinion_Any_Time { public: Any_Opinion_Any_Time(); // Constructor // Public member functions void Connect_to_Database(); // Connects app to database void Provide_Opinion_File(); // File for opinion wanted void Get_Name(); // Requests columnist's name void Get_Subject(); // Gets subject for opinion void Create_All_Opinions_Loc(); // Locator for all opinions void Isolate_Opinion_Wanted(); // Isolates opinion wanted void Put_Opinion_Wanted_to_File(); // Outputs opinion to file void Free_Locators(); // Frees memory void Disconnect_from_Database(); // Disconnects app void Tell_Where_to_Find_It(); // Points to file with opinion ~Any_Opinion_Any_Time(); // Destructor private: // Private data members EXEC SQL BEGIN DECLARE SECTION; char columnist_name[25]; // Stores columnist's name char subject[25]; // Stores subject for opinion SQL TYPE IS CLOB_FILE opinion_file; // Stores the opinion SQL TYPE IS CLOB_LOCATOR all_opinions_locator; // All opinions SQL TYPE IS CLOB_LOCATOR starting_with_subject_locator; SQL TYPE IS CLOB( 5 K ) opinion_wanted_buffer; // Buffer long opinion_wanted_position; // Position long end_of_opinion_wanted; // Position EXEC SQL END DECLARE SECTION; }; // ------- Any_Opinion_Any_Time constructor Any_Opinion_Any_Time::Any_Opinion_Any_Time() { } // ------- Member function to connect application to database void Any_Opinion_Any_Time::Connect_to_Database() { EXEC SQL CONNECT TO tasmania; if ( SQLCODE != 0 ) { cout << "\nConnect to database error: SQLCODE = " << SQLCODE; } } // ------- Member function to provide a file for the opinion wanted void Any_Opinion_Any_Time::Provide_Opinion_File() { strcpy( opinion_file.name, "e:\\locators\\opinion.txt" ); opinion_file.name_length = strlen( "e:\\locators\\opinion.txt" ); opinion_file.file_options = SQL_FILE_OVERWRITE; } // ------- Member function to get columnist's name from user void Any_Opinion_Any_Time::Get_Name() { cout << "Type the name of a columnist and press Enter\n"; cin >> columnist_name; } // ------- Member function to get subject for opinion void Any_Opinion_Any_Time::Get_Subject() { cout << "\nType the subject you wish an opinion about and press Enter\n"; cin >> subject; } // ------- Member function to create a locator for all columnist's opinions void Any_Opinion_Any_Time::Create_All_Opinions_Loc() { EXEC SQL SELECT opinion INTO :all_opinions_locator FROM opinionated_people WHERE columnist = :columnist_name; if ( SQLCODE != 0 ) { cout << "\nColumnist name not found error: SQLCODE = " << SQLCODE; } } // ------- Member function to isolate opinion wanted to buffer void Any_Opinion_Any_Time::Isolate_Opinion_Wanted() { // First find where opinion wanted starts using all_opinions_locator EXEC SQL VALUES( POSSTR( :all_opinions_locator, :subject ) ) INTO :opinion_wanted_position; if ( SQLCODE != 0 ) { cout << "\nStart of opinion wanted position error: SQLCODE = " << SQLCODE; } // Next put all opinions starting with opinion wanted in another locator EXEC SQL VALUES( SUBSTR( :all_opinions_locator, :opinion_wanted_position ) ) INTO :starting_with_subject_locator; if ( SQLCODE != 0 ) { cout << "\nOpinions starting with subject locator error: SQLCODE = " << SQLCODE; } // Next find where opinion wanted ends using starting_with_subject_locator EXEC SQL VALUES( POSSTR( :starting_with_subject_locator, 'End of my humble opinion' ) ) INTO :end_of_opinion_wanted; if ( SQLCODE != 0 ) { cout << "\nEnd of opinion wanted position error: SQLCODE = " << SQLCODE; } // Finally, output opinion wanted to a buffer EXEC SQL VALUES( SUBSTR( :starting_with_subject_locator, 1, :end_of_opinion_wanted - 1 ) ) INTO :opinion_wanted_buffer; if ( SQLCODE != 0 ) { cout << "\nWriting opinion to buffer error: SQLCODE = " << SQLCODE; } } // ------- Member function to write opinion wanted by user to a file void Any_Opinion_Any_Time::Put_Opinion_Wanted_to_File() { EXEC SQL VALUES( :opinion_wanted_buffer ) INTO :opinion_file; if ( SQLCODE != 0 ) { cout << "\nWriting opinion to file error: SQLCODE = " << SQLCODE; } } // ------- Member function to free memory of locator values void Any_Opinion_Any_Time::Free_Locators() { EXEC SQL FREE LOCATOR :all_opinions_locator; EXEC SQL FREE LOCATOR :starting_with_subject_locator; if ( SQLCODE != 0 ) { cout << "\nFreeing locators error: SQLCODE = " << SQLCODE; } } // ------- Member function to disconnect application from database void Any_Opinion_Any_Time::Disconnect_from_Database() { EXEC SQL COMMIT; // Commit any open transaction EXEC SQL DISCONNECT tasmania; if ( SQLCODE != 0 ) { cout << "\nDisconnect from database error: SQLCODE = " << SQLCODE; } } // ------- Member function to tell user where to find opinion void Any_Opinion_Any_Time::Tell_Where_to_Find_It() { cout << "\nThe opinion is in the opinion.txt file"; } // ------- Any_Opinion_Any_Time destructor Any_Opinion_Any_Time::~Any_Opinion_Any_Time() { } // ======= Program to get an opinion from a large object text file void main() { Any_Opinion_Any_Time PC_Mag_Columnists; // PC mag columnists' opinions PC_Mag_Columnists.Connect_to_Database(); // Connect app to database PC_Mag_Columnists.Provide_Opinion_File(); // File for opinion wanted PC_Mag_Columnists.Get_Name(); // Get name of columnist PC_Mag_Columnists.Get_Subject(); // Get subject for an opinion PC_Mag_Columnists.Create_All_Opinions_Loc(); // Locator for all opinions PC_Mag_Columnists.Isolate_Opinion_Wanted(); // Isolate only opinion wanted PC_Mag_Columnists.Put_Opinion_Wanted_to_File(); // Output opinion wanted PC_Mag_Columnists.Free_Locators(); // Free up memory PC_Mag_Columnists.Disconnect_from_Database(); // Disconnect app from db PC_Mag_Columnists.Tell_Where_to_Find_It(); // Tell where to find opinion } Listing Two SQL TYPE IS CLOB_LOCATOR all_opinions_locator; // All opinions SQL TYPE IS CLOB_LOCATOR starting_with_subject_locator; Listing Three // ------- Member function to create a locator for all columnist's opinions void Any_Opinion_Any_Time::Create_All_Opinions_Loc() { EXEC SQL SELECT opinion INTO :all_opinions_locator FROM opinionated_people WHERE columnist = :columnist_name; if ( SQLCODE != 0 ) { cout << "\nColumnist name not found error: SQLCODE = " << SQLCODE; } } Listing Four // ------- Member function to isolate opinion wanted to buffer void Any_Opinion_Any_Time::Isolate_Opinion_Wanted() { // First find where opinion wanted starts using all_opinions_locator EXEC SQL VALUES( POSSTR( :all_opinions_locator, :subject ) ) INTO :opinion_wanted_position; if ( SQLCODE != 0 ) { cout << "\nStart of opinion wanted position error: SQLCODE = " << SQLCODE; } // Next put all opinions starting with opinion wanted in another locator EXEC SQL VALUES( SUBSTR( :all_opinions_locator, :opinion_wanted_position ) ) INTO :starting_with_subject_locator; if ( SQLCODE != 0 ) { cout << "\nOpinions starting with subject locator error: SQLCODE = "<< SQLCODE; } // Next find where opinion wanted ends using starting_with_subject_locator EXEC SQL VALUES( POSSTR( :starting_with_subject_locator, 'End of my humble opinion' ) ) INTO :end_of_opinion_wanted; if ( SQLCODE != 0 ) { cout << "\nEnd of opinion wanted position error: SQLCODE = " << SQLCODE; } // Finally, output opinion wanted to a buffer EXEC SQL VALUES( SUBSTR( :starting_with_subject_locator, 1, :end_of_opinion_wanted - 1 ) ) INTO :opinion_wanted_buffer; if ( SQLCODE != 0 ) { cout << "\nWriting opinion to buffer error: SQLCODE = " << SQLCODE; } } Listing Five // ------- Member function to write opinion wanted by user to a file void Any_Opinion_Any_Time::Put_Opinion_Wanted_to_File() { EXEC SQL VALUES( :opinion_wanted_buffer ) INTO :opinion_file; if ( SQLCODE != 0 ) { cout << "\nWriting opinion to file error: SQLCODE = " << SQLCODE; } } Listing Six // ------- Member function to free memory of locator values void Any_Opinion_Any_Time::Free_Locators() { EXEC SQL FREE LOCATOR :all_opinions_locator; EXEC SQL FREE LOCATOR :starting_with_subject_locator; if ( SQLCODE != 0 ) { cout << "\nFreeing locators error: SQLCODE = " << SQLCODE; } }