Is there a way to skip part of function in IDA? - cocos2d-x

I'm new to reverse engineering and im trying to edit one function then patch apk. This is an old unsupported apk where i want to enable one function, but it have some fail checks. I think the easiest way would be to just skip part of code and go straight to line where it trigger script in apk.
Function:
.text:006615C4 ; =============== S U B R O U T I N E =======================================
.text:006615C4
.text:006615C4 ; Attributes: bp-based frame
.text:006615C4
.text:006615C4 ; DLCView::msg_S_REQUEST_DLC(unsigned int, cocos2d::Ref *)
.text:006615C4 EXPORT _ZN7DLCView17msg_S_REQUEST_DLCEjPN7cocos2d3RefE
.text:006615C4 _ZN7DLCView17msg_S_REQUEST_DLCEjPN7cocos2d3RefE
.text:006615C4 ; DATA XREF: LOAD:00026E50↑o
.text:006615C4 ; __unwind { // 4459C0
.text:006615C4 PUSH {R4-R7,LR}
.text:006615C6 ADD R7, SP, #0xC
.text:006615C8 PUSH.W {R8}
.text:006615CC SUB SP, SP, #0x30
.text:006615CE MOV R4, R0
.text:006615D0 LDR R0, =(__stack_chk_guard_ptr - 0x6615D6)
.text:006615D2 ADD R0, PC
.text:006615D4 LDR.W R8, [R0]
.text:006615D8 LDR.W R0, [R8]
.text:006615DC STR R0, [SP,#0x2C]
.text:006615DE CBZ R2, loc_661632
.text:006615E0 LDR R1, =(aR_0 - 0x6615EA) ; "r"
.text:006615E2 ADD R6, SP, #0x10
.text:006615E4 MOV R5, R2
.text:006615E6 ADD R1, PC ; "r"
.text:006615E8 MOV R0, R6
.text:006615EA BLX j__ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC2IDnEEPKc ; std::__ndk1::basic_string<char,std::__ndk1::char_traits<char>,std::__ndk1::allocator<char>>::basic_string<decltype(nullptr)>(char const*)
.text:006615EE MOV R0, R5
.text:006615F0 MOV R1, R6
.text:006615F2 BLX j__ZN7cocos2d12__Dictionary11valueForKeyERKNSt6__ndk112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE ; cocos2d::__Dictionary::valueForKey(std::__ndk1::basic_string<char,std::__ndk1::char_traits<char>,std::__ndk1::allocator<char>> const&)
.text:006615F6 MOVS R1, #0
.text:006615F8 BLX j__ZNK7cocos2d8__String8intValueEi ; cocos2d::__String::intValue(int)
.text:006615FC MOV R6, R0
.text:006615FE ADD R0, SP, #0x10
.text:00661600 BLX j__ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED2Ev ; std::__ndk1::basic_string<char,std::__ndk1::char_traits<char>,std::__ndk1::allocator<char>>::~basic_string()
.text:00661604 CBZ R6, loc_661656
.text:00661606 BLX j__ZN12FloatMessage9singletonEv ; FloatMessage::singleton(void)
.text:0066160A MOV R4, R0
.text:0066160C BLX j__ZN17NewLocalStringMgr9singletonEv ; NewLocalStringMgr::singleton(void)
.text:00661610 MOV R1, R6
.text:00661612 BLX j__ZN17NewLocalStringMgr17getStringWithCodeEi ; NewLocalStringMgr::getStringWithCode(int)
.text:00661616 ADD R5, SP, #0x10
.text:00661618 MOV R1, R0
.text:0066161A MOV R0, R5
.text:0066161C BLX j__ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC2IDnEEPKc ; std::__ndk1::basic_string<char,std::__ndk1::char_traits<char>,std::__ndk1::allocator<char>>::basic_string<decltype(nullptr)>(char const*)
.text:00661620 LDR R2, =0x40400000
.text:00661622 MOV R0, R4
.text:00661624 MOV R1, R5
.text:00661626 BLX j__ZN12FloatMessage3addERKNSt6__ndk112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEf ; FloatMessage::add(std::__ndk1::basic_string<char,std::__ndk1::char_traits<char>,std::__ndk1::allocator<char>> const&,float)
.text:0066162A
.text:0066162A loc_66162A ; CODE XREF: DLCView::msg_S_REQUEST_DLC(uint,cocos2d::Ref *)+12C↓j
.text:0066162A ADD R0, SP, #0x10
.text:0066162C BLX j__ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED2Ev ; std::__ndk1::basic_string<char,std::__ndk1::char_traits<char>,std::__ndk1::allocator<char>>::~basic_string()
.text:00661630 B loc_6616B6
.text:00661632 ; ---------------------------------------------------------------------------
.text:00661632
.text:00661632 loc_661632 ; CODE XREF: DLCView::msg_S_REQUEST_DLC(uint,cocos2d::Ref *)+1A↑j
.text:00661632 LDR R1, =(aMsgSRequestDlc - 0x66163C) ; "msg_S_REQUEST_DLC"
.text:00661634 MOVS R0, #0x91
.text:00661636 LDR R2, =(aUsersYangqyWor_65 - 0x66163E) ; "/Users/yangqy/work/EWClient/proj.androi"...
.text:00661638 ADD R1, PC ; "msg_S_REQUEST_DLC"
.text:0066163A ADD R2, PC ; "/Users/yangqy/work/EWClient/proj.androi"...
.text:0066163C STRD.W R2, R1, [SP]
.text:00661640 MOVS R1, #8
.text:00661642 STR R0, [SP,#8]
.text:00661644 MOV.W R0, #0x4000000
.text:00661648 LDR R2, =(aCheckFailedSFi - 0x661650) ; "check failed: %s\nfile: '%s', function:"...
.text:0066164A LDR R3, =(aDict - 0x661652) ; "dict"
.text:0066164C ADD R2, PC ; "check failed: %s\nfile: '%s', function:"...
.text:0066164E ADD R3, PC ; "dict"
.text:00661650 BLX j__Z12OutputString11EOutputTypeiPKcz ; OutputString(EOutputType,int,char const*,...)
.text:00661654 B loc_6616B6
.text:00661656 ; ---------------------------------------------------------------------------
.text:00661656
.text:00661656 loc_661656 ; CODE XREF: DLCView::msg_S_REQUEST_DLC(uint,cocos2d::Ref *)+40↑j
.text:00661656 LDR R1, =(aMid - 0x66165E) ; "mid"
.text:00661658 ADD R6, SP, #0x10
.text:0066165A ADD R1, PC ; "mid"
.text:0066165C MOV R0, R6
.text:0066165E BLX j__ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC2IDnEEPKc ; std::__ndk1::basic_string<char,std::__ndk1::char_traits<char>,std::__ndk1::allocator<char>>::basic_string<decltype(nullptr)>(char const*)
.text:00661662 MOV R0, R5
.text:00661664 MOV R1, R6
.text:00661666 BLX j__ZN7cocos2d12__Dictionary11valueForKeyERKNSt6__ndk112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE ; cocos2d::__Dictionary::valueForKey(std::__ndk1::basic_string<char,std::__ndk1::char_traits<char>,std::__ndk1::allocator<char>> const&)
.text:0066166A MOVS R1, #0
.text:0066166C BLX j__ZNK7cocos2d8__String9uintValueEj ; cocos2d::__String::uintValue(uint)
.text:00661670 ADD R5, SP, #0x10
.text:00661672 MOV R6, R0
.text:00661674 MOV R0, R5
.text:00661676 BLX j__ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED2Ev ; std::__ndk1::basic_string<char,std::__ndk1::char_traits<char>,std::__ndk1::allocator<char>>::~basic_string()
.text:0066167A CBZ R6, loc_6616CC
.text:0066167C BLX j__ZN9ScriptMgr9singletonEv ; ScriptMgr::singleton(void)
.text:00661680 MOV R1, R6
.text:00661682 BLX j__ZN9ScriptMgr20triggerEnteringTowerEj ; ScriptMgr::triggerEnteringTower(uint)
.text:00661686 STR R5, [SP,#0x20]
.text:00661688 LDR R1, =(_ZTVNSt6__ndk110__function6__funcIZN7DLCView17msg_S_REQUEST_DLCEjPN7cocos2d3RefEE3$_3NS_9allocatorIS6_EEFvvEEE - 0x66168E) ; `vtable for'std::__ndk1::__function::__func<DLCView::msg_S_REQUEST_DLC(uint,cocos2d::Ref *)::$_3,std::__ndk1::allocator<DLCView::msg_S_REQUEST_DLC(uint,cocos2d::Ref *)::$_3>,void ()(void)>
.text:0066168A ADD R1, PC ; `vtable for'std::__ndk1::__function::__func<DLCView::msg_S_REQUEST_DLC(uint,cocos2d::Ref *)::$_3,std::__ndk1::allocator<DLCView::msg_S_REQUEST_DLC(uint,cocos2d::Ref *)::$_3>,void ()(void)>
.text:0066168C ADDS R1, #8
.text:0066168E STR R1, [SP,#0x10]
.text:00661690 LSRS R1, R0, #4
.text:00661692 CMP R1, #0x7C ; '|'
.text:00661694 IT HI
.text:00661696 MOVHI R6, R0
.text:00661698 STR R6, [SP,#0x14]
.text:0066169A LDR R0, [R4]
.text:0066169C LDR.W R2, [R0,#0x398]
.text:006616A0 MOV R0, R4
.text:006616A2 MOV R1, R5
.text:006616A4 BLX R2
.text:006616A6 ADD R0, SP, #0x10
.text:006616A8 BL _ZNSt6__ndk18functionIFvvEED2Ev_0 ; std::__ndk1::function<void ()(void)>::~function()
.text:006616AC LDR R0, [R4]
.text:006616AE LDR.W R1, [R0,#0x34C]
.text:006616B2 MOV R0, R4
.text:006616B4 BLX R1
.text:006616B6
.text:006616B6 loc_6616B6 ; CODE XREF: DLCView::msg_S_REQUEST_DLC(uint,cocos2d::Ref *)+6C↑j
.text:006616B6 ; DLCView::msg_S_REQUEST_DLC(uint,cocos2d::Ref *)+90↑j
.text:006616B6 LDR.W R0, [R8]
.text:006616BA LDR R1, [SP,#0x2C]
.text:006616BC SUBS R0, R0, R1
.text:006616BE ITTT EQ
.text:006616C0 ADDEQ SP, SP, #0x30 ; '0'
.text:006616C2 POPEQ.W {R8}
.text:006616C6 POPEQ {R4-R7,PC}
.text:006616C8 BLX __stack_chk_fail
.text:006616CC ; ---------------------------------------------------------------------------
.text:006616CC
.text:006616CC loc_6616CC ; CODE XREF: DLCView::msg_S_REQUEST_DLC(uint,cocos2d::Ref *)+B6↑j
.text:006616CC BLX j__ZN12FloatMessage9singletonEv ; FloatMessage::singleton(void)
.text:006616D0 MOV R4, R0
.text:006616D2 BLX j__ZN17NewLocalStringMgr9singletonEv ; NewLocalStringMgr::singleton(void)
.text:006616D6 MOVS R1, #2
.text:006616D8 BLX j__ZN17NewLocalStringMgr17getStringWithCodeEi ; NewLocalStringMgr::getStringWithCode(int)
.text:006616DC ADD R5, SP, #0x10
.text:006616DE MOV R1, R0
.text:006616E0 MOV R0, R5
.text:006616E2 BLX j__ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC2IDnEEPKc ; std::__ndk1::basic_string<char,std::__ndk1::char_traits<char>,std::__ndk1::allocator<char>>::basic_string<decltype(nullptr)>(char const*)
.text:006616E6 LDR R2, =0x40400000
.text:006616E8 MOV R0, R4
.text:006616EA MOV R1, R5
.text:006616EC BLX j__ZN12FloatMessage3addERKNSt6__ndk112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEf ; FloatMessage::add(std::__ndk1::basic_string<char,std::__ndk1::char_traits<char>,std::__ndk1::allocator<char>> const&,float)
.text:006616F0 B loc_66162A
.text:006616F0 ; End of function DLCView::msg_S_REQUEST_DLC(uint,cocos2d::Ref *)
.text:006616F0
.text:006616F0 ; ---------------------------------------------------------------------------
I want this function to always trigger part where there is "ScriptMgr::triggerEnteringTower(uint)" at
.text:00661682 BLX j__ZN9ScriptMgr20triggerEnteringTowerEj ;
and dont fail. If you can help me with detailed instructions how to edit this out i would be realy glad.enter code here

Related

MySQL: Combining all results from a LOOP (possibly with UNION?)

EDIT: already solved and answered: but feel free to read along and see how the process went if you have similar questions
BACKGROUND
I created a procedure called 'sea_dew_potion' and placed it within a loop called 'loopseadew'. the loop works as intended.
QUESTION
My loop produced 18 results, but I would like it to be in a single result set so I can export it to tableau to make a line graph with multiple data points to make some form of curve. After some research I think a UNION would work but I'm not sure how to go about it, mostly cause I just figured out how loops work and then how to fit another procedure within a loop haha. Thanks for the help!
DELIMITER $$
CREATE PROCEDURE loopseadew(IN p_base_name VARCHAR(255), IN p_base_amount integer, IN p_ing_name VARCHAR(255), p_ing_amount integer, p_pot_units INTEGER(3))
BEGIN
DECLARE p_ing_amount int;
SET p_ing_amount = 0;
loop1: LOOP
SET p_ing_amount = p_ing_amount + 1;
CALL sea_dew_potion('sea dew', 100, 'skadite', 0, 10);
IF p_ing_amount = 18 THEN
LEAVE loop1;
END IF;
END LOOP loop1;
SELECT p_base_name, p_base_amount, p_ing_name, p_ing_amount,
m.price * p_ing_amount AS cost
FROM
multiplier m
WHERE
m.ing_name = p_ing_name;
END$$
DELIMITER ;
EDIT: im getting some progress, but i am getting null values for columns 'heal' and 'cost'. values for heal is produced the procedure "sea_dew_potion". Right now i get 18 individual results with all the correct values, and one result with all the results combined but null values for heal and cost.
Screenshots at the bottom to show the problem between the result sets.
DELIMITER $$
CREATE PROCEDURE allloopseadew(IN p_base_name VARCHAR(255), IN p_base_amount integer, IN p_ing_name VARCHAR(255), p_ing_amount integer, p_pot_units INTEGER(3))
BEGIN
DECLARE x int;
CREATE TEMPORARY TABLE allresults (p_base_name varchar(255), p_base_amount int(3), p_ing_name VARCHAR(255), p_ing_amount int(3), heal decimal(10,2), cost decimal(10,2));
SET x = 0;
loop1: LOOP
SET x = x + 1;
CALL sea_dew_potion('sea dew', 100, 'skadite', x, 10);
IF x = 18 THEN
LEAVE loop1;
END IF;
INSERT INTO allresults
VALUES(p_base_name, p_base_amount, p_ing_name , x, heal, cost);
END LOOP loop1;
SELECT p_base_name, p_base_amount, p_ing_name, p_ing_amount,
m.price * p_ing_amount AS cost
FROM
multiplier m
WHERE
m.ing_name = p_ing_name;
SELECT * FROM allresults;
END$$
DELIMITER ;
EDIT PART 2
Shout out to #blabla_bingo i finally got it! Here is the final query for anyone interested haha
CREATE PROCEDURE allloopseadew(IN p_base_name VARCHAR(255), IN p_base_amount integer, IN p_ing_name VARCHAR(255), p_ing_amount integer, p_pot_units INTEGER(3))
BEGIN
DECLARE x decimal(10,3);
DECLARE v_heal decimal(10,3);
DECLARE v_cost decimal(10,3);
DECLaRE v_total_amount int(3);
CREATE TEMPORARY TABLE allresults (p_base_name varchar(255), p_base_amount int(3), p_ing_name VARCHAR(255), p_ing_amount int(3), heal decimal(10,2), cost decimal(10,2));
SET x = 0;
loop1: LOOP
SET x = x + 1;
SET v_total_amount =
(SELECT p_base_amount + x);
SET v_heal =
(SELECT
round(max((2*(2.1*(p_base_amount/v_total_amount))*1*(1+sqrt(x/v_total_amount)*m.multiplier_value)*p_pot_units)),3)
FROM
multiplier m
WHERE
m.ing_name = p_ing_name);
SET v_cost =
(SELECT
m.price * x
FROM
multiplier m
WHERE
m.ing_name = p_ing_name);
CALL sea_dew_potion('sea dew', 100, 'skadite', x, 10);
IF x = 18 THEN
LEAVE loop1;
END IF;
INSERT INTO allresults
VALUES(p_base_name, p_base_amount, p_ing_name, x, v_heal, v_cost);
END LOOP loop1;
SELECT p_base_name, p_base_amount, p_ing_name, p_ing_amount,
m.price * p_ing_amount AS cost
FROM
multiplier m
WHERE
m.ing_name = p_ing_name;
SELECT * FROM allresults;
END$$
DELIMITER ;
all results with no heal or cost
individual result with heal and cost
Final correct result with query
UNION has its drawbacks such as being unable to sort out using ORDER BY clause. Besides, a total of 17 UNION need to be used in this case if you decides to go along, which makes the query drag on too much. I would suggest use a result table and have your procedure sea_dew_potion insert into it. Then you can query the result table and probably make some adjustment before exporting into your tableau table. Finally,as a side note, instead of calling the sea_dew_potion 18 times in a loop, we can also add a count parameter for the procedure sea_dew_potion ,so that we only need to define the count number and run the procedure once. e.g sea_dew_potion(p1,p2,p3,p4,p5,count_num int).

How to run the script with the procedure that generates the plates of a state? and How to consult the plates created for the state of Querétaro?

I have a project that requires solving the following questions:
How to run the script with the procedure that generates the plates of a state?
(probably requires tropicalizing the script)
How to consult the plates created for the state of Querétaro?
the problem is that I don't know how to execute the instructions in postgreSQL, it allows me to create the tables and add data but to execute the instructions no longer. Some instructions are not from postgreSQL like "varchar2" and "numberic".
Note:
I have deleted the "comment on column / table" because it is not relevant. My postgresSSQL only works no graphical interfaces(pgAdmin 4)
-- EXECUTE GENERAPLACAS ('22,'TE')
create or replace procedure GENERAPLACAS(pestado in char,
pservicio in char) is
Result number :=9;
-- Devuelve -1 El estado o el servicio no cuentan con un regisro de la serie a crear.
-- -2 No se pudo contar el número de placas generadas
-- -3 No se pudo recuperar la placa inicial ni final
-- -4 Cuando a serie ya ha sido creada.
-- -5 Estado = 09 o Servicio <> TE
-- 9n Se han creado 9n placas.
vini PSERIE.SERI_INI%TYPE;
vfin PSERIE.SERI_FIN%TYPE;
vtotal number := 0;
-- Se declaran las letras y numeros para su posición correspondiente:
li1 char(1);
lf1 char(1);
li2 char(1);
lf2 char(1);
li3 char(1);
lf3 char(1);
li4 char(1);
lf4 char(1);
ni1 number;
nf1 number;
ni2 number;
nf2 number;
ni3 number;
nf3 number;
P1 number;
P2 number;
P3 number;
P4 number;
p7 number;
total number:=0;
plk char(8):=null;
plkf char(7);
begin
IF (pestado IS NOT NULL) AND (pservicio IS NOT NULL) Then -- El Servicio o estado NO es nulo
BEGIN
SELECT SERI_INI, SERI_FIN
INTO vini, vfin
FROM PSERIE
WHERE SERI_ESTADO = pestado
and SERI_SERVICIO = pservicio ;
EXCEPTION -- No pudo recuperarse la Placa inicial no final
WHEN OTHERS THEN
Result:=-1 ;
END ;
BEGIN
SELECT COUNT(*)
INTO vtotal
FROM PPLACA
WHERE PLAC_PLACA BETWEEN VINI AND VFIN ;
EXCEPTION
WHEN OTHERS THEN -- No se pudo contar el número de placas
Result:=-2 ;
END ;
ELSE -- El Servicio o estado es nulo
Result:=-1 ;
END IF;
-- No cambio Result
IF result = 9 THEN -- Hay placa inicial y final y no marco error contar cuantas placas hay creadas
begin
IF vtotal = 0 THEN -- No hay placas creadas
BEGIN
IF PESTADO <> '09' AND PSERVICIO = 'TE' THEN -- Se generan las placas, El DF ('09') se genera diferente
BEGIN
li1:=substr(vini,1,1) ;
lf1:=substr(vfin,1,1) ;
li2:=substr(vini,2,1) ;
lf2:=substr(vfin,2,1) ;
li3:=substr(vini,3,1) ;
lf3:=substr(vfin,3,1) ;
ni1:=substr(vini,4,1) ;
nf1:=substr(vfin,4,1) ;
ni2:=substr(vini,5,1) ;
nf2:=substr(vfin,5,1) ;
ni3:=substr(vini,6,1) ;
nf3:=substr(vfin,6,1) ;
li4:=substr(vini,7,1) ;
lf4:=substr(vfin,7,1) ;
-- I, Ñ, O, Q
-- 000
FOR P1 in ascii(li1)..ascii(lf1) LOOP
IF chr(p1) not in ('I', 'O', 'Q') THEN
FOR P2 in ascii(li2)..ascii(lf2) LOOP
IF chr(p2) not in ('I', 'O', 'Q') THEN
FOR p3 in ascii(li3)..ascii(lf3) LOOP
IF chr(p3) not in ('I', 'O', 'Q') THEN
FOR P4 in 1..999 LOOP
FOR p7 in ascii(li4)..ascii(lf4) LOOP
IF chr(p7) not in ('I', 'O', 'Q') THEN
begin
total:=total+1;
plk:=null;
plk:=chr(p1) || chr(p2) || chr(p3) || to_char(p4,'009') || chr(p7) ;
plkf:=substr(plk,1,3) || substr(plk,5,4);
INSERT INTO PPLACA(PLAC_PLACA, PLAC_ESTADO)
VALUES (PLKF,pestado);
--plkf:=substr(plk,1,3) || substr(plk(5,4) ;
-- dbms_output.put_line(plkf);
-- || chr(p2) || chr(p3) || to_char(p4,'009') || chr(p7) ;
end ;
END IF;
END LOOP ;
commit ;
END LOOP ;
END IF;
END LOOP;
END iF ;
END LOOP ;
END IF;
END LOOP;
-- result:=ascii(li1) ;
result:=total;
END ;
ELSE
result:=-5 ;
END IF ;
END ;
ELSE
result:=-4 ; -- Ya ha sido creada la serie
END IF;
end ;
END IF;
if Result <> 9 then
dbms_output.put_line('Error: ' || to_char(Result,'0009'));
end if;
end generaplacas;

trying to create column with season-to-date averages of values of another column in same table using MySQL

I'm struggling with determining the MySQL code to create a column (average park_factor) in my table "starting_pitcher_stats" that I'd like to contain the season-to-date in-season average values of the values in another column (park_factor). I'd like this in-season average to be grouped by pitcher and by date.
Ideally, the table would look like this:
pitcher park_fac avg_park_fac date
aased001 94 94 1977-07-31
aased001 100 97 1977-08-06
aased001 108 100.666 1977-08-11
aased001 108 102.5 1977-08-16
aased001 96 101.2 1977-08-21
aased001 108 102.33 1977-08-26
aased001 108 103.14 1977-08-31
aased001 104 103.25 1977-09-05
aased001 108 103.77 1977-09-10
aased001 92 102.6 1977-09-16
aased001 106 102.9 1977-09-22
aased001 108 103.33 1977-09-27
The code I'm using is:
SELECT Starting_Pitcher, full_park_factor, AVG(full_park_factor), Game_Date
FROM starting_pitcher_stats
GROUP BY Starting_Pitcher, Game_Date, Game_Number
...and a sample of the resulting table looks like this:
pitcher park_fac avg_park_fac date
aased001 94 94.0000 1977-07-31
aased001 100 100.0000 1977-08-06
aased001 108 108.0000 1977-08-11
aased001 108 108.0000 1977-08-16
aased001 96 96.0000 1977-08-21
aased001 108 108.0000 1977-08-26
aased001 108 108.0000 1977-08-31
aased001 104 104.0000 1977-09-05
aased001 108 108.0000 1977-09-10
aased001 92 92.0000 1977-09-16
aased001 106 106.0000 1977-09-22
aased001 108 108.0000 1977-09-27
Can someone help please?
Thank you in advance for help with this.
Lee
You need to join your table on all previous results for the same pitcher from the same table.
I'm not quite sure how you define your season, but assuming it's by calendar year, the following query produces the desired output.
SELECT
a.Starting_Pitcher, a.full_park_factor,
AVG(b.full_park_factor), a.Game_Date, a.Game_Number
FROM starting_pitcher_stats a
INNER JOIN starting_pitcher_stats b
ON a.Starting_Pitcher = b.Starting_Pitcher
AND (b.Game_Date < a.Game_Date OR
(b.Game_Date = a.Game_Date AND b.Game_Number <= a.Game_Number))
AND YEAR(b.Game_Date) = YEAR(a.Game_Date)
GROUP BY a.Starting_Pitcher, a.Game_Date, a.Game_Number;
You seem to want to update a column in your table with the result of this calculation. This can be achieved with real-time updates with a trigger which updates the column whenever you insert or update existing data or using a view.
CREATE VIEW starting_pitcher_stats_with_average AS
SELECT
a.Starting_Pitcher, a.full_park_factor,
AVG(b.full_park_factor), a.Game_Date, a.Game_Number
FROM starting_pitcher_stats a
INNER JOIN starting_pitcher_stats b
ON a.Starting_Pitcher = b.Starting_Pitcher
AND (b.Game_Date < a.Game_Date OR
(b.Game_Date = a.Game_Date AND b.Game_Number <= a.Game_Number))
AND YEAR(b.Game_Date) = YEAR(a.Game_Date)
GROUP BY a.Starting_Pitcher, a.Game_Date, a.Game_Number;
In your own answer you create a procedure to update the average column for all records in the table in one go, so perhaps you don't want to have the column update as you insert data, but simply be able to add the average for all rows on demand. In this case, you can write an UPDATE statement which includes the SELECT query above as a subquery. Because MySQL cannot use the same table for the UPDATE and the subquery, you have to wrap the subquery in another SELECT so that MySQL generates a temporary table from your results.
UPDATE starting_pitcher_stats c
SET c.std_F_parkfactor = (
SELECT d.std_F_parkfactor FROM (
SELECT
a.Starting_Pitcher,
AVG(b.full_park_factor) std_F_parkfactor,
a.Game_Date, a.Game_Number
FROM starting_pitcher_stats a
INNER JOIN starting_pitcher_stats b
ON a.Starting_Pitcher = b.Starting_Pitcher
AND (b.Game_Date < a.Game_Date OR
(b.Game_Date = a.Game_Date
AND b.Game_Number <= a.Game_Number))
AND YEAR(b.Game_Date) = YEAR(a.Game_Date)
GROUP BY a.Starting_Pitcher, a.Game_Date, a.Game_Number
) d
WHERE c.Starting_Pitcher = d.Starting_Pitcher
AND c.Game_Date = d.Game_Date
AND c.Game_Number = d.Game_Number
);
UPDATE: Here's a way to store the season-to-date (in-season) park-factor average of a given season in a column, which in this case is the average of another column's values in the same table using a stored procedure. It essentially calculates the average by dividing by the row_number which corresponds to the number of rows of values that have been looped through in calculating this variable. This approach works if you have already-collected data that you want to update in one go or seldomly, but as implied by Matt Raines, may have to be run more frequently than his suggested approach(es). If the table will get updated frequently with data from successive days' games' results at least once daily, I think it will be less labor-intensive to use his approach(es). Please let me know what can be eliminated:
DROP PROCEDURE IF EXISTS std_park_factor_avg;
DELIMITER $$
CREATE PROCEDURE std_park_factor_avg()
BEGIN
DECLARE pit_id CHAR(10);
DECLARE lgID CHAR (2);
DECLARE YEARID INT;
DECLARE gdate DATE;
DECLARE seq INT;
DECLARE F_park_factor INT;
DECLARE RNUMBER INT;
DECLARE accum_F_parkfactor REAL;
DECLARE accum_row_number INT;
DECLARE accum_avg_F_parkfactor REAL;
DECLARE prev_year YEAR(4);
DECLARE end_of_cursor BOOLEAN;
DECLARE no_table CONDITION FOR SQLSTATE '42S02';
DECLARE c1 CURSOR FOR
SELECT Starting_Pitcher, lg_ID, YEAR_ID, Game_Date, Game_Number, full_park_factor, ROW_NUMBER
FROM starting_pitcher_stats
GROUP BY Starting_Pitcher, lg_ID, YEAR_ID, Game_Date, Game_Number;
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET end_of_cursor := TRUE;
SET end_of_cursor := FALSE; -- reset
SET prev_year := 0; -- reset control-break
OPEN c1;
fetch_loop: LOOP
FETCH c1 INTO pit_id, lgID, YEARID, gdate,seq, F_park_factor, RNUMBER;
IF end_of_cursor THEN
LEAVE fetch_loop;
END IF;
-- check control-break conditions
IF YEAR(gdate) != prev_year THEN
SET accum_F_parkfactor := 0.0;
SET RNUMBER:= 1.0;
SET accum_avg_F_parkfactor := 0.0;
SET prev_year := YEAR(gdate);
END IF;
SET accum_F_parkfactor := accum_F_parkfactor + F_park_factor;
SET accum_avg_F_parkfactor := accum_F_parkfactor/RNUMBER;
UPDATE starting_pitcher_stats
SET std_F_parkfactor =accum_avg_F_parkfactor
WHERE Starting_Pitcher = pit_id
AND lg_ID = lgID
AND YEAR_ID = YEARID
AND Game_Date = gdate
AND Game_Number = seq;
END LOOP;
CLOSE c1;
END
$$
DELIMITER ;

Bulk collect and forall with save exception

I have the below code , emp1 table has data of 12 rows in which 2 empno's already present in emp table. i'm trying to save the exceptions for these 2 records and to insert remaining all to emp. But everything is getting error out and i couldn't able to insert into emp. Anyone please help.
SET SERVEROUTPUT ON;
DECLARE
CURSOR C1
IS
SELECT EMPNO FROM EMP1;
TYPE T
IS
TABLE OF C1%ROWTYPE;
L_DATA T;
L_ERRORS_COUNT NUMBER;
EX_DML_ERRORS EXCEPTION;
PRAGMA EXCEPTION_INIT (ex_DML_ERRORS, -47);
L_ERRNO NUMBER;
L_MSG VARCHAR2(4000);
L_IDX NUMBER;
BEGIN
OPEN C1;
LOOP
FETCH C1 BULK COLLECT INTO L_DATA;
BEGIN
FORALL I IN 1..L_DATA.COUNT SAVE EXCEPTIONS
INSERT
INTO EMP
(
EMPNO,
ENAME,
MGR
)
VALUES
(
L_DATA(I).EMPNO,
'SCOTT',
L_DATA(I).EMPNO
);
EXCEPTION
WHEN dup_val_on_index THEN
DBMS_OUTPUT.PUT_LINE('WHD');
L_ERRORS_COUNT := SQL%BULK_EXCEPTIONS.COUNT;
DBMS_OUTPUT.PUT_LINE('WHD::::'||L_ERRORS_COUNT);
FOR J IN 1..L_ERRORS_COUNT
LOOP
L_ERRNO := SQL%BULK_EXCEPTIONS
(
J
)
.ERROR_CODE;
L_MSG := SQLERRM(-L_ERRNO);
L_IDX := SQL%BULK_EXCEPTIONS(J).ERROR_INDEX;
DBMS_OUTPUT.PUT_LINE('I am here SVS:'||L_ERRNO||':'|| L_MSG||':'||L_IDX);
--INSERT INTO EMPS_EXC1(SQLC ,SQLE ,INDX ) VALUES(L_ERRNO, L_MSG,L_IDX);
DBMS_OUTPUT.PUT_LINE('I am here SVS:'||L_ERRNO||':'|| L_MSG||':'||L_IDX);
END LOOP;
END;
EXIT
WHEN C1%NOTFOUND;
END LOOP;
CLOSE C1;
END;

Delphi, Export HTML table to Excel

All I want to do is to implement "Export to excel" option of a classical webbrowser, to Delphi2007 commands...... When I am using this option from a webbrowser to export a 12000 rows table it takes less than a minute to export the table from any web browser from windows. Trying to implement this in Delphi using 2D Array it takes 10 minutes... Trying to implement the export with parsing technique (Stringlists, strings, Pos(tr), pos (td) & some other string functions) it takes a long... Hence, which are the commands of a webbrowser to export an html table to excel that I have to convert them to Delphi? Should I use javascript inside Delphi? Should I use pointers? Should I use HTML entities? xml?...Any ideas? Thank you in advance.
2D ARRAY
Excel:= CreateOleObject('Excel.Application');
ovTable := WebBrowser1.OleObject.Document.all.tags('TABLE').item(0);
arrayn:=VarArrayCreate([1, ovTable.Rows.Length, 1, ovTable.Rows.Item(1).Cells.Length], varvariant);
for i:=0 to (ovTable.Rows.Length - 1) do
begin
for j := 0 to (ovTable.Rows.Item(i).Cells.Length - 1) do
Begin
arrayn[i+1, j+1]:=ovTable.Rows.Item(i).Cells.Item(j).InnerText;
Application.ProcessMessages;
end;end;
WS.range[ws.cells[1, 1], ws.cells[ovTable.Rows.Length, ovTable.Rows.Item(1).Cells.Length]].value:=arrayn;
Excel.WorkBooks[1].SaveAs(directorylistbox1.Directory+'\'+'test.xlsx');
WS := Excel.WorkBooks.close;
Excel.quit;
Excel:=unassigned;
HTML PARSING
function HTMLCleanUp(L : string) : string;
const
CSVTempSeparator = #255; //replaced by a comma
CRLF = #13#10;
var
P1,P2 : integer;
begin
P1 := Pos('<',L); //clean-up anything between <>
while (P1>0) do //WHILE1
begin
P2 := Pos('>',L);
if (P2>0)
then Begin Delete(L,P1,P2-P1+1); end;
P1 := Pos('<',L);
end; //WHILE1
L:=StringReplace(L,' ','-',[rfReplaceAll]);
L:=StringReplace(L,'-01','',[rfReplaceAll]);
L:=StringReplace(L,'-02','',[rfReplaceAll]);
L:=StringReplace(L,'-03','',[rfReplaceAll]);
Result := Trim(L);
end;
function HTMLTableToCSV(HTML,CSV : TStringList) : boolean;
const
CRLF = #13#10;
CSVTempSeparator = #9;
var
P1,P2,P3,P4, p5, P6, p11, p22 : integer;
S,TmpStr,CSVStr : string;
begin
Result := True;
S := Trim(StringReplace(HTML.Text,CRLF,'',[rfReplaceAll]));
P1 := PosEx('<TR',S, 1); //CASE SENSITIVE , TR->FIRST ROW
CSVStr := '';
while (P1>0) do //while1
begin
P2 := PosEx('</TR',S, P1);
if (P2>0) //if1
then begin
TmpStr := Copy(S,P1,P2-P1+1);
//Delete(S,P1,P2-P1+1);
CSVStr := ''; p11:=1;p22:=1;
P11 := PosEx('<TH',TmpStr,1);
while (P11>0) do //while2
begin
P22 := PosEx('</TH',TmpStr, P11);
if (P22>0) //if2
then begin
CSVStr :=
//CSVStr+Trim(Copy(TmpStr,P1+4,P2-P1-4));//+CSVTempSeparator;
CSVStr+Trim(Copy(TmpStr,P11,P22-P11))+CSVTempSeparator;
//Delete(TmpStr,P1,P2-P1+1);
end //if2
else begin
Result := False;
Exit;
end; //if2
P11 := PoseX('<TH',TmpStr, P22);
end; //while2
P11 := PosEx('<TD',TmpStr, 1);
while (P11>0) do //while2
begin
P22 := PosEx('</TD',TmpStr, P11);
if (P22>0) //if2
then begin
CSVStr :=
//CSVStr+Trim(Copy(TmpStr,P1+4,P2-P1-4));//+CSVTempSeparator;
CSVStr+Trim(Copy(TmpStr,P11,P22-P11))+CSVTempSeparator;
//Delete(TmpStr,P1,P2-P1+1);
end //if2
else begin
Result := False;
Exit;
end; //if2
P11 := PosEx('<TD',TmpStr,P22);
end; //while2
end //if1
else begin
Result:=false;
exit;
end; //if1
CSV.Add(HTMLCleanUp(CSVStr));
P1 := PosEx('<TR',S,P2); //CASE SENSITIVE
end; //while1
end;
procedure TForm11.Button1Click(Sender: TObject);
const
xlExcel7 = $00000027;
TmpFileName='c:\test\Test.txt';
VAR
Excel: Olevariant;
HTMLStrList,CSVSTRList : TStringList;
begin
HTMLStrList := TStringList.Create;
try
HTMLStrList.LoadFromFile('C:\test\TestTable1.htm');
CSVSTRList := TStringList.Create;
try
if HTMLTableToCSV(HTMLStrList,CSVSTRList)
then Begin
CSVSTRList.SaveToFile(TmpFileName);
Excel:= CreateOleObject('Excel.Application');
Excel.WorkBooks.opentext(TmpFileName);//OPEN TXT WITH EXCEL
Excel.DisplayAlerts := False;
Excel.WorkBooks[1].SaveAs('c:\test\Nisa.xls', xlExcel7);//SAVE TAB DELIMITED TEXT FILE
Excel.WorkBooks[1].close;
Excel.quit;
Excel:=unassigned;
End
else ShowMessage('Error converting HTML table to CSV');
finally
CSVSTRList.Free;
end;
finally
HTMLStrList.Free;
DeleteFile(TmpFileName);
end;
end;
procedure TForm11.FormCreate(Sender: TObject);
begin
webBrowser1.Navigate('http://samples.msdn.microsoft.com/workshop/samples/author/tables/HTML_ Table.htm');
end;
procedure TForm11.WebBrowser1DocumentComplete(ASender: TObject;
const pDisp: IDispatch; var URL: OleVariant);
var
Document: IHtmlDocument2;
CurWebrowser : IWebBrowser;
TopWebBrowser: IWebBrowser;
WindowName : string;
begin
CurWebrowser := pDisp as IWebBrowser;
TopWebBrowser := (ASender as TWebBrowser).DefaultInterface;
if CurWebrowser=TopWebBrowser then
begin
document := webbrowser1.document as IHtmlDocument2;
memo3.lines.add(trim(document.body.innerhtml)); // to get html
ShowMessage('Document is complete.')
end;
end;
end.
I found the solution...HTML Table Parsing in Less than a second!
function HTMLCleanUp(L : string) : string;
var
P1,P2 : integer;
begin
P1 := Pos('<',L); //clean-up anything between <>
while (P1>0) do //WHILE1
begin
P2 := Pos('>',L);
if (P2>0)
then Begin Delete(L,P1,P2-P1+1); end;
P1 := Pos('<',L);
end; //WHILE1
L:=StringReplace(L,' ','-',[rfReplaceAll]);
Result := Trim(L);
end;
procedure TForm11.WB_SaveAs_HTML(WB : TWebBrowser; const FileName : string) ;
var
PersistStream: IPersistStreamInit;
Stream: IStream;
FileStream: TFileStream;
begin
if not Assigned(WB.Document) then
begin
ShowMessage('Document not loaded!') ;
Exit;
end;
PersistStream := WB.Document as IPersistStreamInit;
FileStream := TFileStream.Create(FileName, fmCreate) ;
try
Stream := TStreamAdapter.Create(FileStream, soReference) as IStream;
if Failed(PersistStream.Save(Stream, True)) then ShowMessage('SaveAs HTML fail!') ;
finally
FileStream.Free;
end;
end; (* WB_SaveAs_HTML *)
procedure TForm11.Button1Click(Sender: TObject);
const
xlExcel7 = $00000027;
TmpFileName='c:\test\xxxx.txt';
CRLF = #13#10;
CSVTempSeparator = #9; //#255; //replaced by a comma
ADPNEWHOTURL = 'http://samples.msdn.microsoft.com/workshop/samples/author/tables/HTML_Table.htm';
VAR
Excel, WS: Olevariant;
P1,P2,P3,P4, p5, P6, p11, p22 : integer;
i, j: Integer;
buffer,rawHTM,TmpStr,CSVStr:string;
HTMFile : TextFile;
CSVSTRList : TStringList;
begin
CSVSTRList := TStringList.Create;
WB_SaveAs_HTML(WebBrowser1,TmpFileName) ;
AssignFile(HTMFile, TmpFileName);//read the HTML file
Reset(HTMFile);
while not EOF(HTMFile) do begin
ReadLn(HTMFile, buffer);
rawHTM := Concat(rawHTM, buffer);
end;
i:=1;j:=1;
rawHTM := Trim(StringReplace(rawHTM,CRLF,'',[rfReplaceAll]));
P1 := PosEx('<TR',rawHTM, 1); //CASE SENSITIVE , TR->FIRST ROW
while (P1>0) do //while1
begin
P2 := PosEx('</TR',rawHTM, P1);
if (P2>0) //if1
then begin
TmpStr := Copy(rawHTM,P1,P2-P1+1);
CSVStr := '';p11:=1;p22:=1;
P11 := PosEx('<TH',TmpStr,1);
while (P11>0) do //while2
begin
P22 := PosEx('</TH',TmpStr, P11);
if (P22>0) //if2
then begin
CSVStr :=CSVStr+
HTMLCleanUp(Trim(Copy(TmpStr,P11,P22-P11)))+CSVTempSeparator; j:=j+1;
end //if2
else begin
Exit;
end; //if2
P11 := PoseX('<TH',TmpStr, P22);
end; //while2
P11 := PosEx('<TD',TmpStr, 1);
while (P11>0) do //while2
begin
P22 := PosEx('</TD',TmpStr, P11);
if (P22>0) //if2
then begin
CSVStr :=CSVStr+
HTMLCleanUp(Trim(Copy(TmpStr,P11,P22-P11)))+CSVTempSeparator; j:=j+1;
end //if2
else begin
Exit;
end; //if2
P11 := PosEx('<TD',TmpStr,P22);
end; //while2
end //if1
else begin
exit;
end; //if1
CSVSTRList.Add(CSVStr);
P1 := PosEx('<TR',rawHTM,P2); i:=i+1; j:=1; //CASE SENSITIVE
end; //while1
CSVSTRList.SaveToFile('c:\test\xxx2.txt');
Excel:= CreateOleObject('Excel.Application');
Excel.WorkBooks.opentext('c:\test\xxx2.txt');//OPEN TXT WITH EXCEL
Excel.visible := True;
CloseFile(HTMFile);
DeleteFile(TmpFileName);
end;