How to assign hexadecimal value to char variable in plsql - c

Below is the piece of code from C, here they are assigning the hexadecimal value to a char variable sKaigyoCode
char sKaigyoCode[512];
sKaigyoCode[0] = 0x0d;
sKaigyoCode[1] = 0x0a;
I am trying to do the same thing in PLSQL
sKaigyoCode CHAR(512);
sKaigyoCode[0] = 0x0d;
sKaigyoCode[1] = 0x0a;
Which shows compile time error
Error(46,18): PLS-00103: Encountered the symbol "[" when expecting one of the following: := . ( # % ;
Error(46,23): PLS-00103: Encountered the symbol "X0D" when expecting one of the following: * & = - + ; < / > at in is mod remainder not rem <> or != or ~= >= <= <> and or like like2 like4 likec between || multiset member submultiset The symbol "*" was substituted for "X0D" to continue.

As already mentioned in comments, char, varchar, varchar2, nvarchar2, etc. are not arrays. Also, usually there is no need to use hex values in PL/SQL. But if you need to put special characters into a string variable you can do this:
declare
sKaigyoCode CHAR(512);
begin
sKaigyoCode := chr(10) || chr(13);
end;
And opposite operation - to return a symbol code:
declare
a number;
begin
a := ascii(substr('Hello, world!', 1, 1));
end;

Related

PostgreSQL C function to get values

I am trying to write a PostgreSQL function in C.
My goal is finding minimum value of a list. So, my function will be executed like these:
SELECT min_to_max(val) FROM (VALUES(1),(2),(3)) x(val);
SELECT min_to_max(val) FROM my_table;
Here is my C code and I lost here. For example, there is a function called "PG_GETARG_INT32" to get integer values, but I don' t know how to get values from a table in order to process. Any idea?
#include "postgres.h"
#include "fmgr.h"
PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(get_sum);
Datum
get_sum(PG_FUNCTION_ARGS)
{
ArrayType *v1,
bool isnull;
isnull = PG_ARGISNULL(0);
if (isnull)
ereport( ERROR,
( errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("The input cannot be empty")));
List a = PG_GETARR_SOMEFUNCTION_2_GET_LIST(0);
# for loop iteration to find min_val
# return min_val
}
Edited(2022.05.13 - below is edited part):
Thanks to #Laurenz Albe. I made some progress.
Yet, now I want to go further(No needs to be in C language. As Laurenz Albe stated, I am just taking small steps).
My functions and aggregates like below to find min and max:
CREATE or replace FUNCTION find_min_func(
state integer,
next integer
) RETURNS integer
LANGUAGE plpgsql
STRICT
AS $$
declare
min_val integer;
begin
if $1 <= $2 then min_val := $1;
elsif $2 <$1 then min_val := $2;
end if;
return min_val;
END;
$$;
CREATE or replace AGGREGATE find_min(integer)
(
SFUNC = find_min_func,
STYPE = integer
);
CREATE or replace FUNCTION find_max_func(
state integer,
next integer
) RETURNS integer
LANGUAGE plpgsql
STRICT
AS $$
declare
max_val integer;
begin
if $1 >= $2 then max_val := $1;
elsif $2 > $1 then max_val := $2;
end if;
return max_val;
END;
$$;
CREATE or replace AGGREGATE find_max(integer)
(
SFUNC = find_max_func, -- State function
STYPE = integer -- State type
);
They are working great but now I want to do something like
SELECT min_to_max(val) FROM (VALUES(1),(2),(3)) x(val);
Expected output:
1 -> 3
So, I just wrote a state function and aggregate pair like below(I know it is wrong):
CREATE or replace FUNCTION find_min_and_max_func(
state integer,
next integer
) RETURNS varchar
LANGUAGE plpgsql
STRICT
AS $$
declare
min_val integer;
max_val integer;
output varchar;
begin
if $1 <= $2 then min_val := $1; max_val := $2;
elsif $2 <$1 then min_val := $2; max_val := $1;
end if;
output = cast(min_val as varchar) || '->' || cast(max_val as varchar) ;
return output;
END;
$$;
CREATE or replace AGGREGATE find_min_and_max(integer)
(
SFUNC = find_min_and_max_func, -- State function
STYPE = varchar -- State type
);
It is wrong because state function is taking arguments as integer but returns(?) varchar, so it varying.
How can I arrange my state function here?
Thanks!
To create an aggregate function, you have to use CREATE AGGREGATE. You create that in SQL. What you may need to implement in C is the state transition function (SFUNC), perhaps also others, depending on the kind of aggregate you want to create.
The aggregate function does not have to read from the table; the PostgreSQL executor will feed it the data it needs.
If you start writing C functions, you should perhaps start with something simpler than aggregate functions.
With the help of #Laurenz Albe(thanks to him again), I found the solution. Also, I checked out:
https://hoverbear.org/blog/postgresql-aggregates-with-rust/
https://hashrocket.com/blog/posts/custom-aggregates-in-postgresql
Here is my solution:
CREATE or replace FUNCTION find_min_and_max_func(
state point,
next integer
) RETURNS point
LANGUAGE plpgsql
STRICT
AS $$
declare
min_val integer;
max_val integer;
begin
if state[0] <= next then min_val := state[0];
elsif next < state[0] then min_val := next;
end if;
if state[1] >= next then max_val := state[1];
elsif next > state[1] then max_val := next;
end if;
return point(min_val, max_val) ;
END;
$$;
CREATE or replace FUNCTION find_min_and_max_final_func(
state point
) RETURNS varchar
LANGUAGE plpgsql
STRICT
AS $$
begin
return cast(state[0] as varchar) || '->' || cast(state[1] as varchar) ;
END;
$$;
CREATE or replace AGGREGATE find_min_and_max(integer)
(
SFUNC = find_min_and_max_func, -- State function
STYPE = point, -- State type
FINALFUNC = find_min_and_max_final_func,
initcond = '(1231231232131,0)'
);
SELECT find_min_and_max(value) FROM UNNEST(ARRAY [1, 2, 3]) as value;
find_min_and_max
------------------
1->6
(1 row)
Thanks!

Disjoint ranges in VHDL

I have a bit vector like this
subtype alarms_type : std_logic_vector(1 to 8)
signal alarms : alarms_type := (others => '0');
and the purpose of each bit is defined like this
constant sys1_temp_hi_al : integer := 1;
constant sys1_temp_lo_al : integer := 2;
constant sys1_crnt_hi_al : integer := 3;
constant sys1_cnrt_lo_al : integer := 4;
constant sys2_temp_hi_al : integer := 5;
constant sys2_temp_lo_al : integer := 6;
constant sys2_crnt_hi_al : integer := 7;
constant sys2_cnrt_lo_al : integer := 8;
I would like to be able to access subsets of the alarms_type with a short, readable notation. For example
alarms(SYS2_ALS) <= (others => '0'); -- set multiple values
temp_alarm <= or(alarms(TEMP_ALS)); -- or together multiple values to a std_logic
temp_alarms <= alarms(TEMP_ALS)); -- extract a subset to a suitably sized vector
alarms(TEMP_ALS) := (others => '1'); -- set (or clear) multiple disjoint values
I would like to know if the alias keyword will help me, like this:
alias HI_ALARMS is sys1_temp_hi_al|sys1_crnt_hi_al|sys2_temp_hi_al|sys2_crnt_hi_al;
alias LO_ALARMS is sys1_temp_lo_al|sys1_crnt_lo_al|sys2_temp_lo_al|sys2_crnt_lo_al;
alias TEMP_ALS is sys1_temp_hi_al|sys1_temp_lo_al|sys2_temp_hi_al|sys2_temp_lo_al;
alias CRNT_ALS is sys1_crnt_hi_al|sys1_crnt_lo_al|sys2_crnt_hi_al|sys2_crnt_lo_al;
alias SYS1_ALS is sys1_temp_hi_al|sys1_crnt_hi_al|sys2_temp_hi_al|sys2_crnt_hi_al;
alias SYS2_ALS is sys1_temp_hi_al|sys1_crnt_hi_al|sys2_temp_hi_al|sys2_crnt_hi_al;
It appears from the Alias chapter of the Ashenden book that this is not how an alias should be used, but hopefully I am missing something.
If there is a correct way to use alias to achieve my goal, please provide examples.
Alternatively, if there is a different or better way using constant or some other aspect of VHDL, please show me how.
Or just tell me that it can't be done, and if it is appropriate, please confirm that I could write functions to get and procedures to set the different subsets.
If I use functions and procedures, is there a cleaner notation than this? (I may need lots of this functions and procedures).
function get_temp_als(alarms : alarms_type)
return alarms(sys1_temp_hi_al) & alarms(sys1_temp_lo_al) & alarms(sys2_temp_hi_al) & alarms(sys2_temp_lo_al);
function get_combined_temp_als(alarms : alarms_type)
return alarms(sys1_temp_hi_al) or alarms(sys1_temp_lo_al) or alarms(sys2_temp_hi_al) or alarms(sys2_temp_lo_al);
procedure set_temp_als(alarms: alarm_type, value:std_logic)
begin
alarms(sys1_temp_hi_al) <= value;
alarms(sys1_temp_lo_al) <= value;
alarms(sys2_temp_hi_al) <= value;
alarms(sys2_temp_lo_al) <= value;;
end;
I would like this to work with VHDL 2002 and it is intended for synthesis.
Aliases are new names for existing named entities not new entities.
Alternatively, if there is a different or better way using constant or some other aspect of VHDL, please show me how.
There's the basic issue where it isn't clear what you're going to do with information, lacking a minimal, complete, and verifiable example you're trying to make more 'elegant'.
It is possible to use constants to specify alarms_type indexes:
library ieee;
use ieee.std_logic_1164.all;
entity alarming is
end entity;
architecture fum of alarming is
-- subprograms, constants and type declarations could be in a package
subtype alarm_range is integer range 1 to 8;
subtype alarms_type is std_logic_vector(alarm_range);
signal alarms: alarms_type := (others => '0');
constant sys1_temp_hi_al : integer := 1;
constant sys1_temp_lo_al : integer := 2;
constant sys1_crnt_hi_al : integer := 3;
constant sys1_crnt_lo_al : integer := 4;
constant sys2_temp_hi_al : integer := 5;
constant sys2_temp_lo_al : integer := 6;
constant sys2_crnt_hi_al : integer := 7;
constant sys2_crnt_lo_al : integer := 8;
type index is array (natural range <>) of alarm_range;
constant HI_ALARMS: index := (sys1_temp_hi_al, sys1_crnt_hi_al,
sys2_temp_hi_al, sys2_crnt_hi_al);
constant LO_ALARMS: index := (sys1_temp_lo_al, sys1_crnt_lo_al,
sys2_temp_lo_al, sys2_crnt_lo_al);
constant TEMP_ALS: index := (sys1_temp_hi_al, sys1_temp_lo_al,
sys2_temp_hi_al, sys2_temp_lo_al);
constant CRNT_ALS: index := (sys1_crnt_hi_al, sys1_crnt_lo_al,
sys2_crnt_hi_al, sys2_crnt_lo_al);
constant SYS1_ALS: index := (sys1_temp_hi_al, sys1_temp_lo_al,
sys1_crnt_hi_al, sys1_crnt_lo_al);
constant SYS2_ALS: index := (sys2_temp_hi_al, sys2_temp_lo_al,
sys2_crnt_hi_al, sys2_crnt_lo_al);
function get_alarm (alarm: alarms_type; indx: alarm_range)
return std_logic is
begin
return alarm(indx);
end function;
function set_alarm (alarm: alarms_type; indx: alarm_range)
return alarms_type is
variable ret_val: alarms_type := alarm;
begin
ret_val(indx) := '1';
return ret_val;
end function;
function get_alarms (alarm: alarms_type; alarm_indx: index)
return std_logic_vector is -- doesn't look real useful.
variable ret_val: std_logic_vector(alarm_indx'range);
begin
for i in alarm_indx'range loop
ret_val(i) := alarm(alarm_indx(i));
end loop;
return ret_val;
end function;
-- instead:
function select_alarms (alarm: alarms_type; alarm_indx: index)
return alarms_type is
variable ret_val: alarms_type := (others => '0');
begin
for i in alarm_indx'range loop
ret_val(alarm_indx(i)) := alarm(alarm_indx(i));
end loop;
return ret_val;
end function;
-- which returns a mask selected alarms_type value that allows the use of a
-- single alarm service routine.
function set_alarms (alarm: alarms_type; alarm_indx: index)
return alarms_type is
variable ret_val: alarms_type := (others => '0');
begin
for i in alarm_indx'range loop
ret_val(i) := alarm(alarm_indx(i));
end loop;
return ret_val;
end function;
procedure report_alarms (alarm: in alarms_type) is
type name_array is array (alarm_range) of string (1 to 15);
constant alarm_name: name_array := (
"sys1_temp_hi_al", "sys1_temp_lo_al",
"sys1_crnt_hi_al", "sys1_crnt_lo_al",
"sys2_temp_hi_al", "sys2_temp_lo_al",
"sys2_crnt_hi_al", "sys2_crnt_lo_al"
);
begin
for i in alarm_range loop
if alarm(i) = '1' then
report "alarm " & alarm_name(i) & " is set";
end if;
end loop;
end procedure;
begin
alarms <= select_alarms("11111111", TEMP_ALS) after 5 ns;
LABELED:
process (alarms)
begin
report_alarms(alarms);
end process;
end architecture;
And
ghdl -r alarming
alarming.vhdl:102:17:#5ns:(report note): alarm sys1_temp_hi_al is set
alarming.vhdl:102:17:#5ns:(report note): alarm sys1_temp_lo_al is set
alarming.vhdl:102:17:#5ns:(report note): alarm sys2_temp_hi_al is set
alarming.vhdl:102:17:#5ns:(report note): alarm sys2_temp_lo_al is set
tells us I can set all the temperature alarms using alarms selected by the set of temperature alarm indexes.
By providing a second parameter for selecting a set of alarms by name the number of subprograms drops (the alternative is to declare a type for all the different sets of alarms and provide subprograms for them all).
You are correct in that aliases do not work like that. They are an alias to a single object (or slice thereof) and cannot be used to make new compounded objects like you might do with a pointer in another language.
A procedure is likely the only way you can achieve this. The alarms paramter should be a signal and mode out:
procedure set_temp_als(signal alarms: out alarm_type; value:std_logic)
begin
alarms(sys1_temp_hi_al) <= value;
alarms(sys1_temp_lo_al) <= value;
alarms(sys2_temp_hi_al) <= value;
alarms(sys2_temp_lo_al) <= value;
end;
so you can assign the alarms with:
set_temp_als(alarms, '1');
Your functions are the right idea, but syntactically wrong:
function get_temp_als(alarms : alarms_type) return std_logic_vector is
begin
return alarms(sys1_temp_hi_al) & alarms(sys1_temp_lo_al) & alarms(sys2_temp_hi_al) & alarms(sys2_temp_lo_al);
end function;
signal some_other_slv : std_logic_vector(3 downto 0);
some_other_slv <= get_temp_als(alarms);

PLSQL - Convert Char Array To Varchar2

I have a function that remove last character from a varchar2, but I needed to convert it to char array first. Now I cant find anything to convert it back to varchar2.
My function:
DECLARE
TYPE CHAR_ARRAY IS TABLE OF CHAR(1) INDEX BY PLS_INTEGER;
NAME VARCHAR2(100) := '&vname';
NAME_CHAR CHAR_ARRAY;
BEGIN
FOR X IN 1..LENGTH(NAME) LOOP
IF((X = LENGTH(NAME))) THEN
NAME_CHAR(X) := '';
ELSE
NAME_CHAR(X) := SUBSTR(NAME, X , 1);
END IF;
END LOOP;
-- Now I need to convert it back to varchar2
END;
How about:
name := '';
for x in 1..name_char.count loop
name := name || name_char(x);
end loop;
Though why you would do any of this eludes me! If I wanted to remove the last character from a string I would do this:
name := substr (name, 1, length(name)-1);

How to convert an EBCDIC zoned decimal to a decimal in MS SQL Server 2014?

Hi everyone this is major chunk for me I have been trying lot but not getting success
there is data in db as [AH_TRAN_CV] of length 9 as Integer. and I want that in varchar with 9 char and 2 decimals.
I guess this whole code may be wrong as I don't have knowledge just used internet to get till here.. The sample is like
123D is +1234
678{ is +6780
468K is -4682
Digit Positive Negative
0 { }
1 A J
2 B K
3 C L
4 D M
5 E N
6 F O
7 G P
8 H Q
9 I R
So kindly help. Below is just part of code
Code :
Case When (substring(convert(varchar,[AH_TRAN_CV] * 0.0000001), 9, 1) = '4'
and ([AH_TRAN_CV] >= 0.00))
Then concat (substring(convert(varchar,[AH_TRAN_CV]*0.0000001), 3, 8), 'D')
end [AH_TRAN_CV]
This encoding isn't a numeric format that can be parsed to a number. It's an EBCDIC zoned decimal encoding found only in mainframes.
You can create a function that splits the string and generates the appropriate sign and last digit from the input string, eg :
create function ZonedToNumber(#somenum varchar(20))
returns varchar(20)
as
begin
declare #c char = right(#somenum,1);
declare #digit char = case when #c between 'A' and 'I' then (ascii(#c) -64)
when #c between 'J' and 'R' then (ascii(#c) -73)
when #c in ('{','}') then 0
else null end
declare #sign char = case when #c between 'A' and 'I' or #c = '{' then '+'
when #c between 'J' and 'R' or #c = '}' then '-'
else null end
RETURN CONCAT(#sign,left(#somenum,len(#somenum)-1) ,#digit)
end
Instead of performing any clever arithmetic, the function uses CASE and subtracts a base ASCII value for each case to generate the last digit and sign.
You can apply that function to a zoned decimal string to convert it to an actual number, eg: SELECT dbo.ZonedToNumber('1234') will return =1234. You can also use it in a query :
declare #t table (num varchar(20))
insert into #t
values
('123D'),
('123K'),
('123{'),
('123}')
select cast(dbo.ZonedToNumber(num) as int)
from #t x
This will return :
1234
-1232
1230
-1230
You should use this function only to convert zoned decimals to actual numbers when loading the data. Almost nobody (outside mainframes) uses this format anymore.

How can I use a prepared module in a loop in Verilog?

I am trying to generate 128 parellel XOR gates, and then connecting their outputs to 64 XOR gates in Verilog. I use a module that prepared named "EXOR". My problem is: When I put this module "EXOR" into the loop, program gives syntax error "unexpected token: 'EXOR'". And I want to name the gates exor0, exor1, ... .
How can I solve it?
initial begin
for (i=0; i<128 ; i=i +1 )
EXOR exor[i](.I1(m[2*i]), .I2(m[2*i+1]), .o(t[i]));
end
initial begin
for (i=0; i<64 ; i=i +1 )
EXOR exor[i+128](.I1(t[2*i]), .I2(t[2*i+1]), .o(f[i]));
end
initial begin
for (i=0; i<32 ; i=i +1 )
EXOR exor[i+192](.I1(f[2*i]), .I2(f[2*i+1]), .o(g[i]));
end
To elaborate on Munkymorgy's answer what you're looking for here is a generate loop. 'initial' and 'always' blocks are used for "runtime" constructs. Since you're trying to create an array on instances you want something interpreted at elaboration time.
genvar i;
generate
for (i = 0; i < 64; i = i + 1) begin : gen_loop
EXOR exor(.I1(m[2 * i]), .I2(m[2 * i + 1], .o(t[i]));
end
endgenerate
Two things:
1) The loop variable has to be declared as a 'genvar'
2) The for loop needs to be named. This will be used in the hierarchical name of the instance.

Resources