2016년 7월 6일 수요일

MySQL에서 URL Decoding 하는 SQL Stored Procedure.

MySQL에서 URL Decoding 하는 SQL Stored Procedure.

데이터 입력을 encode된걸 넣어서 - 게다가 중간중간 깨진데이터들이나 URL일부가 그대로 들어가있는 경우도 있었고 (물론 매우 소수 일부가 그러했다.)아무튼 그런 이유로 어쩔 수 없이 검증하는 쿼리가 필요했다. (등떠밀려 만듦ㅎ)

아래는 최초 적용한 함수이다.
근데.. 이게 영 이상하게 동작한다. 실패작이다.
(그냥 된다카길래 가져다 썼는데 이거 원;)

  1. DELIMITER $$  
  2.   
  3. DROP FUNCTION IF EXISTS `url_decode` $$  
  4. CREATE DEFINER=`root`@`%` FUNCTION `url_decode`(original_text TEXT) RETURNS TEXT CHARSET utf8  
  5. BEGIN  
  6.     DECLARE new_text TEXT DEFAULT NULL;  
  7.     DECLARE pointer INT DEFAULT 1;  
  8.     DECLARE end_pointer INT DEFAULT 1;  
  9.     DECLARE encoded_text TEXT DEFAULT NULL;  
  10.     DECLARE result_text TEXT DEFAULT NULL;
  11.     DECLARE EXIT HANDLER FOR SQLEXCEPTION
  12.     BEGIN
  13.         return NULL;
  14.     END;

  15.     SET new_text = REPLACE(original_text,'+',' ');  
  16.     SET new_text = REPLACE(new_text,'%0A','\r\n');  
  17.    
  18.     SET pointer = LOCATE("%", new_text);  
  19.     while pointer <> 0 && pointer < (CHAR_LENGTH(new_text) - 2) DO  
  20.         SET end_pointer = pointer + 3;  
  21.         while MID(new_text, end_pointer, 1) = "%" DO  
  22.             SET end_pointer = end_pointer+3;  
  23.         END while;  
  24.    
  25.         SET encoded_text = MID(new_text, pointer, end_pointer - pointer);  
  26.         SET result_text = CONVERT(UNHEX(REPLACE(encoded_text, "%""")) USING utf8);  
  27.         SET new_text = REPLACE(new_text, encoded_text, result_text);  
  28.         SET pointer = LOCATE("%", new_text, pointer + CHAR_LENGTH(result_text));  
  29.     END while;  
  30.    
  31.     return new_text;  
  32.   
  33. END $$  
  34.   
  35. DELIMITER ;


그래서 다른 것을 찾아보았다.
그래서 아래와 같은 함수를 발견하게되었고 이번엔 꼼꼼하게 소스를 다 훝어보았다.
먼저 소스보다 훨씬 더 가독성이 좋았고 편리하게 작성되어있어 수정도 편했다.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
DROP FUNCTION IF EXISTS urldecode;

DELIMITER |

CREATE FUNCTION urldecode (s VARCHAR(4096)) RETURNS VARCHAR(4096)
DETERMINISTIC 
CONTAINS SQL 
BEGIN
       DECLARE c VARCHAR(4096) DEFAULT '';
       DECLARE pointer INT DEFAULT 1;
       DECLARE s2 VARCHAR(4096) DEFAULT '';
       DECLARE h3 VARCHAR(4096) DEFAULT '';
       DECLARE CONTINUE handler FOR 1366
       BEGIN
       END;

       IF ISNULL(s) THEN
          RETURN NULL;
       ELSE
       SET s2 = '';
       WHILE pointer <= LENGTH(s) DO
          SET c = SUBSTR(s,pointer,1);
          IF c = '+' THEN
             SET h3 = '20';
          ELSEIF c = '%' AND pointer + 2 <= LENGTH(s) THEN
                   SET h3 = UPPER(SUBSTR(s,pointer+1,2));
                   SET pointer = pointer + 2;
          ELSE
                   SET h3 = HEX(c);
          END IF;
          SET s2 = CONCAT(s2,h3);
          SET pointer = pointer + 1;
       END while;
       END IF;
       RETURN UNHEX(s2);
END;

|

DELIMITER ;

헌데, 이넘도 문제가 있다.

encode data가 깨진 경우, 마지막 RETURN UNHEX(s2); 에서 1366 오류가 난다.
이해가 가지 않는다; ㅠㅠ;;;;;;;;;;;;;;;;

일단 작업에 방해가 되면 안되니, 위 소스처럼
DECLARE CONTINUE handler FOR 1366
BEGIN
END;
로서 땜빵.

문제의 진짜 이유를 찾기 위해 테스트해 보았다.

결국, 수십여분 삽질끝에.. 이상한것을 발견했다. 이유는 모른다. 

RETURN UNHEX(s2); #1366 ERROR 발생
위 부분을 
RETURN s2;

위와 같이 UNHEX 배제 후 함수 호출부분에서 UNHEX하니 

SELECT urldecode('%ED%81%AC%EBCsn%3D3%7Chk%3Dbbcac20f524e408ffbd748bce750e921a2aca717'); #1366 ERROR 발생 

SELECT UNHEX(urldecode('%ED%81%AC%EBCsn%3D3%7Chk%3Dbbcac20f524e408ffbd748bce750e921a2aca717'));


결과가 나왔다. 응?! 왜지?!
return되기직전에 unhex를 사용하면 안되고 반환반고나서 unhex를 쓰면된다?!

SQL 잘하는 사람한테 물어봐야할라나..?

아는사람은 좀 알려주세요~~~~ ㅠㅠ





아무튼 이 상황에 대해 공유하려 했으나,
데이터 넣은 사람은 제대로 듣지도 않고 그냥 됐단다.

"더 파지말아라"는 압박이 느껴졌다. 뭘 더 따지냐는 시선... 흠..

괜한분쟁으로 에너지낭비 > 모르는 것에 대한 궁금함

순간 머리속에 떠오른 공식. ㅎㅎ

근데,
프로그래머로서 뭔가 이상동작하면 궁금해지지 않나?
왜 그럴까? 오류는 왜 날까? 하는 궁금증은 어디 갔을까?
바빠서? 그렇겠지? 급히 해결해야할 일이 있어서 바빴겠지?
이상현상에 대한 궁금증이 없다는 것은 아니겠지?

한국 프로그래머들은 항상 기한에 들볶이니..
그렇게 믿자. 포지티브 포지티브..


내가 DBA가 아니라서 SQL을 잘 모른다.

물론 JAVA 전문 개발자들은 대부분 말하길, "프로그래머가 SQL을 모른다는게 말이되나?" 라고들 하더라. 근데 주로 C/C++로서 개발하던 사람들은 SQL 잘 모르는 사람 많다.

왜냐,
C 전문 개발자들은 파일처리나 네트워크 프로그래밍을 더 많이 하다보니,
DB를 직접 만드는 경우는 있어도 RDBMS를 다루는 경우는 매우 드물기 때문이다.

본인도 RDBMS를 다룬거보다, NoSQL DB를 직접 만들어 사용한 것이 더 많다.
여기서 잘 모른다는건 간단한 INSERT나 UPDATE등을 모른다는게 아니라, STORED PROCEDURE같은걸 만든다거나 전문적인 튜닝? 같은걸 모른다는 말이지 레코드삽입이나 조회도 못한다는건 아니다; 

국내 개발환경상 SQL을 기본으로 숙지해야하는 JAVA 전문 개발자들에겐,
의아하게 보일지도 모른다.

이런 내입장에선 SQL을 잘하는 사람의 등엔 아우라가 보인다. 멋져보인다.
아, 사실, SQL뿐만이 아니다.

포토샵 잘쓰는 사람, 앱 만드는 사람, 네트워킹에 정통한 사람, 보안 및 해킹기술에 해박한 사람, 춤 잘추는 사람, 케잌 만드는 사람 등등 세상엔 멋진 사람으로 넘쳐난다. ㅠㅠ

근데 요즘 대한민국 IT업계엔 이상한 흐름을 느낀다.
전부 남들이 만들어 놓은 오픈소스를 가져다쓰는데 익숙해져있고
 스스로 개발은 뒷전이다.

그나마도 직접 개발을 한다하면
"니가 뭔재주로?"
"왜 개고생을하냐? 다 만들어진게 있는데?"
"뻘짓도 풍년이다ㅋㅋ"
라며 핀잔주기 바쁘다.

더군다나 이 핀잔은 같은 프로그래머들 입에서 나오는 말이다. (지저스~)

대한민국 개발환경이 지랄인 이유가 문제이겠지만, 그래도 안타까운건 어쩔 수 없다.

오픈소스를 잘 가져다 쓰는 사람 역시 전문가이다.
내 말은 이러한 사람들이 전문지식인이 아니란 것이 아니다.
다만 너무 편중되어있다는 것이다.

뭐 내주변은 안그런데? 라고들 할지 모르겠지만,
적어도 내 주변이 그렇게 변해가고 있다는 말이다. ㅎㅎ


아무튼 격세지감인지, 프로그래머의 모습이 예전에 비해 많이 변한 듯 하다.
"수학을 왜해요? 그건 데이터 사이언티스트가 하는거에요. ㅎㅎㅎ"
이 말이 왜이렇게 낯설게 느껴질까....?

내가 너무 늙었나보다. ㅠㅠ

수년전만해도 개발자는 기본으로 수학을 알아야 한다고들 말하지 않았나?

알고리즘 이해가 안가서 전공도 아닌 수학을 이해하기 위해 수학정석 펴놓고
미친듯이 읽고 또 읽었던 내 지난날들..
외우는걸 너무 못하던 내 특성상, 나이 서른이 넘어서야 외울수 있었던 구구단.
더불어 싫어졌던 수학. 그 수학을 이렇게 원하게 될 줄은 미처 몰랐다.

정말 알고싶은 코어를 이해하기 위해서는 반드시 필요한 것이 수학이기에
어쩔수없이 파고들었던 수학이었다.

남들이 만들어놓은 코드만으로 살아가기 싫었던 프로그래머로서의 자존심.
그 자존심이 날 삼각함수로 안내했고 통계학으로 이끌었다.

하지만 분위기 거스르기 싫어 나도 한마디 거들었다.


"글쵸~ 개발자가 수학이라니~ 웃겨증말~ 알리가 있나요? 하하하하~ "

.
.
.

그래도 지구는 돈다.


.



댓글 없음:

댓글 쓰기