what's a nice, fast way to sort a list of GUIDs (as TGuid). i thought i'd just use SysUtils.CompareMem(P1, P2: Pointer; Length: Integer): Boolean; until i realized it returns boolean.
i'd wish for something comparable to CompareText( ) or CompareValue( ) that return integer so it can be used in a sort comparison.
i suppose not many people wish to sort GUIDs...any ideas?
i suppose i could call make some cascading calls to CompareValue( ) on the contents of the TGuid record. my instincts tell me there must be a better way!
thank you!
If you're using Delphi 2009 or better, you can use TComparer<TGUID>.Compare(), or the BinaryCompare function it calls, from the Generics.Defaults unit.
I do not know Delphi but generally a GUID is a 128-bit hexadecimal string, you can just cast/parse the sub-elements to unsigned (4 * 4-byte or 2*8-byte) integers and then compare them. Once you have that function just apply a standard sort algorithm.
If my answer does not satisfy the RFC of the GUID specification Microsoft uses is presented here, you can probably come up with better ways of sorting extracting the bit-level data in the GUID.
Use GUIDToString and do CompareStr on that -- not the fastest option but it works.
Function CompareGUIDS( pvGUID1, pvGUID2 : TGUID ) : Boolean;
Begin
If ( pvGUID1.D1 = pvGUID2.D1 ) And
( pvGUID1.D2 = pvGUID2.D2 ) And
( pvGUID1.D3 = pvGUID2.D3 ) And
( pvGUID1.D4[ 0 ] = pvGUID2.D4[ 0 ] ) And
( pvGUID1.D4[ 1 ] = pvGUID2.D4[ 1 ] ) And
( pvGUID1.D4[ 2 ] = pvGUID2.D4[ 2 ] ) And
( pvGUID1.D4[ 3 ] = pvGUID2.D4[ 3 ] ) And
( pvGUID1.D4[ 4 ] = pvGUID2.D4[ 4 ] ) And
( pvGUID1.D4[ 5 ] = pvGUID2.D4[ 5 ] ) And
( pvGUID1.D4[ 6 ] = pvGUID2.D4[ 6 ] ) And
( pvGUID1.D4[ 7 ] = pvGUID2.D4[ 7 ] ) Then
Result := True
Else
Result := False;
End;
Related
We have a view which contains 2 columns: pattern_start_time, pattern_end_time.
The select query in the function will convert it to minutes and using that result we are processing to get the shift unused coverage.The function is getting created but the processing is not happening and getting the below error:
SQLError[IX000]:Routine (my_list) cant be resolved.
Also please enter image description heresuggest to loop till the length of the result.
CREATE function myshifttesting(orgid int) returning int;
DEFINE my_list LIST( INTEGER not null );
DEFINE my_list1 LIST( INTEGER not null );
define i, j, sub, sub1 int;
define total int;
TRACE ON;
TRACE 'my testing starts';
INSERT INTO TABLE( my_list )
select
((extend(current, year to second) + (dots.v_shift_coverage.pattern_start_time - datetime(00:00) hour to minute) - current)::interval minute(9) to minute)::char(10)::INTEGER
from
dots.v_shift_coverage
where
org_guid = orgid;
INSERT INTO TABLE( my_list1 )
select
((extend(current, year to second) + (dots.v_shift_coverage.pattern_end_time - datetime(00:00) hour to minute) - current)::interval minute(9) to minute)::char(10)::INTEGER
from
dots.v_shift_coverage
where
org_guid = orgid;
let sub = 0;
let sub1 = 0;
let total = 0;
for j = 0 to 4
if (my_list(j) < my_list1(j))
then
if (my_list(j + 1) > my_list1(j))
then
let sub = sub + my_list(j + 1) - my_list1(j);
end if;
end if;
end for
if (my_list(0) > my_list1(4))
then
let sub1 = my_list(0) - my_list1(4);
end if;
let total = sub + sub1;
return total;
end function;
The error that you are receiving is because my_list(j) is not valid Informix syntax to access a LIST element. Informix is interpreting my_list(j) as a call to a function named mylist.
You can use a temporary table to "emulate" an array with your logic, something like this:
CREATE TABLE somedata
(
letter1 CHAR( 2 ),
letter2 CHAR( 2 )
);
INSERT INTO somedata VALUES ( 'a1', 'a2' );
INSERT INTO somedata VALUES ( 'b1', 'b2' );
INSERT INTO somedata VALUES ( 'c1', 'c2' );
INSERT INTO somedata VALUES ( 'd1', 'd2' );
INSERT INTO somedata VALUES ( 'e1', 'e2' );
DROP FUNCTION IF EXISTS forloop;
CREATE FUNCTION forloop()
RETURNING CHAR( 2 ) AS letter1, CHAR( 2 ) AS letter2;
DEFINE number_of_rows INTEGER;
DEFINE iterator INTEGER;
DEFINE my_letter1 CHAR( 2 );
DEFINE my_letter2 CHAR( 2 );
-- Drop temp table if it already exists in the session
DROP TABLE IF EXISTS tmp_data;
CREATE TEMP TABLE tmp_data
(
tmp_id SERIAL,
tmp_letter1 CHAR( 2 ),
tmp_letter2 CHAR( 2 )
);
-- Insert rows into the temp table, serial column will be the access key
INSERT INTO tmp_data
SELECT 0,
d.letter1,
d.letter2
FROM somedata AS d
ORDER BY d.letter1;
-- Get total rows of temp table
SELECT COUNT( * )
INTO number_of_rows
FROM tmp_data;
FOR iterator = 1 TO number_of_rows
SELECT d.tmp_letter1
INTO my_letter1
FROM tmp_data AS d
WHERE d.tmp_id = iterator;
-- Check if not going "out of range"
IF iterator < number_of_rows THEN
SELECT d.tmp_letter2
INTO my_letter2
FROM tmp_data AS d
WHERE d.tmp_id = iterator + 1;
ELSE
-- iterator + 1 is "out of range", return to the beginning
SELECT d.tmp_letter2
INTO my_letter2
FROM tmp_data AS d
WHERE d.tmp_id = 1;
END IF;
RETURN my_letter1, my_letter2 WITH RESUME;
END FOR;
END FUNCTION;
-- Running the function
EXECUTE FUNCTION forloop();
-- Results
letter1 letter2
a1 b2
b1 c2
c1 d2
d1 e2
e1 a2
5 row(s) retrieved.
My field values are like:
810.9 MB
1.2 GB
395.1 MB
982.3 MB
7.7 GB
149.4 MB
10.0 GB
429.1 MB
3.1 GB
and I want to sum this column in gb in my ASP.NET MVC controller.
But I have no idea how to do this.
You could try something like this:
-- This is your "raw" input - just all the strings in your example
DECLARE #input TABLE (Measure VARCHAR(50))
INSERT INTO #input ( Measure )
VALUES ('810.9 MB'), ('1.2 GB'), ( '395.1 MB'), ( '982.3 MB'), ( '7.7 GB'), ( '149.4 MB'), ( '10.0 GB'), ( '429.1 MB'), ( '3.1 GB')
-- Now declare a separate table that contains (1) the raw value, (2) the contained *numerical* value, and (3) the unit of measure
DECLARE #Storage TABLE (Measure VARCHAR(50), NumValue DECIMAL(20,4), Unit VARCHAR(10))
-- Fill your raw input into that "working table"
INSERT INTO #Storage (Measure, NumValue, Unit)
SELECT
Measure,
NumMeasure = CAST(SUBSTRING(Measure, 1, CHARINDEX(' ', Measure)) AS DECIMAL(20, 2)),
Unit = SUBSTRING(Measure, CHARINDEX(' ', Measure) + 1, 9999)
FROM
#input
SELECT * FROM #Storage
-- when you select from that "working" table, you can now easily *SUM* the numerical values,
-- and show them on screen whichever way you want - as "xxx MB" or "yyyy GB" or whatever - up to you
SELECT
SUM(CASE Unit
WHEN 'MB' THEN NumValue * 1000000
WHEN 'GB' THEN NumValue * 1000000000
ELSE NumValue
END),
CAST(SUM(CASE Unit
WHEN 'MB' THEN NumValue * 1000000
WHEN 'GB' THEN NumValue * 1000000000
ELSE NumValue
END) / 1000000000.0 AS VARCHAR(25)) + ' GB'
FROM
#Storage
Update:
If you want to do this in C# code, try this:
foreach(var item in list)
{
// split "item" into two parts
string[] parts = item.Split(' ');
// parts[0] should be a decimal value
decimal numValue = 0.0m;
if (decimal.TryParse(parts[0], out numValue))
{
decimal convertedValue = 0.0m;
if(parts[1] == "MB")
{
convertedValue = numValue * 1000000;
}
else if (parts[1] == "GB")
{
convertedValue = numValue * 1000000000;
}
}
}
I'm attempting to modify my market orders to breakeven the position when the position get 100 pips to the good. This also accounts for the StopLevels which are around 20-30 pips for my broker. It checks the param's via a "for(){...} loop" function
The MagicNumber is the timeframe number for the chart it is on (i.e. 240=4H, 60=1H) I don't set a TakeProfit price & initially no StopLoss price.
The EA is not adding a SL to be equal to the opening price when the trade reaches 100 pip in profit (plus stoplevels). Profit points reaches well over 130 points.
My code is below for a OP_SELL order - any help would be appreciated. Regards, Todd
/*Global Declarations*/
double pnlPoints;
double price, sl, tp;
double point;
int stopLevel;
int breakeven;
double newSL;
/*Local Declaratons*/
pnlPoints = 0;
point = MarketInfo( Symbol(), MODE_POINT );
stopLevel = int( MarketInfo( Symbol(), MODE_STOPLEVEL )
+ MarketInfo( Symbol(), MODE_SPREAD )
);
sl = NormalizeDouble( OrderStopLoss(), Digits );
tp = OrderTakeProfit();
breakeven = 100;
for( int s = OrdersTotal() - 1; s >= 0; s-- )
{ if ( ( OrderSelect( s, SELECT_BY_POS, MODE_TRADES ) ) == true )
price = MarketInfo( Symbol(), MODE_ASK );
newSL = NormalizeDouble( OrderOpenPrice(), Digits );
pnlPoints = ( OrderOpenPrice() - price ) / point;
if ( OP_SELL == OrderType() )
if ( Period() == OrderMagicNumber() )
if ( stopLevel < ( newSL - price ) / point )
if ( breakeven < pnlPoints )
if ( newSL != sl )
ModSell = OrderModify( OrderTicket(),
OrderOpenPrice(),
newSL,
tp,
buycolor
);
else if ( ModBuy == false )
{ Print( "OrderModify failed with error #",
GetLastError()
);
}
}
For the moment being,refine the codeandadd self-debuging / tracing code
After OrderModify() use a self-debugging / journaling Print( StringFormat( ... ) ) to document all instructed values used in the actual OrderModify() call and also the remote-execution ( { server-side | StrategyTester } ) reported issues.
The current code does not enter into such self-diagnostics and ModSell is not inspected at all, ModBuy is inspected only at uncertain conditions / by-coincidence at some future visit of the for(){...} code-execution path to a part after newSL == sl ( and all above stated conditions are just by chance met too )
Next, check an assigned value of tp
As stated above,
/*Local Declarations*/
...
tp = OrderTakeProfit();
which introduces a reasonable doubt, that re-using of this ( inherently uncertain value, as no one knows, which OrderSelect() was the last one that set a db.Pool pointer to decide, from which record from the db.Pool this veryOrderTakeProfit() would accidentally read ( if any record is present in db.Pool already ) inside the whole for(){...} traversing the db.Pool records will not meet conditions for setting properly a TakeProfit price in the next series of OrderModify() calls.
This seems to be the root cause, or a source of unhandled exceptions to the valid, Broker-compliant, OrderModify() values.
Try this:
if (newSL != sl ) {
ModSell = OrderModify( OrderTicket(),
OrderOpenPrice(),
OrderOpenPrice(),
0,
OrderExpiration(),
clrRed
);
if(ModBuy == false )
Print( "OrderModify failed with error #", GetLastError());
}
Then check the Expert-tab for error-message if it fails to set the stop.
Also, you need to take note that StopLoss will ONLY occur if you are on the right chart-timeframe; Otherwise, it won't even get into the if-statements.
I am new to DB2 queries.
Here, I am passing a comma separated value as an IN parameter in a Stored Procedure. I want to search on the basis of those values.
Select * from USER where user_id in (IN_User);
Here, IN_User will have values of the kind ('val1','val2','val3')
It should return all the rows which has val1 or val2 or val3 as the User_id. As much as I know this can be done using UDF but I want to know is there any other way to do it without UDF.
please create a function to split the comma separated string
Please see the below function
CREATE FUNCTION StringToRows(
cString1 CLOB (10 M) ,
cStringSplitting1 VARCHAR(10) )
RETURNS TABLE (Lines VARCHAR(500))
SPECIFIC StringToRows_Big
DETERMINISTIC
NO EXTERNAL ACTION
CONTAINS SQL
BEGIN ATOMIC
DECLARE cStringSplitting VARCHAR(10);
DECLARE LenSplit SMALLINT;
SET cStringSplitting = cStringSplitting1;
SET LenSplit = LENGTH(cStringSplitting);
IF LENGTH(TRIM(cStringSplitting)) = 0 THEN
SET cStringSplitting = ' ', LenSplit = 1 ;
END IF ;
RETURN WITH
TEMP1 ( STRING) as (values (cString1) ),
TEMP2 ( Lines, STRING_left) as
(SELECT
SUBSTR(STRING,1, CASE WHEN LOCATE(cStringSplitting, STRING) = 0 THEN LENGTH(STRING) ELSE LOCATE(cStringSplitting,STRING) - 1 END),
(CASE WHEN (LOCATE(cStringSplitting, STRING) = 0) THEN '' ELSE SUBSTR(STRING, LOCATE(cStringSplitting,STRING) + LenSplit) END)
FROM TEMP1 WHERE LENGTH(STRING) > 0
UNION ALL
SELECT
SUBSTR(STRING_left,1, CASE LOCATE(cStringSplitting,STRING_left) WHEN 0 THEN LENGTH(STRING_left) ELSE LOCATE(cStringSplitting,STRING_left) - 1 END),
(CASE WHEN LOCATE(cStringSplitting,STRING_left) = 0 THEN '' ELSE SUBSTR(STRING_left, LOCATE(cStringSplitting,STRING_left) + LenSplit) END)
FROM TEMP2 WHERE LENGTH(STRING_left) > 0 )
SELECT Lines FROM TEMP2;
END
please see the sample stored procedure to call the function
CREATE PROCEDURE TEST_USR(IN #inputParam CLOB (10 M))
SPECIFIC TEST_USR
DYNAMIC RESULT SETS 1
P1: BEGIN
DECLARE CURSOR1 CURSOR WITH RETURN FOR
Select * from USER where user_id IN (SELECT * FROM TABLE(StringToRows(#inputParam, ',')) AS test);
OPEN CURSOR1;
END P1
I am tidying old code that used to use FastStrings and I've implemented an old routine of mine 'PosAnyCase' which should operate like 'Pos'. (I was hoping that SearchBuf was better than calling UpperCase on both strings).
function PosAnyCase( const AFindStr, AStr : string ) : integer;
// Returns the position of this substring within a string ignoring case
I'm using SearchBuf as follows:
function PosAnyCase( const AFindStr, AStr : string ) : integer;
// Returns the position of this substring within a string ignoring case
var
Start, ResultPos : PChar;
begin
Start := PChar( AStr );
ResultPos := SearchBuf(
Start, ByteLength( AStr ),
0, 0,
AFindStr, [soDown] );
if ResultPos = nil then
Result := 0
else
Result := ResultPos-Start+1;
end;
When I call this routine from my unit tests, the following tests PASS:
Check(
PosAnyCase( '', '123' ) = 0 );
Check(
PosAnyCase( '2', '123' ) = 2 );
Check(
PosAnyCase( 'A', 'ABC' ) = 1 );
Check(
PosAnyCase( 'a', 'ABC' ) = 1 );
Check(
PosAnyCase( 'the', 'hellot there' ) = 8 );
Check(
PosAnyCase( 'THE', 'hellot there' ) = 8 );
But this test FAILS:
Check(
PosAnyCase( 'nice', 'does not have n i c e' ) = 0 );
What am I doing wrong please? The documentation on SearchBuf is very limited....
Thanks
The call to ByteLength is incorrect. Although the documentation explicitly states that the parameter is the length in bytes, that is not the case. You should use Length instead because the function actually expects units of char rather than units of byte.