PACKAGE BODY MISTAKE - plsql

-- PACKAGE SPECIFICATION OR HEADER
CREATE OR REPLACE PACKAGE pkg_Answer2 IS
FUNCTION grade_std(marks NUMBER) RETURN VARCHAR2;
END pkg_Answer2;
/
--PACKAGE BODY
CREATE OR REPLACE PACKAGE BODY pkg_Answer2 IS
--FUNCTION IMPLEMENTATION
FUNCTION grade_std(marks NUMBER) RETURN VARCHAR2 IS
BEGIN
IF marks>90 THEN
RETURN 'A';
ELSIF marks<=90 AND marks>80 THEN
RETURN 'B';
ELSIF marks<=80 AND marks>70 THEN
RETURN 'C';
ELSIF marks<=70 AND marks>60 THEN
RETURN 'D';
ELSIF marks<=60
RETURN 'F';
ELSE
RETURN 'I';
END IF;
END grade_std;
END pkg_Answer2;
PACKAGE BODY IS SHOWING ERROR :
Errors: PACKAGE BODY PKG_ANSWER2
Line/Col: 14/9 PLS-00103: Encountered the symbol "RETURN" when expecting one of the following:
& - + / at mod remainder rem then <an exponent (**)> and or
|| multiset
WHAT DOES IT MEAN BU ENCOUNTER SYMBOL RETURN THUS I AM UNABLE TO CREATE PACKAGE BODY

This is basic debugging, you should not have to ask this on stack overflow. All the information is right in your question.
To find out what is going on:
Open the created package in a tool like sql developer. That tool highlights the line where error occurs (Line 14, as shown in the error)
Check what is happening around line 14...
13 ELSIF marks<=60
14 RETURN 'F';
15 ELSE
the error states "Encountered the symbol "RETURN" when ". This means it cannot compile because a previous expression does not have correct syntax and the word "RETURN" doesn't make any sense there... so check the line before. That is line 13. It does not have the THEN keyword. There is your error.

Related

Ada constraint error: Discriminant check failed. What does this mean?

I've tried searching the docs and the code, but I'm unable to find what this is and therefore how to correct it.
Scenario:
I'm using the Ada SPARK vectors library and I have the following code:
package MyPackage
with SPARK_Mode => On
is
package New_Vectors is new Formal_Vectors (Index_Type => test, Element_Type => My_Element.Object);
type Object is private;
private
type Object is
record
Data : New_Vectors.Vector (Block_Vectors.Last_Count);
Identifier : Identifier_Range;
end record;
I get the error when the code calls:
function Make (Identifier : Identifier_Range) return Object is
begin
return (
Data => New_Vectors.Empty_Vector,
Identifier => Identifier);
end Make;
Pointing to Empty_Vector. The difficulty is that Empty_Vector defines the Capacity as 0 which appears to be leading to the problem. Now I'm not sure then how to deal with that as Capacity seems to be in the type definition (having looked in a-cofove.ads).
So basically I'm stuck as to how to resolve this; or quite how to spot this happening in future.
Your analysis is correct. The error occurs because you attempt to assign an empty vector (i.e. a vector with capacity 0) to a vector with capacity Block_Vectors.Last_Count (which appears to be non-zero).
You actually do not need to initialize the vector explicitly in order to use it. A default initialization (using <>, see, for example, here) suffices as shown in de example below.
However, in order to prove the absence of runtime errors, you do need to explicitly clear the vector using Clear. The Empty_Vector function can then be used to in assertions that check if a vector is empty or not as shown in the example below. The example can be shown to be free of runtime errors using gnatprove. For example by opening the prove settings via menu SPARK > Prove in GNAT Studio, selecting "Report checks moved" in the "General" section (top left) and then running the analysis by selecting "Execute" (bottom right).
main.adb
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Formal_Vectors;
procedure Main with SPARK_Mode is
package My_Vectors is new Ada.Containers.Formal_Vectors
(Index_Type => Natural,
Element_Type => Integer);
use My_Vectors;
type Object is record
Data : Vector (Capacity => 10); -- Max. # of elements: 10
Value : Integer;
end record;
-- Initialize with default value (i.e. <>), no explicit initialization needed.
Obj : Object :=
(Data => <>,
Value => 42);
begin
-- Clear the vector, required for the assertions to be proven.
Clear (Obj.Data);
-- Assert that the vector is not empty.
pragma Assert (Obj.Data = Empty_Vector);
-- Populate the vector with some elements.
Append (Obj.Data, 4);
Append (Obj.Data, 5);
Append (Obj.Data, 6);
-- Assert that the vector is populated.
pragma Assert (Obj.Data /= Empty_Vector);
-- Show the contents of Obj.Data.
Put_Line ("Contents of Obj.Data:");
for I in Natural range 0 .. Natural (Length (Obj.Data)) - 1 loop
Put_Line ("[" & I'Image & "]" & Element (Obj.Data, I)'Image);
end loop;
New_Line;
-- or, alternatively using an iterator ...
declare
I : Extended_Index := Iter_First (Obj.Data);
begin
while Iter_Has_Element (Obj.Data, I) loop
Put_Line ("[" & I'Image & "]" & Element (Obj.Data, I)'Image);
I := Iter_Next (Obj.Data, I);
end loop;
end;
New_Line;
-- Show the contents of Obj.Value.
Put_Line ("Contents of Obj.Value:");
Put_Line (Obj.Value'Image);
New_Line;
end Main;
output
Contents of Obj.Data:
[ 0] 4
[ 1] 5
[ 2] 6
[ 0] 4
[ 1] 5
[ 2] 6
Contents of Obj.Value:
42

Ada 95 Check if enter was pressed

I am new to Ada.
How can I check if enter was pressed?
The while loop should be able to check whether the input character is a white space or an enter key.
Furthermore, how can I check the user input type, like the type() or typeof() function in other languages?
FUNCTION ReadValue RETURN Unbounded_String IS
ValueChar : Character;
Result : Unbounded_String := To_Unbounded_String("NULL");
BEGIN
Get(ValueChar);
Skip_Line;
WHILE ValueChar /= ';'LOOP
Get(ValueChar);
IF IsValidNameInput(ValueChar) THEN
Result := Result & ValueChar;
ELSE
exit;
END IF;
END LOOP;
ValueIntegerFlag := CheckValue(Value);
RETURN Result;
END ReadValue;
Read the characters one-at-a-time without special ENTER handling using Get_Immediate instead of Get - ARM A.10.7(9).
You can do checks on the class of the character you’ve just read using Ada.Characters.Handling - ARM A.3.2 - something like
function Is_Valid_Name_Input (Ch : Character) return Boolean is
begin
return Ada.Characters.Handling.Is_Graphic (Ch)
and then not Ada.Characters.Handling.Is_Space (Ch);
end Is_Valid_Name_Input;
(probably not quite what you want, since it makes &*^$$^ a valid name!)
Ada.Characters.Handling.Is_Line_Terminator detects ENTER (on Unix; probably on Windows too).
You can check whether a string corresponds to an integer by trying the conversion and catching the exception when it fails:
function Check_Integer_Value (Str : Unbounded_String) return Boolean is
Dummy : Integer;
begin
Dummy := Integer'Value (To_String (Str));
return True;
exception
when Constraint_Error =>
return False;
end Check_Integer_Value;
With regard to ReadValue:
Don’t initialize Result - it starts off as the empty string (and you really don’t want to start with the string ”NULL”).
It skips the first character input.
What’s that Skip_Line for?
Try something like
function Read_Value return Unbounded_String is
Value_Char : Character;
Result : Unbounded_String;
begin
loop
Get_Immediate (Value_Char);
exit when Value_Char = ';';
if Is_Valid_Name_Input (Value_Char) then
Result := Result & Value_Char;
end if;
end loop;
return Result;
end Read_Value;

PL/SQL Return Cursor

I am trying to define the PL/SQL function
CREATE OR REPLACE FUNCTION B2BOWNER.F_SSC_Page_Map_Select(
p_page_id IN B2BOWNER.SSC_Page_Map.PAGE_ID_NBR%TYPE,
p_page_type IN B2BOWNER.SSC_Page_Map.PAGE_TYPE%TYPE,
p_page_dcpn IN B2BOWNER.SSC_Page_Map.PAGE_DCPN%TYPE)
RETURN MAP_REC
AS
CURSOR MAP_CURSOR IS
SELECT *
FROM B2BOWNER.SSC_PAGE_MAP
WHERE PAGE_ID_NBR = p_page_id AND PAGE_TYPE = p_page_type;
MAP_REC MAP_CURSOR%ROWTYPE;
TABLE_DOES_NOT_EXIST exception;
PRAGMA EXCEPTION_INIT(TABLE_DOES_NOT_EXIST, -942); -- ORA-00942
BEGIN
FOR MAP_REC IN MAP_CURSOR
LOOP
System.out.println("ID: " + MAP_REC.PAGE_ID_NBR + " " + "TYPE: " + MAP_REC.PAGE_TYPE + " " + "DCPN: " + MAP_REC.PAGE_DCPN);
END LOOP;
RETURN MAP_REC;
EXCEPTION
WHEN TABLE_DOES_NOT_EXIST THEN
RETURN -1;
WHEN DUP_VAL_ON_INDEX THEN
RETURN -2;
WHEN INVALID_NUMBER THEN
RETURN -3;
WHEN OTHERS THEN
RETURN -4;
END F_SSC_Page_Map_Select;
SHOW ERRORS PROCEDURE B2BOWNER.F_SSC_Page_Map_Select;
GRANT EXECUTE ON B2BOWNER.F_SSC_Page_Map_Select TO B2B_USER_DBROLE;
and receive the following error
Warning: compiled but with compilation errors
No errors.
Grant complete.
[Warning] ORA-24344: success with compilation error
6/12 PLS-00320: the declaration of the type of this expression is incomplete or malformed
PL/SQL: Compilation unit analysis terminated
(1: 0): Warning: compiled but with compilation errors
A few things. First, the MAP_REC declared in the declaration section is not the same as the MAP_REC used in the cursor FOR loop. This was certainly surprising to me when I first encountered it but it's something we all have to get used to. To do what you're trying to do you'll need to either use the OPEN, FETCH, and CLOSE method of working with a cursor, or else copy the values from the cursor FOR loop variable to the 'declared' variable.
Secondly, you can't return a MAP_REC from this function as MAP_REC is declared inside the function and thus isn't known to the compiler when it processes the function definition. Best to use the specific table ROWTYPE.
Third, later in the code you have RETURN -1, etc, which won't work as a cursor %ROWTYPE variable. I suggest that instead of trying to return 'magic number' values to indicate specific failures you should simply let the exceptions propagate to the caller, who can then handle the exceptions as needed. That's why we have exceptions - to prevent having different error handling schemes for every single subroutine out there.
And finally: this is PL/SQL - we don't System.out.println here. :-)
A possible way to rewrite your code would be:
CREATE OR REPLACE FUNCTION B2BOWNER.F_SSC_Page_Map_Select(
p_page_id IN B2BOWNER.SSC_Page_Map.PAGE_ID_NBR%TYPE,
p_page_type IN B2BOWNER.SSC_Page_Map.PAGE_TYPE%TYPE,
p_page_dcpn IN B2BOWNER.SSC_Page_Map.PAGE_DCPN%TYPE)
RETURN B2BOWNER.SSC_PAGE_MAP%ROWTYPE
AS
CURSOR MAP_CURSOR IS
SELECT *
FROM B2BOWNER.SSC_PAGE_MAP
WHERE PAGE_ID_NBR = p_page_id AND
PAGE_TYPE = p_page_type;
MAP_REC B2BOWNER.SSC_PAGE_MAP%ROWTYPE;
bCursor_open BOOLEAN := FALSE;
BEGIN
OPEN MAP_CURSOR;
bCursor_open := TRUE;
LOOP
FETCH MAP_CURSOR
INTO MAP_REC;
EXIT WHEN MAP_CURSOR%NOT_FOUND;
DBMS_OUTPUT.PUT_LINE('ID: ' || MAP_REC.PAGE_ID_NBR || ' ' || 'TYPE: ' ||
MAP_REC.PAGE_TYPE || ' ' || 'DCPN: ' || MAP_REC.PAGE_DCPN);
END LOOP;
CLOSE MAP_CURSOR;
bCursor_open := FALSE;
RETURN MAP_REC;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error in F_SSC_Page_Map_Select: ' || SQLCODE || ' ' ||
SQLERRM);
IF bCursor_open THEN
CLOSE MAP_CURSOR;
END IF;
RAISE;
END F_SSC_Page_Map_Select;
Best of luck.
Share and enjoy.

Function reading from standard input without any "in" parameters

Perhaps this is simple, and I am just missing some basic information, but I can't seem to find the answer anywhere.
I'm writing a Get_Word function for class, here is the relevant section of the spec file my prof wrote:
function Get_Word return Ustring;
-- return a space-separated word from standard input
procedure Fill_Word_List(Wl : in out Ustring_Vector);
-- read a text file from standard in and add all
-- space-separated words to the word list wl
I've written the Get_Word function, and am trying to test it out with this code:
with Ada.Text_IO; use Ada.Text_Io;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
procedure ngramtest is
Name : String(1..80);
File : File_Type;
Size : Natural;
function Get_Word return String is
-- I'm using a strings instead of Unbounded_Strings for testing purposes.
Word : String(1..80) := (others => ' ');
Char : Character;
File : File_Type;
Eol : Boolean;
I : Integer := 1;
begin
--this code below, when uncommented reveals whether or not the file is open.
--if Is_Open(File) then
-- Word := (1..80 => 'y');
--else
-- Word := (1..80 => 'n');
--end if;
loop
Look_Ahead(File, Char, Eol);
if Eol then
exit;
elsif Char = ' ' then
exit;
else
Get (File, Char);
Word(I) := Char;
I := I + 1;
end if;
end loop;
return Word(1..Word'Last);
end Get_Word;
begin
Put ("Enter filename: ");
Get_Line (Name, Size);
Open (File, Mode => In_File, Name => Name(1..Size));
Put (Get_Word);
Close(File);
end ngramtest;
It compiles, but at runtime I get an exception telling me that the file isn't open, and the commented out section returns "nnnnnn..." meaning that the file is not open within the function.
My question is how am I to read from standard input if i'm not allowed to use in parameters in my function? Without them the function won't be able to access files.
Essentially, how can I "Get_Word"?
Sorry if this is simple, but I'm completely lost.
You need to set your "File" variable to standard input:
File : File_Type := Ada.Text_IO.Standard_Input;

Writing a function inside a PL/SQL page

I want to create a function that do a specific task inside a oracle package, I tried with the bellow code, but it gives an error that I don't understand.
CREATE OR REPLACE
PACKAGE DINIDU_EXE_PACKAGE AS
FUNCTION EXE14
(SUP_ID_ SUPPLIER_PART_PROJECT_TAB.SUPPLIER_ID%TYPE,PAR_ID_ SUPPLIER_PART_PROJECT_TAB.PART_ID%TYPE,PRO_ID_ SUPPLIER_PART_PROJECT_TAB.PROJECT_ID%TYPE) RETURN NUMBER IS
QUNTITY_FOR_A_PROJECT_ NUMBER;
BEGIN
SELECT QUENTITY AS QUNTITY_FOR_A_PROJECT_ FROM SUPPLIER_PART_PROJECT_TAB WHERE SUPPLIER_ID=SUP_ID AND PART_ID=PAR_ID AND PRO_ID=PROJECT_ID;
IF QUNTITY_FOR_A_PROJECT_ >0 THEN
RETURN QUNTITY_FOR_A_PROJECT_;
ELSE
RETURN 0;
END IF;
END EXE14;
END;
Error(6,1): PLS-00103: Encountered the symbol "QUNTITY_FOR_A_PROJECT_" when expecting one of the following: language
Egor is right in his comment. You are putting a function in to the package specification while it has to be in package body instead.
Only a reference to a function or its signature - function name and arguments list - have to be in the package specification. The actual function has to be coded in the body.
CREATE OR REPLACE PACKAGE DINIDU_EXE_PACKAGE AS
FUNCTION EXE14
( SUP_ID_ SUPPLIER_PART_PROJECT_TAB.SUPPLIER_ID%TYPE
, PAR_ID_ SUPPLIER_PART_PROJECT_TAB.PART_ID%TYPE
,PRO_ID_ SUPPLIER_PART_PROJECT_TAB.PROJECT_ID%TYPE)
END;
/
CREATE OR REPLACE PACKAGE BODY DINIDU_EXE_PACKAGE AS
FUNCTION EXE14
( SUP_ID_ SUPPLIER_PART_PROJECT_TAB.SUPPLIER_ID%TYPE
, PAR_ID_ SUPPLIER_PART_PROJECT_TAB.PART_ID%TYPE
,PRO_ID_ SUPPLIER_PART_PROJECT_TAB.PROJECT_ID%TYPE)
RETURN NUMBER IS
QUNTITY_FOR_A_PROJECT_ NUMBER;
BEGIN
SELECT QUENTITY AS QUNTITY_FOR_A_PROJECT_ FROM SUPPLIER_PART_PROJECT_TAB WHERE SUPPLIER_ID=SUP_ID AND PART_ID=PAR_ID AND PRO_ID=PROJECT_ID;
IF QUNTITY_FOR_A_PROJECT_ >0 THEN
RETURN QUNTITY_FOR_A_PROJECT_;
ELSE
RETURN 0;
END IF;
END EXE14;
END;
/
EDIT: see Egor's comment and Rachcha's answer for the actual cause of the compilation error.
Your code first declares QUNTITY_FOR_A_PROJECT_ as a local variable, but then your SELECT statement uses the same identifier as a column alias (QUENTITY AS QUNTITY_FOR_A_PROJECT_). More importantly, you have not selected the result INTO anything.
I think you meant to do something like this:
SELECT QUENTITY INTO QUNTITY_FOR_A_PROJECT_ FROM SUPPLIER_PART_PROJECT_TAB ...
Another problem: your function accepts the following parameters: SUP_ID_, PAR_ID_ and PRO_ID_, but you don't use them in your function. I suspect the identifiers are not used correctly in the query, but I cannot know for sure because I don't know what the columns of your SUPPLIER_PART_PROJECT_TAB table are.

Resources