here i start with GtkAda but i met a problem that i don't understand. I give you a summary of the code.
file.ads
With Gtk.Window; Use Gtk.Window;
With Gtk.Table; Use Gtk.Table;
With Gtk.Widget; use Gtk.Widget;
With Gtk.Alignment; Use Gtk.Alignment;
Package File is
Type Align is array ( Positive range <> ) of Gtk_Alignment;
Type T_Test_Record is tagged record
Conteneur : Gtk_Table;
Win : Gtk_Window;
Button1 : Gtk_Button;
Button2 : Gtk_Button;
end record;
Type T_Test is access all T_Test_Record;
Align_Elements : Align(1..2);
Procedure Initialize_Window ( Window : out T_Test_Record ) ;
-- Initialize the Window of Gtk_Window type.
Procedure Initialize_Table ( Table : out T_Test_Record );
-- Initialze the Table of Gtk_Table type.
Procedure Initialize_Buttons ( Button : T_Test );
-- Initialize the Button1 and button2 of Gtk_Button type.
Procedure Show_Window ( Window : out T_Test_Record );
-- Display the Window with the method Gtk.Widgdet.Show_All
Private
Procedure Exit_Window (Window : access Gtk_Widget_Record'Class);
-- Callback to Close the Window.
end file;
File.adb
With Gtk.Main; Use Gtk.Main;
Package body File is
Procedure Initialize_Window ( Window : out T_Test_Record ) is
begin
Gtk_New (Window.Win);
Window.Win.Set_Default_Size (Width => 600,
Height => 400);
P.Connect (Window.Win,
Name => Signal_Destroy,
Marsh => P.To_Marshaller (Exit_Window'Access),
After => False);
end Initialize_Window;
Procedure Initialize_Buttons ( Button : T_Test ) is
Begin
Gtk_New (Button.Button1,Label => "Bouton1");
Gtk_New (Button.Button2,Label => "Bouton2");
For i in Align_Elements'range loop
Case i is
When 1 => Gtk_New (Align_Elements(i),
Xalign => 0.0,
Yalign => 0.0,
Xscale => 0.0,
Yscale => 0.0);
Align_Elements(i).Add (Button.Button1);
When 2 => Gtk_new (Align_Elements(i),
Xalign => 0.5,
Yalign => 0.0,
Xscale => 0.0,
Yscale => 0.0);
Align_Elements(i).Add (Button.Button2);
end case;
end loop;
Test2.P.Connect (Widget => Button.Button1,
Name => Signal_Clicked,
Marsh => P.To_Marshaller
(Callback_Bouton1'Access),
After => False);
end Initialize_Buttons;
Procedure Initialize_Table ( Table : out T_Test_Record ) is
Window : T_Test;
begin
Window := New T_Test_Record;
Initialize_Window (Window => Table);
Initialize_Buttons (Button => Window);
Gtk_New (Table.Conteneur,
Rows => 0,
Columns => 0,
Homogeneous => False);
For i in Align_Elements'range loop
Table.Conteneur.Add (Align_Elements(i));
end loop;
Table.Win.Add (Table.Conteneur);
end Initialize_Table;
Procedure Show_Window (Window : out T_Test_Record ) is
begin
Initialize_Table (Table => Window);
Window.Win.Show_All;
end Show_Window;
Procedure Exit_Window ( Window : access Gtk_Widget_Record'Class)
is
begin
Main_Quit;
end Exit_Window;
end File;
file2.ads
With file; Use file;
With Gtk.Radio_Button; Use Gtk.Radio_Button;
With Gtk.Handlers;
Package file2 is
Package P is new Gtk.Handlers.Callback (Gtk_Widget_Record);
Use P;
Type Continent is (Europa, America, Africa, Asia);
Type Payment_Mode ( Choose : Continent := America ) is record
bank_Transfer : Gtk_Radio_Button;
Case Choose is
When Europa | America | Asia =>
By_Check : Gtk_Radio_Button;
By_Card : Gtk_Radio_Button;
When Africa => null;
end case;
end record;
Type Test_Record Is new T_Test_Record with record
Method : Payment_Mode;
Amount : Integer;
end record;
Type Test is access all Test_Record'class;
Procedure Saisir_Montant ( Saisie : out Test_Record );
Procedure Choose_Payment_Mode ( Mode : Test );
Procedure Callback_Bouton1 (Emet : access Gtk_Widget_Record'Class);
end file2;
File2.adb
With Ada.Integer_Text_IO; Use Ada.Integer_Text_IO;
Package body file2 is
Procedure Saisir_Montant (Saisie : out Test_Record ) is
begin
Put_Line ("Entry Amount");
Get (Saisie.Amount); Skip_Line;
end Saisir_Montant;
Procedure Choose_Payment_Mode (Mode : Test ) is
Local_Variable : Test_Record;
begin
Saisir_Montant (Local_Variable);
Put_Line ("What's your payment mode ?");
Gtk_New (Mode.Method.bank_transfer,
Group => null,
Label => "Wire");
Gtk_New (Mode.Method.By_Check,
Group => null,
Label => "Check");
Gtk_New (Mode.Method.By_Card,
Group => null,
Label => "Card");
end Choose_Payment_Mode;
Procedure Callback_Bouton1 (Emet : access Gtk_Widget_Record'Class) is
Local_Variable : Test;
begin
Local_Variable := New Test_Record;
Choose_Payment_Mode (Mode => Local_Variable);
Initialize_Table (Table => Local_Variable.all);
Local_Variable.Conteneur.Add (Local_Variable.Method.bank_transfer);
Local_Variable.Conteneur.Add (Local_Variable.Method.By_Check);
Local_Variable.Conteneur.Add (Local_Variable.Method.By_Card);
Local_Variable.Conteneur.Show_All;
end Callback_Bouton1;
end File2;
Main_Program.Adb
With file; Use file;
Procedure Main_Program is
Test : T_Test_Record;
begin
Init;
Show_Window (Window => Test);
Main;
end Main_Program;
the program compile and execute well but don't show me my Gtk_Radio_Button (in package File2.Choose_Payment_Mode) called when click on button1. the callback works very well but my Gtk_Radio_Button don't Show. yet i don't see any error.
Related
Hi I try to create Oracle procedure which take backup from user schema (POSData) and place it in directory called "Backups", POSData grant read, write on directory "Backups" using this code from system user.
DECLARE
h2 NUMBER;
BEGIN
h2 := DBMS_DATAPUMP.OPEN('EXPORT', 'SCHEMA');
DBMS_DATAPUMP.ADD_FILE(h2,'POSData.dmp','Backups');
DBMS_DATAPUMP.METADATA_FILTER(h2,'SCHEMA_EXP','IN (''POSData'')');
DBMS_DATAPUMP.START_JOB(h2);
dbms_datapump.detach(h2);
END;
but I always get this error
Error starting at line : 1 in command -
DECLARE
h2 NUMBER;
BEGIN
h2 := DBMS_DATAPUMP.OPEN('EXPORT', 'SCHEMA');
DBMS_DATAPUMP.ADD_FILE(h2,'POSData.dmp','Backups');
DBMS_DATAPUMP.METADATA_FILTER(h2,'SCHEMA_EXP','IN (''POSData'')');
DBMS_DATAPUMP.START_JOB(h2);
dbms_datapump.detach(h2);
END;
Error report -
ORA-39001: invalid argument value
ORA-06512: at "SYS.DBMS_SYS_ERROR", line 79
ORA-06512: at "SYS.DBMS_DATAPUMP", line 3507
ORA-06512: at "SYS.DBMS_DATAPUMP", line 3756
ORA-06512: at line 5
39001. 00000 - "invalid argument value"
*Cause: The user specified API parameters were of the wrong type or
value range. Subsequent messages supplied by
DBMS_DATAPUMP.GET_STATUS will further describe the error.
*Action: Correct the bad argument and retry the API.
help please?
DBMS_DATAPUMP has some really good error messages, but you have to dig in to get them. In the example below, I added a nested procedure output_expdp_error to dump the detailed message. You should of course modify this to do appropriate logging for your environment:
DECLARE
h1 NUMBER;
l_filename VARCHAR2( 100 ) := 'deleteme.dmp';
l_directory VARCHAR2( 100 ) := 'CIFS_DIR';
PROCEDURE output_expdpd_error( p_handle IN NUMBER ) AS
-- *******************************************************************
-- Output EXPDP Error
-- Purpose:
-- Send detailed EXPDP error to DBMS_OUTPUT
-- Modified:
-- 2020.03.02 - BFL Created
-- Notes:
-- Borrowed from: https://docs.oracle.com/database/121/SUTIL/GUID-5AAC848B-5A2B-4FD1-97ED-D3A048263118.htm#SUTIL977
-- *******************************************************************
l_status ku$_status; --ku$_jobstatus;
l_logentry ku$_logentry;
l_job_state VARCHAR2( 30 );
l_ind NUMBER;
l_pos NUMBER;
l_length NUMBER;
l_linesize CONSTANT NUMBER := 1000;
l_message VARCHAR2( 1000 );
BEGIN
-- Original had "if sqlcode = dbms_datapump.success_with_info_num" but this
-- hides some errors. Just always process the handle.
DBMS_OUTPUT.put_line( 'Data Pump job started with info available:' );
DBMS_DATAPUMP.get_status( p_handle
, DBMS_DATAPUMP.ku$_status_job_error
, 0
, l_job_state
, l_status );
IF (BITAND( l_status.mask, DBMS_DATAPUMP.ku$_status_job_error ) != 0)
THEN
l_logentry := l_status.error;
IF l_logentry IS NOT NULL
THEN
l_ind := l_logentry.FIRST;
WHILE l_ind IS NOT NULL
LOOP
l_pos := 1;
l_length := LENGTH( l_logentry( l_ind ).logtext );
l_length := CASE WHEN l_linesize < l_length THEN l_linesize ELSE l_length END;
WHILE l_length > 0
LOOP
l_message :=
SUBSTR( l_logentry( l_ind ).logtext
, l_pos
, l_length );
DBMS_OUTPUT.put_line( l_message );
l_pos := l_pos + l_linesize;
l_length := LENGTH( l_logentry( l_ind ).logtext ) + 1 - l_pos;
END LOOP;
l_ind := l_logentry.NEXT( l_ind );
END LOOP;
END IF;
END IF;
END;
BEGIN
DBMS_OUTPUT.put_line( 'open' );
h1 := DBMS_DATAPUMP.open( 'EXPORT', 'SCHEMA' );
DBMS_OUTPUT.put_line( 'add_file' );
DBMS_DATAPUMP.add_file( handle => h1
, filename => l_filename
, directory => l_directory
, filetype => DBMS_DATAPUMP.ku$_file_type_dump_file
, reusefile => 1 );
DBMS_OUTPUT.put_line( 'hr filter' );
DBMS_DATAPUMP.metadata_filter( h1
, 'SCHEMA_EXPR'
, 'IN (''BOGUS'')' );
DBMS_OUTPUT.put_line( 'BOGUS filter' );
DBMS_DATAPUMP.metadata_filter( h1
, 'SCHEMA_EXPR'
, 'IN (''BOGUS'')' );
DBMS_OUTPUT.put_line( 'start_job' );
DBMS_DATAPUMP.start_job( h1 );
DBMS_DATAPUMP.detach( h1 );
EXCEPTION
WHEN OTHERS
THEN
DECLARE
l_message VARCHAR2( 1000 );
BEGIN
output_expdpd_error( p_handle => h1 );
DBMS_DATAPUMP.detach( h1 );
l_message :=
SUBSTR(
SQLERRM
|| UTL_TCP.crlf
|| DBMS_UTILITY.format_error_backtrace
|| UTL_TCP.crlf
|| UTL_TCP.crlf
, 1
, 1000 );
DBMS_OUTPUT.put_line( l_message );
raise_application_error( -20000, l_message );
END;
END;
When I ran this with the non-existent schema, I got the wonderfully specific error message:
ORA-39001: invalid argument value
ORA-39170: Schema expression IN ('BOGUS') does not correspond to any schemas.
ORA-39001: invalid argument value
ORA-06512: at "SYS.DBMS_SYS_ERROR", line 79
ORA-06512: at "SYS.DBMS_DATAPUMP", line 3507
ORA-06512: at "SYS.DBMS_DATAPUMP", line 4825
ORA-06512: at line 76
I found the solution for my problem and here the code
DECLARE
h1 number;
errorvarchar varchar2(100):= 'ERROR';
tryGetStatus number := 0;
begin
h1 := dbms_datapump.open (operation => 'EXPORT', job_mode => 'SCHEMA', job_name => 'EXPORT_JOB_SQLDEV_2344', version => 'COMPATIBLE');
tryGetStatus := 1;
dbms_datapump.set_parallel(handle => h1, degree => 1);
dbms_datapump.add_file(handle => h1, filename => 'EXPDAT.LOG', directory => 'BACKUPS', filetype => 3);
dbms_datapump.set_parameter(handle => h1, name => 'KEEP_MASTER', value => 0);
dbms_datapump.metadata_filter(handle => h1, name => 'SCHEMA_EXPR', value => 'IN(''POSDATA'')');
dbms_datapump.add_file(handle => h1, filename => 'POSData.DMP', directory => 'BACKUPS', filesize => '100M', filetype => 1, reusefile => 1);
dbms_datapump.set_parameter(handle => h1, name => 'INCLUDE_METADATA', value => 1);
dbms_datapump.set_parameter(handle => h1, name => 'DATA_ACCESS_METHOD', value => 'AUTOMATIC');
dbms_datapump.set_parameter(handle => h1, name => 'ESTIMATE', value => 'BLOCKS');
dbms_datapump.start_job(handle => h1, skip_current => 0, abort_step => 0);
dbms_datapump.detach(handle => h1);
errorvarchar := 'NO_ERROR';
EXCEPTION
WHEN OTHERS THEN
BEGIN
IF ((errorvarchar = 'ERROR')AND(tryGetStatus=1)) THEN
DBMS_DATAPUMP.DETACH(h1);
END IF;
EXCEPTION
WHEN OTHERS THEN
NULL;
END;
RAISE;
END;
How do you check if the queue table exist before flushing it.
I have used the below syntax to create queue table
CREATE type Message_typ as object (
subject VARCHAR2(30),
text VARCHAR2(80));
BEGIN
dbms_aqadm.CREATE_QUEUE_TABLE (
queue_table => 'XX'
,queue_payload_type => 'Message_typ'
);
END;
And the below code to purge the flush table:
declare
l_type dbms_aqadm.aq$_purge_options_t;
begin
l_type.block := true;
l_type.delivery_mode := dbms_aq.buffered;
dbms_aqadm.purge_queue_table(queue_table => 'XX',
purge_condition => '',
purge_options => l_type);
l_type.block := true;
l_type.delivery_mode := dbms_aq.persistent;
dbms_aqadm.purge_queue_table(queue_table => 'XX',
purge_condition => '',
purge_options => l_type);
end;
Please guide how to check if the queue table exists and if exists do a purge.
Thanks.
In Python it would look something like this:
class Stack:
def __init__(self):
self.items = []
def isEmpty(self):
return self.items == []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
return self.items[len(self.items)-1]
def size(self):
return len(self.items)
Which data structure do I use and how do I implement stack in Oracle PL/SQL?
You can achieve the object oriented kind of things by using OBJECT types.
Like a class in other programming languages, you can use OBJECT in PL/SQL for encapsulating data.
For example the stack definition: (lifted from ORACLE documentation link.... posted down below. You can find definition of below declaration in that link).
CREATE TYPE Stack AS OBJECT (
max_size INTEGER,
top INTEGER,
position IntArray,
MEMBER PROCEDURE initialize,
MEMBER FUNCTION full RETURN BOOLEAN,
MEMBER FUNCTION empty RETURN BOOLEAN,
MEMBER PROCEDURE push (n IN INTEGER),
MEMBER PROCEDURE pop (n OUT INTEGER)
);
https://docs.oracle.com/cd/A97630_01/appdev.920/a96624/13_elems32.htm
You can implement stacks in pl/sql using Associative array tables.
Consider the following example.
You can read more at the following locations:
Oracle Collections Documentation
Collections Tutorial
declare
type stack_type is table of binary_integer index by binary_integer;
---^ Use your data type here
stack stack_type;
procedure push( p_element in binary_integer ) as
-----^ Use your data type here
begin
stack( stack.count + 1 ) := p_element;
end push;
procedure pop as
begin
stack.delete( stack.count ) ;
end;
function find ( p_element in binary_integer )
-----^ Use your data type here
return boolean as
begin
for element in 1 .. stack.count loop
if stack( element ) = p_element then
return true;
end if;
end loop;
return false;
end;
function top
return binary_integer as
-------^ Use your data type here
begin
return stack( stack.count );
end;
begin
push( 123 );
push( 456 );
push( 678 );
push( 929 );
push( 104 );
for element in 1 .. stack.count loop
dbms_output.put_line( 'Element:' || element || ' Value: ' || stack( element ) );
end loop;
dbms_output.put_line( 'Find|Top:' || top() );
if find( 929 ) then
dbms_output.put_line( '929 Found' );
else
dbms_output.put_line( '929 Not found');
end if;
if find(321) then
dbms_output.put_line( '321 Found' );
else
dbms_output.put_line( '321 Not found');
end if;
while stack.count > 0 loop
dbms_output.put_line( 'Pop|Top:' || top() );
pop();
end loop;
end;
I was wondering if any of you could answer a quick question for me. I am currently working with records right now and in my program I need it to understand what the line of a file that i'm importing contains. My problem lies in the fact that I don't know how to "split" the line into actual variables. For example the line is
22134.09 Kia Bernice
How do I make the program know that the first part, 22134.09 is the variable price, Kia is the variable company and Bernice is the variable model, and then sort them all into a record?
Such as
type PriceCompModel is record
price : Float range 1.0..99999.99;
company : String (1..CompNameLength);
Model : String (1..ModelNameLength);
Thanks.
edited code
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Float_Text_IO; use Ada.Float_Text_IO;
procedure Testexercise is
type Inventory is Record
CarPrice : Float := 0.0;
CarType : String (1..40);
-- CarType will include both the model and company
end record;
InventoryItem : Inventory;
ImportedFile : File_Type;
FileName : String := "Cars.txt";
WordsFromFile : String(1..40);
LengthofWords : Integer ;
PriceofCar : Float := 0.0;
LoopCount : Integer := 1;
type Cars is array (1..12) of Inventory;
begin
Open(File => ImportedFile, Mode => In_File, Name => FileName);
--for I in 1..12 loop
while LoopCount /= 12 loop
Get(File => ImportedFile, Item => InventoryItem.CarPrice);
Get_Line(File => ImportedFile, Item => WordsFromFile, Last=> LengthofWords);
Put (Integer(InventoryItem.CarPrice),1);
Put (WordsFromFile(1..LengthofWords));
New_Line;
LoopCount := LoopCount + 1;
InventoryItem.CarType := WordsFromFile;
end loop;
close(ImportedFile);
end Testexercise;
So i tried doing this within the loop
for I in 1..12 loop
Cars := Inventory;
end loop;
This ended up working for me after i set
Car : Cars;
for I in 1..12 loop
Car(I) := Inventory;
end loop;
You have many factors to consider when defining the record to contain your information.
It will be useful to create a named subtype of float, or a named floating point type so that the I/O routines can check the input values for the price component.
Fields of type String must be constrained to a predefined size. This means that all "company" strings must be the same size, and all "model" strings must be the same size, although model strings may be a different length than company strings. If the names of companies and/or models may vary then you should consider using either bounded strings (Ada Language Reference Manual section A.4.4) or unbounded strings (Ada Language Reference Manual section A.4.5).
If the strings of the input file are fixed in size you can use Ada.Text_IO.Text_Streams (Ada Language Reference Manual section A.12.2) to read each field of the record. If the strings can be different sizes then you will need to read and parse each field manually using Ada.Text_IO.
-- Read record data from a file
with Ada.Text_Io; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Strings.Fixed; use Ada.Strings.Fixed;
procedure read_record is
type Prices is delta 0.01 digits 7 range 0.0..99999.99;
type Auto_Inventory is record
Price : Prices := 0.0;
Company : Unbounded_String := Null_Unbounded_String;
Model : Unbounded_String := Null_Unbounded_String;
end record;
package AI_IO is new Ada.Text_IO.Decimal_IO(Prices);
use AI_IO;
Inventory_Item : Auto_Inventory;
The_File : File_Type;
File_Name : String := "inventory.txt";
Inpt_Str : String(1..1024);
Length : Natural;
Start, Finis : Positive;
begin
Open(File => The_File,
Mode => In_File,
Name => File_Name);
Get(File => The_File,
Item => Inventory_Item.Price);
Get_Line(File => The_File,
Item => Inpt_Str,
Last => Length);
Close(The_File);
Start := Index_Non_Blank(Source => Inpt_Str(1..Length));
Finis := Start;
while Finis < Length and then Inpt_Str(Finis) /= ' ' loop
Finis := Finis + 1;
end loop;
Inventory_Item.Company := To_Unbounded_String(Inpt_Str(Start..Finis));
Start := Index_Non_Blank(Inpt_Str(Finis + 1..Length));
Inventory_Item.Model := To_Unbounded_String(Inpt_Str(Start..Length));
Put_Line("Price: " & Prices'Image(Inventory_Item.Price));
Put_Line("Company: " & To_String(Inventory_Item.Company));
Put_Line("Model: " & To_String(Inventory_Item.Model));
end read_record;
If you want to read a file containing many records you need to collect the information in some kind of container. The following example uses a Vector from the generic package Ada.Containers.Vectors.
-- Auto Inventory Package specification
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Vectors;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
package Auto_Inventory is
type Prices is delta 0.01 digits 7 range 0.0..99999.99;
type Automobile is tagged private;
procedure Print(Item : Automobile);
function Set return Automobile;
function Get_Price(Item : Automobile) return Prices;
function Get_Company(Item : Automobile) return String;
function Get_Model(Item : Automobile) return String;
type Inventory is tagged private;
procedure Read(Item : out Inventory; File : File_Type) with
Pre => Mode(File) = In_File;
procedure Write(Item : in Inventory; File : File_type) with
Pre => Mode(File) = Out_File;
procedure Print(Item : Inventory);
private
type Automobile is tagged record
Price : Prices := 0.0;
Company : Unbounded_String := Null_Unbounded_String;
Model : Unbounded_String := Null_Unbounded_String;
end record;
package Auto_Vect is new
Ada.Containers.Vectors(Index_Type => Positive,
Element_Type => Automobile);
use Auto_Vect;
type Inventory is tagged record
List : Vector;
end record;
end Auto_Inventory;
The body for this package is:
with Ada.Strings.Fixed; use Ada.Strings.Fixed;
package body Auto_Inventory is
package Prices_IO is new Ada.Text_IO.Decimal_IO(Prices);
use Prices_IO;
-----------
-- Print --
-----------
procedure Print (Item : Automobile) is
use Prices_Io;
begin
Put_Line("Price : " & Prices'Image(Item.Price));
Put_Line("Company: " & To_string(Item.Company));
Put_Line("Model : " & To_String(Item.Model));
New_Line;
end Print;
---------
-- Set --
---------
function Set return Automobile is
Temp : Automobile;
Inpt_Str : String(1..1024);
Length : Natural;
begin
Put("Enter the automobile price: ");
Get(Item => Temp.Price);
Put("Enter the automobile company: ");
Get_Line(Item => Inpt_Str, Last => Length);
Temp.Company := To_Unbounded_String(Inpt_Str(1..Length));
Put("Enter the automobile model: ");
Get_Line(Item => Inpt_Str, Last => Length);
Temp.Model := To_Unbounded_String(Inpt_Str(1..Length));
return Temp;
end Set;
---------------
-- Get_Price --
---------------
function Get_Price (Item : Automobile) return Prices is
begin
return Item.Price;
end Get_Price;
-----------------
-- Get_Company --
-----------------
function Get_Company (Item : Automobile) return String is
begin
return To_String(Item.Company);
end Get_Company;
---------------
-- Get_Model --
---------------
function Get_Model (Item : Automobile) return String is
begin
return To_String(Item.Model);
end Get_Model;
----------
-- Read --
----------
procedure Read (Item : out Inventory;
File : File_Type) is
Temp : Inventory;
Auto : Automobile;
Inpt_Str : String(1..1024);
Length : Natural;
Start, Finis : Positive;
begin
while not End_Of_File(File) loop
Get(File => File, Item => Auto.Price);
Get_Line(File => File, Item => Inpt_str, Last => Length);
Start := Index_Non_Blank(Inpt_Str(1..Length));
Finis := Start;
while Finis < Length and then Inpt_Str(Finis) /= ' ' loop
Finis := Finis + 1;
end loop;
Auto.Company := To_Unbounded_String(Inpt_Str(Start..Finis - 1));
Start := Index_Non_Blank(Inpt_Str(Finis..Length));
Auto.Model := To_Unbounded_String(Inpt_Str(Start..Length));
Temp.List.Append(Auto);
end loop;
Item := Temp;
end Read;
-----------
-- Write --
-----------
procedure Write (Item : in Inventory;
File : File_type) is
begin
for Element of Item.List loop
Put(File => File, Item => Prices'Image(Element.Price) &
" " & To_String(Element.Company) & " " &
To_String(Element.Model));
New_Line;
end loop;
end Write;
-----------
-- Print --
-----------
procedure Print (Item : Inventory) is
begin
for Element of Item.List loop
Element.Print;
end loop;
end Print;
end Auto_Inventory;
An example of a main procedure to exercise this package:
------------------------------------------------------------------
-- Read a file of many records --
------------------------------------------------------------------
with Auto_Inventory; use Auto_Inventory;
with Ada.Text_IO; use Ada.Text_IO;
procedure read_file is
The_Inventory : Inventory;
The_File : File_Type;
File_Name : String := "inventory.txt";
begin
Open(File => The_File,
Mode => In_File,
Name => File_Name);
The_Inventory.Read(The_File);
Close(The_File);
The_Inventory.Print;
end read_file;
An example input file for this program is:
22134.09 Kia Bernice
12201.15 Nissan Versa
22349.99 Chevrolet Cruse
It is not clear for me what language you are using .However the concept is to deal with each line from the file alone then process it with a function that do the token-zing or splitting depending on the language you use and save each token in a variable depending on how the function you are using will save the tokens
for example:
In java there is a class
StringTokenizer(String str, String delim)
StringTokenizer st = new StringTokenizer("this is a test", "$a; ");
while (st.hasMoreTokens()) {
System.out.println(st.nextToken());
}
delim in your case is space so use the format
StringTokenizer st = new StringTokenizer("this is a test");
or
String line = reader.readLine();
String[] tokens = line.split("\\s");
note that you need to save the line you read in a string so you can use those functions in java then access each token from the array
String price = tokens[1] and so on
for other languages please find the following resources:
In c https://www.tutorialspoint.com/c_standard_library/c_function_strtok.htm
In pyhton https://www.tutorialspoint.com/python/string_split.htm
I'm trying to create a queue and a callback that triggers when a message is queued, but I can't get the callback to trigger. What am I doing wrong?
I have a trigger that enqueues a message, and I can see it on the queue message table, and I can dequeue it by hand and process it, I just can't get the callback to fire on enqueue.
BEGIN
DBMS_AQADM.CREATE_QUEUE_TABLE (
queue_table => 'queue_message_table',
queue_payload_type => 'queue_message_type',
multiple_consumers => TRUE);
DBMS_AQADM.CREATE_QUEUE (
queue_name => 'message_queue',
queue_table => 'queue_message_table');
DBMS_AQADM.START_QUEUE (queue_name => 'message_queue');
END;
CREATE OR REPLACE PROCEDURE queue_callback(
context RAW, reginfo SYS.AQ$_REG_INFO, descr SYS.AQ$_DESCRIPTOR, payload RAW, payloadl NUMBER) AS
queue_options DBMS_AQ.DEQUEUE_OPTIONS_T;
message_properties DBMS_AQ.MESSAGE_PROPERTIES_T;
my_message queue_message_type;
ret varchar2(200);
message_id RAW(16);
BEGIN
DBMS_OUTPUT.PUT_LINE('Callback');
queue_options.msgid := descr.msg_id;
queue_options.consumer_name := descr.consumer_name;
DBMS_AQ.DEQUEUE(
queue_name => descr.queue_name,
dequeue_options => queue_options,
message_properties => message_properties,
payload => my_message,
msgid => message_id );
ret := handle_message(my_message);
commit;
END;
BEGIN
DBMS_AQADM.ADD_SUBSCRIBER (queue_name => 'message_queue',
subscriber => SYS.AQ$_AGENT('queue_subscriber', 'message_queue',NULL));
DBMS_AQ.REGISTER (
SYS.AQ$_REG_INFO_LIST(
SYS.AQ$_REG_INFO(
'MESSAGE_QUEUE:QUEUE_SUBSCRIBER',
DBMS_AQ.NAMESPACE_AQ,
'plsql://QUEUE_CALLBACK',
HEXTORAW('FF')
)
), 1
);
END;
At first glance, it appears you're neither starting the queue (dbms_aqadm.start_queue), neither are you enqueueing anything to it (dbms_aq.enqueue).
I'd recommend following this demo.
You need to be careful with the database version. some bugs has been reported about issues with Oracle Aq.
In particular I've followed this link to built my own sample, executing the demo in a Oracle 11gR2 enterprise database. I was abled to enqueue, dequeue, purge the queue but the listener created with Dbms_Aq.Register didn't work.
I ran the same example downloading a Oracle 11g R2 xe database and it worked.
The same example was runned in a Oracle 10gR2 instance and it works perfectly.
There are some things that you need to be careful on using aq:
use the appropriate parameters adding the subscriber
use the appropriate namespace registering the listener with Dbms_Aq.Register
use the multiple consumers flag declaring the queue table
use the appropriate permissions to packages and to handle the queues
use the qualified name of the queues in some cases if it didn't works.
'
First create the schema
connect / as sysdba
-- #?/rdbms/admin/dbmsaqad.sql --(install if you don't have aq installed yet)
-- create the user and permissions
create user aqadmin identified by aqadmin default tablespace users temporary tablespace temp;
GRANT create session TO aqadmin;
grant connect, resource to aqadmin;
GRANT aq_administrator_role TO aqadmin IDENTIFIED BY aqadmin;
GRANT execute ON dbms_aq TO aqadmin;
GRANT execute ON dbms_aqadm TO aqadmin;
Create the ddl objects
CREATE TABLE demo_queue_message_table
( message VARCHAR2(4000) );
Create the aq-objects
create or replace type demo_queue_payload_type as object(message varchar2(4000)) ;
/
begin
DBMS_AQADM.CREATE_QUEUE_TABLE (queue_table => 'demo_queue_table', queue_payload_type => 'demo_queue_payload_type',multiple_consumers => TRUE);
DBMS_AQADM.CREATE_QUEUE (queue_name => 'demo_queue', queue_table => 'demo_queue_table');
DBMS_AQADM.START_QUEUE('demo_queue');
end;
/
CREATE or replace PROCEDURE demo_queue_callback_procedure(
context RAW,
reginfo SYS.AQ$_REG_INFO,
descr SYS.AQ$_DESCRIPTOR,
payload RAW,
payloadl NUMBER
) AS
r_dequeue_options DBMS_AQ.DEQUEUE_OPTIONS_T;
r_message_properties DBMS_AQ.MESSAGE_PROPERTIES_T;
v_message_handle RAW(16);
o_payload demo_queue_payload_type;
BEGIN
r_dequeue_options.msgid := descr.msg_id;
r_dequeue_options.consumer_name := descr.consumer_name;
DBMS_AQ.DEQUEUE(
queue_name => descr.queue_name,
dequeue_options => r_dequeue_options,
message_properties => r_message_properties,
payload => o_payload,
msgid => v_message_handle
);
INSERT INTO demo_queue_message_table ( message )
VALUES ( 'Message [' || o_payload.message || '] ' ||
'dequeued at [' || TO_CHAR( SYSTIMESTAMP,
'DD-MON-YYYY HH24:MI:SS.FF3' ) || ']' );
COMMIT;
END;
/
BEGIN
DBMS_AQADM.ADD_SUBSCRIBER (
queue_name => 'demo_queue',
subscriber => SYS.AQ$_AGENT(
'demo_queue_subscriber',
NULL,
NULL )
);
DBMS_AQ.REGISTER (
SYS.AQ$_REG_INFO_LIST(
SYS.AQ$_REG_INFO(
'DEMO_QUEUE:DEMO_QUEUE_SUBSCRIBER',
DBMS_AQ.NAMESPACE_AQ,
'plsql://DEMO_QUEUE_CALLBACK_PROCEDURE',
HEXTORAW('FF')
)
),
1
);
END;
/
And finally test the queue
DECLARE
r_enqueue_options DBMS_AQ.ENQUEUE_OPTIONS_T;
r_message_properties DBMS_AQ.MESSAGE_PROPERTIES_T;
v_message_handle RAW(16);
o_payload demo_queue_payload_type;
BEGIN
o_payload := demo_queue_payload_type(
TO_CHAR(SYSTIMESTAMP, 'DD-MON-YYYY HH24:MI:SS.FF3' )
);
DBMS_AQ.ENQUEUE(
queue_name => 'demo_queue',
enqueue_options => r_enqueue_options,
message_properties => r_message_properties,
payload => o_payload,
msgid => v_message_handle
);
COMMIT;
END;
/