sql schema/parser generator explained

definitions

why?

problems with db

and there's more profitable points

features

how it works

	sql_schema_xml => (sql schema/parser generator) => GEN_sql_schema.sql
	sql_schema_xml => (sql schema/parser generator) => GEN_db.h
	sql_schema_xml => (sql schema/parser generator) => _intemediate_ => (proto parser generator) => protocol parser for c++/c#
	

example codes

* beblow codes cut and paste from production codes so logic not fit with only theses files.

INPUT SOURCE

sql_schema_xml

<xml>	
	<!-- --------------------------------------------------------------------------- -->
	<!-- config -->
	<!-- --------------------------------------------------------------------------- -->
	<config>
		<db name="bb_system" version="32"/> <!-- increment version if backward compatibility broken -->
		<timezone db="9" local="0"/>
		<output type="cpp" code="SystemDB.generated.h"/>
		<output type="packetXML" code="SystemDB.generated.xml" param1="MS" param2="DB"/>
		<output type="MySQL" code="SystemDB_MySQL.generated.sql" param1="SystemDB_SP_MySQL.generated.sql"/>
		<drop table="true" sp="true"/>
		<!-- disable testdata -->
		<rawcode_disable tag="testdata"/>
		<select default_max_size="128"/> 
	</config>


	<!-- --------------------------------------------------------------------------- -->
	<!-- ERROR CODE -->
	<!-- --------------------------------------------------------------------------- -->
    <error>
        <code value="0" name="SUCCESS" comment="success"/>
        <code value="1" name="ERR_GENERAL" comment="error"/>
        <code value="2" name="ERR_NOT_IMPLEMENTED" comment="not implemented"/>
        <code value="3" name="ERR_SESSION_SERVER" comment="session error"/>
        <code value="4" name="ERR_HAS_PENDING_REQUEST" comment="client should wait until last response receive"/>

        <code value="100" name="ERR_ALREADY_LOGGED_IN" comment="already logged in"/>
        <code value="101" name="ERR_WRONG_VERSION" comment="wrong version"/>
        <code value="102" name="ERR_FORCE_DISCONNECT_INACTIVE_ACCOUNT" comment="disconnect inactive account, try to logged in again"/>
        <code value="103" name="ERR_SESSION_NOT_FOUND" comment="ERR_SESSION_NOT_FOUND"/>

        <code value="200" name="ERR_WRONG_PARAMETER_ACCT_NAME" comment="wrong parameter"/>        
        <code value="201" name="ERR_WRONG_PARAMETER_1" comment="wrong parameter: 1st"/>
        <code value="202" name="ERR_WRONG_PARAMETER_2" comment="wrong parameter: 2nd"/>
        <code value="203" name="ERR_WRONG_PARAMETER_3" comment="wrong parameter: 3rd"/>
        ...
    </error>


	<!------------------------------------------------------------------------------->
	<!-- static system schema
	<!------------------------------------------------------------------------------->
 	<!-- static_acct_info -->
	<table name="static_acct_info" select_max_size="128" primary_key="acct_level">
		<uint32 name="acct_level" key="true" table_index="true"/>
		<uint32 name="max_ap"/>
		<uint32 name="exp_to_lvup"/>
		<uint32 name="total_exp_to_lvup"/>
		<postfix_rawcode type="MySQL" tag="data" import_csv="../DB_data/static_acct_info.csv"/>
	</table>

	<!-- static_char_info -->
	<table name="static_char_info" select_max_size="128" primary_key="char_index,char_level">
		<uint32 name="char_index" key="true"/>
		<uint32 name="char_level" key="true"/>
		<uint32 name="exp_to_lvup"/>
		<uint32 name="total_exp_to_lvup"/>
		<uint32 name="char_att"/>
		<uint32 name="char_def"/>
		<uint32 name="char_health"/>
		<uint32 name="char_ai"/>
		<uint32 name="char_attr_train_time" array_size="4" array_name_format="%s_%01d" comment="att,def,health,ai"/>
		<uint32 name="max_attr_point" comment="max attr points"/>
		<uint32 name="attr_train_gold_cost"/>
		<uint32 name="max_spec_point"/>
		<postfix_rawcode type="MySQL" tag="data" import_csv="../DB_data/static_char_info.csv"/>
	</table>
	<generate_import_sp from="static_char_info" index="char_index,char_level" select_max_size="32"/>

   	<!-- static_monster -->
	<table name="static_monster" select_max_size="128" primary_key="monster_index">
		<uint32 name="monster_index" key="true"/>
		<astring max_size="50" name="monster_code" key="true" table_index="true"/>
		<astring max_size="50" name="monster_name"/>
		<astring max_size="50" name="reward_code"/>
		<uint32 name="monster_grade" comment="몬스터 등급" default="0"/>
		<uint32 name="monster_gold_min"/>
		<uint32 name="monster_gold_max"/>
		<uint32 name="monster_exp"/>
		<uint32 name="Monster_Lv"/>
		<astring max_size="50" name="Attack_Type"/>
		<uint32 name="Item_MinDam"/>
		<uint32 name="Item_MaxDam"/>
		<uint32 name="Item_Att"/>
		<uint32 name="Item_Def"/>
		<uint32 name="Item_Health"/>
		<float name="Dam_Slash"/>
		<float name="Dam_Crash"/>
		<float name="Dam_Pierce"/>
		<uint32 name="Item_Pen"/>
		<float name="Item_PenPer"/>
		<float name="Item_CriPer"/>
		<float name="Item_CriRat"/>
		<uint32 name="Item_TrueDam"/>
		<astring max_size="50" name="TagRule"/>
		<postfix_rawcode type="MySQL" tag="data" import_csv="../DB_data/static_monster.csv"/>
	</table>
	<generate_import_sp from="static_monster" index="monster_index" select_max_size="32"/>

 	<!-- static_mission -->
	<table name="static_mission" select_max_size="128" primary_key="mission_index">
		<uint32 name="mission_index" key="true" table_index="true" />
		<astring max_size="50" name="mission_code" key="true"/>
		<astring max_size="50" name="mission_name"/>
		<uint32 name="ap_cost" comment="ap 소모"/>
		<uint32 name="mission_group" comment="미션 그룹" key="true"/>
		<astring max_size="50" name="boss_monster_code"/>
		<uint32 name="opt_monster_count" comment="잡몹 숫자"/>
		<astring max_size="50" name="opt_monster_code" default="0" array_size="10" array_name_format="%s_%01d" comment="잡몹 코드"/>
		<astring max_size="50" name="reward_code_if_cleard_1st" commnet="첫 클리어시 보상"/>

		<uint32 name="drop_item_index" array_size="5" array_name_format="%s_%01d" default="0" comment="추가 데이터: 드랍 아이템 Index 리스트"/>

		<postfix_rawcode type="MySQL" tag="data" import_csv="../DB_data/static_mission.csv"/>
	</table>
	<generate_import_sp from="static_mission" index="mission_index" select_max_size="32"/>

 	<!-- static_item -->
	<table name="static_item" select_max_size="128" primary_key="item_index">
 		<uint32 name="item_index" key="true" table_index="true"/>
		<astring max_size="50" name="code" key="true" comment="아이템 코드"/>
		<astring max_size="50" name="name" comment="아이템 이름"/>
		<uint32 name="item_tier" default="0" comment="아이템 아레나 티어"/>
		<uint32 name="grade" default="0" comment="아이템 등급. 1:Normal 2:Uncommon ... 5: legend"/>
		<uint32 name="max_stack" default="1" comment="아이템 최대 스택 수"/>
		<uint32 name="max_level" default="10" comment="최대 레벨"/>
		<astring max_size="50" name="item_desc" default="N/A" comment="아이템 설명"/>
		<uint32 name="slot" default="255" comment="아이템 장착 부위 0:skin ... 1:weapon, 88: skill_dummy 99: skill, 255:other"/>
		<uint32 name="evolvable_item_index" default="0" comment=" 진화 가능하면 진화 가능한 아이템 Index, 0이면 불가능"/>
		<uint32 name="equippable_char_index" default="0" comment=" 장착 가능한 캐릭터 인덱스, 0이면 아무나 "/>
		<uint32 name="base_sell_price" default="0"/>
		<astring max_size="50" name="reward_code_on_use" default="0"/>
		<uint32 name="expire_in_hours" default="0" comment="0; 무제한, 주의: stackable 아이템에 기한제한을 넣으면 좇된다"/>
		<postfix_rawcode type="MySQL" tag="data" import_csv="../DB_data/static_item.csv"/>
	</table>
	<generate_import_sp from="static_item" index="item_index" select_max_size="32"/>

	<!-- static_reward -->
	<table name="static_reward" select_max_size="128" primary_key="reward_index">
		<uint32 name="reward_index" auto_increment="1" key="true" />
		<astring max_size="50" name="reward_code" key="true" table_index="true"/>
		<astring max_size="50" name="expr_gold" default="0"/>
		<astring max_size="50" name="expr_ruby" default="0"/>
		<astring max_size="50" name="expr_honor" default="0"/>
		<astring max_size="50" name="expr_exp" default="0"/>
		<astring max_size="50" name="expr_ap" default="0"/>
		<astring max_size="50" name="expr_item" default="0" array_size="20" array_name_format="%s_%01d"/>
		<postfix_rawcode type="MySQL" tag="data" import_csv="../DB_data/static_reward.csv"/>
	</table>
	<generate_import_sp from="static_reward" index="reward_index" select_max_size="32"/>

	<!-- --------------------------------------------------------------------------- -->
	<!-- __TTTTTTT__BBBBB___L_______________________________________________________ -->
	<!-- _____T_____B____B__L_______________________________________________________ -->
	<!-- _____T_____BBBBB___L_______________________________________________________ -->
	<!-- _____T_____B____B__L_______________________________________________________ -->
	<!-- _____T_____BBBBB___LLLLLL__________________________________________________ -->
	<!-- --------------------------------------------------------------------------- -->

	<table name="tbl_account" primary_key="acct_id">
		<uint64 name="acct_id" auto_increment="10000" comment="계정 Unique no"/>
		<uint64 name="acct_id_external" key="true"/>
		<astring max_size="50" name="acct_name" key="true" />
		<astring max_size="50" name="nickname" />
		<timestamp name="creation_time" default_current_time="true" />

		<postfix_rawcode type="MySQL">
		-- you can add any code here after 'create table'
		</postfix_rawcode>

		<postfix_rawcode type="MySQL" tag="testdata">
		-- ----------------------------
		-- Records of tbl_account
		-- ----------------------------
		insert into `tbl_account` values ('100', '100', 'icedac', '아이스닥', DEFAULT );
		insert into `tbl_account` values ('101', '101', 'deepfry', '딥후라이', DEFAULT );			
		</postfix_rawcode>
	</table>
	<copy name="client_account" comment="client copy_from">
		<uint64 name="acct_id" auto_increment="10000" comment="계정 Unique no"/>
		<uint64 name="acct_id_external" key="true"/>
		<astring max_size="50" name="acct_name" key="true" />
		<astring max_size="50" name="nickname" />
		<timestamp name="creation_time" default_current_time="true" />
	</copy>

	<table name="tbl_account_game" primary_key="acct_id"> 
		<uint64 name="acct_id" foreign_key="acct_id" source_table="tbl_account"/>
		<uint32 name="acct_level" default="1" />
		<uint32 name="acct_exp" default="0" />
		<uint64 name="curr_char_id" default="0"/>
		<uint32 name="gold"/>
		<uint32 name="ruby"/>
		<uint32 name="max_ap" default="71" comment="최대 행동력" />
		<timestamp name="time_to_max_ap" comment="ap가 최대치가 될 시간" default_current_time="true" />
		<uint32 name="ap_cool_time" comment='ap 쿨타임(1차는데 걸리는 초)' default="360" />
		<timestamp name="last_logged_in" null="true"/>
		<uint32 name="max_inventory_count" default="500" />
		<uint32 name="last_processed_system_mail_id" default="0"/>
		<timestamp name="time_to_free_product" null="true" array_size="10" array_name_format="%s_%01d" default="0"/>
		<uint32 name="max_box_inventory_count" default="4" comment=""/>
	</table>
 
        ...

	<!-- --------------------------------------------------------------------------- -->
	<!-- __SSSS___PPPP______________________________________________________________ -->
	<!-- _S_______P___P_____________________________________________________________ -->
	<!-- __SSSS___PPPP______________________________________________________________ -->
	<!-- ______S__P_________________________________________________________________ -->
	<!-- __SSSS___P_________________________________________________________________ -->
	<!-- --------------------------------------------------------------------------- -->

	<!-- SP: sp_get_account_box -->
	<sp name="sp_get_account_box">
		<in>
			<uint64 name="acct_id" /> 
		</in>
		<out>
			<uint32 name="result"/>
		</out>
		<result_set max_size="1">
			<!-- tbl_account -->
			<uint64 name="acct_id" foreign_key="acct_id" source_table="tbl_account" comment="계정 Unique no"/>
			<uint32 name="box_type" array_size="10" array_name_format="%s_%01d" default="0" comment="0; no box. 1:silver 2:gold 3: magic 4:giant 5:legend"/>
			<uint32 name="box_arena_tier" array_size="10" array_name_format="%s_%01d" default="0; no box, 1-9"/>			
			<timestamp name="time_to_unlock" array_size="10" array_name_format="%s_%01d" comment="box가 언락되는 시간; 0; locked" default="0000-00-00 00:00:00"/>
		</result_set>
		<sql type="MySQL">
	CALL fn_check_account( acct_id, result ); IF ( result != 0 ) THEN SELECT 0 LIMIT 0; LEAVE fin; END IF;
	-- CALL fn_check_character( char_id, result ); IF ( result != 0 ) THEN SELECT 0 LIMIT 0; LEAVE fin; END IF;

	SELECT AB.*
		FROM tbl_account_box AS AB
		WHERE AB.acct_id = acct_id;

	SET result = 0;
		</sql>
	</sp>

	<!-- SP: sp_account_login     -->
	<sp name="sp_account_login" comment="last_logged_in을 업데이트">
		<in>
			<astring max_size="50" name="acct_name" />
			<astring max_size="50" name="ip_address" default="0.0.0.0"/>
			<uint32 name="port" default="0"/>
		</in>
		<out>
			<uint32 name="result"/>
		</out>
		<sql type="MySQL">
	CALL fn_check_account( acct_id, result ); IF ( result != 0 ) THEN LEAVE fin; END IF;
	-- CALL fn_check_character( char_id, result ); IF ( result != 0 ) THEN LEAVE fin; END IF;
	
	UPDATE tbl_account_game
		SET last_logged_in = NOW()
		WHERE tbl_account_game.acct_id = @acct_id;

	INSERT INTO `tbl_log_account_login`(
		`acct_id`, `acct_name`, `ip_address`, `port` )
		VALUES (
			@acct_id, acct_name, ip_address, port
		);

	SET result = 0;
		</sql>
	</sp>
    

</xml>

OUTPUT GENERATED CODES

GEN_sql_schema.sql

-- generated by SQL COMPILER
-- time : 2018-07-11 13:08:59.179
-- do not modify
-- contact: icedac@gmail.com

USE bb_game;

SET FOREIGN_KEY_CHECKS = 0;

-- ****************************************************************************
-- *
-- * BEGIN RAWCODE
-- */

DROP EVENT IF EXISTS `ev_on_daily_rank`;
CREATE EVENT `ev_on_daily_rank`
	ON SCHEDULE
		EVERY 10 MINUTE STARTS '2000-01-01 05:00:00'
	ON COMPLETION PRESERVE
	ENABLE
	COMMENT ''
	DO call sp_balance_arena_rank(@r);	
	

-- ****************************************************************************
-- *
-- *	table: tbl_account
-- */
DROP TABLE IF EXISTS `tbl_account`;
CREATE TABLE `tbl_account`(
	`acct_id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '계정 Unique no'
,	`acct_id_external` bigint UNSIGNED NOT NULL
,	KEY (`acct_id_external`)
,	`acct_name` varchar(50) NOT NULL
,	KEY (`acct_name`)
,	`nickname` varchar(50) NOT NULL
,	`creation_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
,	PRIMARY KEY (`acct_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT = 10000;

		-- you can add any code here after 'create table'
		

-- ****************************************************************************
-- *
-- *	table: tbl_account_game
-- */
DROP TABLE IF EXISTS `tbl_account_game`;
CREATE TABLE `tbl_account_game`(
	`acct_id` bigint UNSIGNED NOT NULL
,	KEY `FK__tbl_account_game_acct_id` (`acct_id`)
,	CONSTRAINT `FK__tbl_account_game_acct_id` FOREIGN KEY (`acct_id`) REFERENCES `tbl_account` (`acct_id`)
,	`acct_level` int UNSIGNED NOT NULL DEFAULT '1'
,	`acct_exp` int UNSIGNED NOT NULL DEFAULT '0'
,	`curr_char_id` bigint UNSIGNED NOT NULL DEFAULT '0'
,	`gold` int UNSIGNED NOT NULL
,	`ruby` int UNSIGNED NOT NULL
,	`max_ap` int UNSIGNED NOT NULL DEFAULT '71' COMMENT '최대 행동력'
,	`time_to_max_ap` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'ap가 최대치가 될 시간'
,	`ap_cool_time` int UNSIGNED NOT NULL DEFAULT '360' COMMENT 'ap 쿨타임(1차는데 걸리는 초)'
,	`last_logged_in` timestamp
,	`max_inventory_count` int UNSIGNED NOT NULL DEFAULT '500'
,	`last_processed_system_mail_id` int UNSIGNED NOT NULL DEFAULT '0'
,	`time_to_free_product_0` timestamp DEFAULT '0'
,	`time_to_free_product_1` timestamp DEFAULT '0'
,	`time_to_free_product_2` timestamp DEFAULT '0'
,	`time_to_free_product_3` timestamp DEFAULT '0'
,	`time_to_free_product_4` timestamp DEFAULT '0'
,	`time_to_free_product_5` timestamp DEFAULT '0'
,	`time_to_free_product_6` timestamp DEFAULT '0'
,	`time_to_free_product_7` timestamp DEFAULT '0'
,	`time_to_free_product_8` timestamp DEFAULT '0'
,	`time_to_free_product_9` timestamp DEFAULT '0'
,	`max_box_inventory_count` int UNSIGNED NOT NULL DEFAULT '4'
,	PRIMARY KEY (`acct_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


-- ****************************************************************************
-- *
-- *	table: tbl_character
-- */
DROP TABLE IF EXISTS `tbl_character`;
CREATE TABLE `tbl_character`(
	`acct_id` bigint UNSIGNED NOT NULL
,	KEY `FK__tbl_character_acct_id` (`acct_id`)
,	CONSTRAINT `FK__tbl_character_acct_id` FOREIGN KEY (`acct_id`) REFERENCES `tbl_account` (`acct_id`)
,	`char_id` bigint UNSIGNED NOT NULL AUTO_INCREMENT
,	KEY (`char_id`)
,	`char_index` int UNSIGNED NOT NULL DEFAULT '0'
,	`char_level` int UNSIGNED NOT NULL DEFAULT '1'
,	`char_exp` int UNSIGNED NOT NULL DEFAULT '0'
,	`char_attr_pt_0` int UNSIGNED NOT NULL DEFAULT '1' COMMENT '0:att,def,health,ai'
,	`char_attr_pt_1` int UNSIGNED NOT NULL DEFAULT '1' COMMENT '0:att,def,health,ai'
,	`char_attr_pt_2` int UNSIGNED NOT NULL DEFAULT '1' COMMENT '0:att,def,health,ai'
,	`char_attr_pt_3` int UNSIGNED NOT NULL DEFAULT '1' COMMENT '0:att,def,health,ai'
,	`char_spec` varchar(20) NOT NULL COMMENT 'sepc string: 010021304201102'
,	`slot_item_id_0` bigint UNSIGNED NOT NULL DEFAULT '0' COMMENT '0: char_skin 1:weapon'
,	`slot_item_id_1` bigint UNSIGNED NOT NULL DEFAULT '0' COMMENT '0: char_skin 1:weapon'
,	`slot_item_id_2` bigint UNSIGNED NOT NULL DEFAULT '0' COMMENT '0: char_skin 1:weapon'
,	`slot_item_id_3` bigint UNSIGNED NOT NULL DEFAULT '0' COMMENT '0: char_skin 1:weapon'
,	`slot_item_id_4` bigint UNSIGNED NOT NULL DEFAULT '0' COMMENT '0: char_skin 1:weapon'
,	`slot_item_id_5` bigint UNSIGNED NOT NULL DEFAULT '0' COMMENT '0: char_skin 1:weapon'
,	`slot_item_id_6` bigint UNSIGNED NOT NULL DEFAULT '0' COMMENT '0: char_skin 1:weapon'
,	`slot_item_id_7` bigint UNSIGNED NOT NULL DEFAULT '0' COMMENT '0: char_skin 1:weapon'
,	`slot_item_id_8` bigint UNSIGNED NOT NULL DEFAULT '0' COMMENT '0: char_skin 1:weapon'
,	`slot_item_id_9` bigint UNSIGNED NOT NULL DEFAULT '0' COMMENT '0: char_skin 1:weapon'
,	`slot_item_skill_id_0` bigint UNSIGNED NOT NULL DEFAULT '0'
,	`slot_item_skill_id_1` bigint UNSIGNED NOT NULL DEFAULT '0'
,	`slot_item_skill_id_2` bigint UNSIGNED NOT NULL DEFAULT '0'
,	`slot_item_skill_id_3` bigint UNSIGNED NOT NULL DEFAULT '0'
,	`slot_item_skill_id_4` bigint UNSIGNED NOT NULL DEFAULT '0'
,	`slot_item_skill_id_5` bigint UNSIGNED NOT NULL DEFAULT '0'
,	`slot_item_skill_id_6` bigint UNSIGNED NOT NULL DEFAULT '0'
,	`slot_item_skill_id_7` bigint UNSIGNED NOT NULL DEFAULT '0'
,	`slot_item_skill_id_8` bigint UNSIGNED NOT NULL DEFAULT '0'
,	`slot_item_skill_id_9` bigint UNSIGNED NOT NULL DEFAULT '0'
,	PRIMARY KEY (`char_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT = 20000;

-- ****************************************************************************
-- *
-- *	stored procedure: sp_account_login
-- */
DROP PROCEDURE IF EXISTS `sp_account_login`;
DELIMITER //
CREATE PROCEDURE `sp_account_login`(
	IN `acct_name` varchar(50)
,	IN `ip_address` varchar(50)
,	IN `port` int UNSIGNED
,	OUT `result` int UNSIGNED
)
fin:BEGIN
	
	CALL fn_check_account( acct_id, result ); IF ( result != 0 ) THEN LEAVE fin; END IF;
	-- CALL fn_check_character( char_id, result ); IF ( result != 0 ) THEN LEAVE fin; END IF;
	
	UPDATE tbl_account_game
		SET last_logged_in = NOW()
		WHERE tbl_account_game.acct_id = @acct_id;

	INSERT INTO `tbl_log_account_login`(
		`acct_id`, `acct_name`, `ip_address`, `port` )
		VALUES (
			@acct_id, acct_name, ip_address, port
		);

	SET result = 0;
		
END//
DELIMITER ;


-- ****************************************************************************
-- *
-- *	stored procedure: sp_new_item_list
-- */
DROP PROCEDURE IF EXISTS `sp_new_item_list`;
DELIMITER //
CREATE PROCEDURE `sp_new_item_list`(
	IN `acct_id` bigint UNSIGNED
,	IN `new_item_index_0` int UNSIGNED
,	IN `new_item_index_1` int UNSIGNED
,	IN `new_item_index_2` int UNSIGNED
,	IN `new_item_index_3` int UNSIGNED
,	IN `new_item_index_4` int UNSIGNED
,	IN `amount_0` int UNSIGNED
,	IN `amount_1` int UNSIGNED
,	IN `amount_2` int UNSIGNED
,	IN `amount_3` int UNSIGNED
,	IN `amount_4` int UNSIGNED
,	OUT `result` int UNSIGNED
,	OUT `added_count` int UNSIGNED
,	OUT `added_item_id_0` bigint UNSIGNED
,	OUT `added_item_id_1` bigint UNSIGNED
,	OUT `added_item_id_2` bigint UNSIGNED
,	OUT `added_item_id_3` bigint UNSIGNED
,	OUT `added_item_id_4` bigint UNSIGNED
)
fin:BEGIN
	
	CALL fn_check_account( acct_id, result ); IF ( result != 0 ) THEN LEAVE fin; END IF;
	-- CALL fn_check_character( char_id, result ); IF ( result != 0 ) THEN LEAVE fin; END IF;

	set added_count = 0;

	start transaction;

	if ( new_item_index_0 != 0 ) then
		call fn_new_item( acct_id, new_item_index_0, amount_0, result, added_item_id_0 );
		if ( result != 0 ) then rollback; leave fin; end if;
		set added_count = added_count + 1;
	end if;
	if ( new_item_index_1 != 0 ) then
		call fn_new_item( acct_id, new_item_index_1, amount_1, result, added_item_id_1 );
		if ( result != 0 ) then rollback; leave fin; end if;
		set added_count = added_count + 1;
	end if;
	if ( new_item_index_2 != 0 ) then
		call fn_new_item( acct_id, new_item_index_2, amount_2, result, added_item_id_2 );
		if ( result != 0 ) then rollback; leave fin; end if;
		set added_count = added_count + 1;
	end if;
	if ( new_item_index_3 != 0 ) then
		call fn_new_item( acct_id, new_item_index_3, amount_3, result, added_item_id_3 );
		if ( result != 0 ) then rollback; leave fin; end if;
		set added_count = added_count + 1;
	end if;
	if ( new_item_index_4 != 0 ) then
		call fn_new_item( acct_id, new_item_index_4, amount_4, result, added_item_id_4 );
		if ( result != 0 ) then rollback; leave fin; end if;
		set added_count = added_count + 1;
	end if;

	commit;

	SET result = 0;
		
END//
DELIMITER ;


-- version check sp
DROP PROCEDURE IF EXISTS `sp_version_check`;
DELIMITER //
CREATE PROCEDURE `sp_version_check`( OUT version BIGINT, OUT minor_version BIGINT )
BEGIN
	set version = 32; -- 0x0000000000000020
	set minor_version = 131757557391620000; -- 0x01d418cce4ccf7a0
END//
DELIMITER ;
GEN_db.h

// generated by SQL COMPILER
// time : 2018-07-11 13:08:59.164
// do not modify
// contact: icedac@gmail.com
#pragma once
#pragma warning(push)
#pragma warning(disable: 4100) // unreferenced formal parameter

namespace bb_game {

	using corn::FormatString;

	inline const char* name_A() { return "bb_game"; }
	inline const wchar_t* name_W() { return L"bb_game"; };
	inline const TCHAR* name() { return _T("bb_game"); }
	const int64_t version = 0x0000000000000020; // 32
	const int64_t minor_version = 0x01d418cce4ccf7a0; // 131757557391620000

	/****************************************************************************
	*
	*	stored procedure: sp_version_check
	*/
	struct sp_version_check
	{
		static const char* name_A() { return "sp_version_check"; }
		static const wchar_t* name_W() { return L"sp_version_check"; };
		static const TCHAR* name() { return _T("sp_version_check"); }

		struct sp_t {

			struct out_t {
				std::int64_t version; // bigint
				std::int64_t minor_version; // bigint

				BEGIN_OTLA_BINDING
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_FROM_DB, version, "version")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_FROM_DB, minor_version, "minor_version")
				END_OTLA_BINDING
			} out;


			BEGIN_OTLA_BINDING
				OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_SET_ARG, out.version, "version")
				OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_SET_ARG, out.minor_version, "minor_version")
			END_OTLA_BINDING
		}; // struct sp {

		//
		oTLA::StoredProcedure sp;
		oTLA::Search out;
	
		template < typename UPDATER >
		void open( UPDATER* u, const TCHAR* db_name = nullptr )
		{
			auto sp_name = FormatString(_T("%s.%s"), db_name ? db_name : bb_game::name(), name() ).AsString();
			sp.Open(u, sp_name.c_str());
			out.Open(u,nullptr);
		}
	};

	template 
	inline auto Enum_AsInt(E const value)
		-> typename std::underlying_type::type {
		return static_cast::type>(value);
	}
	
	enum class Error : std::int32_t {
		SUCCESS = 0,
		ERR_GENERAL = 1,
		ERR_NOT_IMPLEMENTED = 2,
		ERR_SESSION_SERVER = 3,
		ERR_HAS_PENDING_REQUEST = 4,
		ERR_ALREADY_LOGGED_IN = 100,
		ERR_WRONG_VERSION = 101,
		ERR_FORCE_DISCONNECT_INACTIVE_ACCOUNT = 102,
		ERR_SESSION_NOT_FOUND = 103,
		ERR_WRONG_PARAMETER_ACCT_NAME = 200,
		ERR_WRONG_PARAMETER_1 = 201,
		ERR_WRONG_PARAMETER_2 = 202,
		ERR_WRONG_PARAMETER_3 = 203,
		ERR_WRONG_PARAMETER_4 = 204,
		ERR_WRONG_PARAMETER_5 = 205,
		ERR_WRONG_PARAMETER_COST = 206,
		ERR_WRONG_PARAMETER = 299,
		ERR_RESOURCE_NOT_FOUND = 300,
		ERR_RESOURCE_NOT_FOUND_SOURCE = 301,
		ERR_RESOURCE_NOT_FOUND_TARGET = 302,
		ERR_ACCESS_DENIED = 400,
		ERR_ACCESS_DENIED_PROTECTED = 401,
		ERR_ACCESS_DENIED_SOURCE = 402,
		ERR_ACCESS_DENIED_TARGET = 403,
		ERR_DB_SERVER = 500,
		ERR_DB_SERVER_SQLEXCEPTION = 501,
		ERR_DB_SERVER_SQLWARNING = 502,
		ERR_INSURFFICIENT_RESOURCE = 1100,
		ERR_INSURFFICIENT_GAME_MONEY = 1101,
		ERR_INSURFFICIENT_GAME_CASH = 1102,
		ERR_INSURFFICIENT_HONOR_POINT = 1103,
		ERR_INSURFFICIENT_AP = 1104,
		ERR_INSURFFICIENT_ITEM_MATERIAL = 1105,
		ERR_INSURFFICIENT_INVENTORY = 1106,
		ERR_OPERATION_NOT_READY = 1200,
		ERR_ACCOUNT_EVENT_RAISED = 1300,
		ERR_ACCOUNT_EVENT_NOT_FOUND = 1301,
	};



	/****************************************************************************
	*
	*	table: tbl_account
	*/
	
	struct tbl_account
	{
		static const char* name_A() { return "tbl_account"; }
		static const wchar_t* name_W() { return L"tbl_account"; };
		static const TCHAR* name() { return _T("tbl_account"); };

		static std::basic_string table_name( const TCHAR* db_name = nullptr )
		{
			return FormatString(_T("%s.%s"), db_name ? db_name : _T("bb_game"), name()).AsString();
		}

		struct table_t {
			std::uint64_t acct_id; // bigint; 계정 Unique no
			std::uint64_t acct_id_external; // bigint; 
			corn::TFixedStringA<50> acct_name; // varchar; 
			corn::TFixedStringA<50> nickname; // varchar; 
			oTLA::DB_Time_t creation_time; // timestamp; 

			BEGIN_OTLA_BINDING
				OTLA_BIND_ATT_COLUMN_NAME(oTLA::TO_DB | oTLA::FROM_DB, acct_id, "acct_id")
				OTLA_BIND_ATT_COLUMN_NAME(oTLA::TO_DB | oTLA::FROM_DB, acct_id_external, "acct_id_external")
				OTLA_BIND_ATT_COLUMN_NAME(oTLA::TO_DB | oTLA::FROM_DB, acct_name, "acct_name")
				OTLA_BIND_ATT_COLUMN_NAME(oTLA::TO_DB | oTLA::FROM_DB, nickname, "nickname")
				OTLA_BIND_ATT_COLUMN_NAME(oTLA::TO_DB | oTLA::FROM_DB, creation_time, "creation_time")
			END_OTLA_BINDING

			template < typename U, typename V > // packet to packet
			static void copy(const U& from, V& to) {
				to.acct_id = from.acct_id; // CT_PRIMITIVE
				to.acct_id_external = from.acct_id_external; // CT_PRIMITIVE
				to.acct_name = from.acct_name; // CT_STRING
				to.nickname = from.nickname; // CT_STRING
				to.creation_time = from.creation_time; // CT_TIMESTAMP
			}
			template < typename DB, typename T > // db to packet
			static void copy_from( const DB& from, T& to ) {
				to.acct_id = from.acct_id; // CT_PRIMITIVE
				to.acct_id_external = from.acct_id_external; // CT_PRIMITIVE
				to.acct_name = from.acct_name.c_str(); // CT_STRING
				to.nickname = from.nickname.c_str(); // CT_STRING
				oTLA::time_db_to_timestamp(to.creation_time, from.creation_time, (float)0, (float)9); // CT_TIMESTAMP
			}
			template < typename DB, typename T > // packet to db
			static void copy_to( const T& from, DB& to ) {
				to.acct_id = from.acct_id; // CT_PRIMITIVE
				to.acct_id_external = from.acct_id_external; // CT_PRIMITIVE
				to.acct_name = from.acct_name.c_str(); // CT_STRING
				to.nickname = from.nickname.c_str(); // CT_STRING
				oTLA::time_timestamp_to_db(to.creation_time, from.creation_time, (float)9, (float)0); // CT_TIMESTAMP
			}
		};
		// where clause classes
		struct PK_by_acct_id { // PRIMARY_KEY
			std::uint64_t acct_id; // bigint
			BEGIN_OTLA_BINDING
				OTLA_BIND_ATT_COLUMN_NAME(oTLA::TO_DB | oTLA::UNIQUE_FIELD, acct_id, "acct_id")
			END_OTLA_BINDING

			template < typename U, typename V > // packet to packet
			static void copy(const U& from, V& to) {
				to.acct_id = from.acct_id; // CT_PRIMITIVE
			}
			template < typename DB, typename T > // db to packet
			static void copy_from( const DB& from, T& to ) {
				to.acct_id = from.acct_id; // CT_PRIMITIVE
			}
			template < typename DB, typename T > // packet to db
			static void copy_to( const T& from, DB& to ) {
				to.acct_id = from.acct_id; // CT_PRIMITIVE
			}
		};
		struct K_by_acct_id_external { // KEY
			std::uint64_t acct_id_external; // bigint
			BEGIN_OTLA_BINDING
				OTLA_BIND_ATT_COLUMN_NAME(oTLA::TO_DB | oTLA::UNIQUE_FIELD, acct_id_external, "acct_id_external")
			END_OTLA_BINDING

			template < typename U, typename V > // packet to packet
			static void copy(const U& from, V& to) {
				to.acct_id_external = from.acct_id_external; // CT_PRIMITIVE
			}
			template < typename DB, typename T > // db to packet
			static void copy_from( const DB& from, T& to ) {
				to.acct_id_external = from.acct_id_external; // CT_PRIMITIVE
			}
			template < typename DB, typename T > // packet to db
			static void copy_to( const T& from, DB& to ) {
				to.acct_id_external = from.acct_id_external; // CT_PRIMITIVE
			}
		};
		struct K_by_acct_name { // KEY
			corn::TFixedStringA<50> acct_name; // varchar
			BEGIN_OTLA_BINDING
				OTLA_BIND_ATT_COLUMN_NAME(oTLA::TO_DB | oTLA::UNIQUE_FIELD, acct_name, "acct_name")
			END_OTLA_BINDING

			template < typename U, typename V > // packet to packet
			static void copy(const U& from, V& to) {
				to.acct_name = from.acct_name; // CT_STRING
			}
			template < typename DB, typename T > // db to packet
			static void copy_from( const DB& from, T& to ) {
				to.acct_name = from.acct_name.c_str(); // CT_STRING
			}
			template < typename DB, typename T > // packet to db
			static void copy_to( const T& from, DB& to ) {
				to.acct_name = from.acct_name.c_str(); // CT_STRING
			}
		};
		struct PK_by_all { // PRIMARY_KEY_ALL
			std::uint64_t acct_id; // bigint

			BEGIN_OTLA_BINDING
				OTLA_BIND_ATT_COLUMN_NAME(oTLA::TO_DB | oTLA::UNIQUE_FIELD, acct_id, "acct_id")
			END_OTLA_BINDING

			template < typename U, typename V > // packet to packet
			static void copy(const U& from, V& to) {
				to.acct_id = from.acct_id; // CT_PRIMITIVE
			}
			template < typename DB, typename T > // db to packet
			static void copy_from( const DB& from, T& to ) {
				to.acct_id = from.acct_id; // CT_PRIMITIVE
			}
			template < typename DB, typename T > // packet to db
			static void copy_to( const T& from, DB& to ) {
				to.acct_id = from.acct_id; // CT_PRIMITIVE
			}
		};

		template < typename DB >
		static oTLA::Persist persist(DB* db, const TCHAR* db_name = nullptr)
		{
			oTLA::Persist u(db, table_name(db_name).c_str() );
			return std::move(u);
		}

		template < typename DB, typename Where >
		static oTLA::search_t search(DB* db, const Where& where, const TCHAR* db_name = nullptr)
		{
			oTLA::search_t u(db, table_name(db_name).c_str(), where);
			return std::move(u);
		}

		template < typename DB >
		static oTLA::search_t search(DB* db, const TCHAR* db_name = nullptr)
		{
			oTLA::search_t u(db, table_name(db_name).c_str(), oTLA::NullWhereClause());
			return std::move(u);
		}
		
	};

	// ...


	/****************************************************************************
	*
	*	stored procedure: sp_get_account_box
	*/
	struct sp_get_account_box
	{
		static const char* name_A() { return "sp_get_account_box"; }
		static const wchar_t* name_W() { return L"sp_get_account_box"; };
		static const TCHAR* name() { return _T("sp_get_account_box"); };

		static std::basic_string sp_name( const TCHAR* db_name = nullptr )
		{
			return FormatString(_T("%s.%s"), db_name ? db_name : _T("bb_game"), name()).AsString();
		}

		struct sp_t {
			struct {
				std::uint64_t acct_id; // bigint

				template < typename U, typename V > // packet to packet
				static void copy(const U& from, V& to) {
					to.acct_id = from.acct_id; // CT_PRIMITIVE
				}
				template < typename DB, typename T > // db to packet
				static void copy_from( const DB& from, T& to ) {
					to.acct_id = from.acct_id; // CT_PRIMITIVE
				}
				template < typename DB, typename T > // packet to db
				static void copy_to( const T& from, DB& to ) {
					to.acct_id = from.acct_id; // CT_PRIMITIVE
				}
				std::basic_string as_string() const {
					std::basic_stringstream ss;
					ss << _T(" in.") << _T("acct_id") << _T(":") << acct_id;
					return ss.str();
				}
			} in;

			struct out_t {
				std::uint32_t result; // int

				BEGIN_OTLA_BINDING
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_FROM_DB, result, "result")
				END_OTLA_BINDING

				template < typename U, typename V > // packet to packet
				static void copy(const U& from, V& to) {
					to.result = from.result; // CT_PRIMITIVE
				}
				template < typename DB, typename T > // db to packet
				static void copy_from( const DB& from, T& to ) {
					to.result = from.result; // CT_PRIMITIVE
				}
				template < typename DB, typename T > // packet to db
				static void copy_to( const T& from, DB& to ) {
					to.result = from.result; // CT_PRIMITIVE
				}
				std::basic_string as_string() const {
					std::basic_stringstream ss;
					ss << _T(" in.") << _T("result") << _T(":") << result;
					return ss.str();
				}
			} out;

			struct result_set_t {
				std::uint64_t acct_id; // bigint
				static const auto box_type__max_size = 10;
				std::uint32_t box_type[10]; // int
				static const auto box_arena_tier__max_size = 10;
				std::uint32_t box_arena_tier[10]; // int
				static const auto time_to_unlock__max_size = 10;
				oTLA::DB_Time_t time_to_unlock[10]; // timestamp

				BEGIN_OTLA_BINDING
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, acct_id, "acct_id")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, box_type[0], "box_type_0")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, box_type[1], "box_type_1")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, box_type[2], "box_type_2")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, box_type[3], "box_type_3")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, box_type[4], "box_type_4")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, box_type[5], "box_type_5")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, box_type[6], "box_type_6")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, box_type[7], "box_type_7")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, box_type[8], "box_type_8")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, box_type[9], "box_type_9")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, box_arena_tier[0], "box_arena_tier_0")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, box_arena_tier[1], "box_arena_tier_1")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, box_arena_tier[2], "box_arena_tier_2")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, box_arena_tier[3], "box_arena_tier_3")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, box_arena_tier[4], "box_arena_tier_4")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, box_arena_tier[5], "box_arena_tier_5")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, box_arena_tier[6], "box_arena_tier_6")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, box_arena_tier[7], "box_arena_tier_7")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, box_arena_tier[8], "box_arena_tier_8")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, box_arena_tier[9], "box_arena_tier_9")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, time_to_unlock[0], "time_to_unlock_0")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, time_to_unlock[1], "time_to_unlock_1")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, time_to_unlock[2], "time_to_unlock_2")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, time_to_unlock[3], "time_to_unlock_3")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, time_to_unlock[4], "time_to_unlock_4")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, time_to_unlock[5], "time_to_unlock_5")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, time_to_unlock[6], "time_to_unlock_6")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, time_to_unlock[7], "time_to_unlock_7")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, time_to_unlock[8], "time_to_unlock_8")
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_ARG, time_to_unlock[9], "time_to_unlock_9")
				END_OTLA_BINDING

				template < typename U, typename V > // packet to packet
				static void copy(const U& from, V& to) {
					to.acct_id = from.acct_id; // CT_PRIMITIVE
					for ( int i = 0; i < 10; ++i )
						to.box_type[i] = from.box_type[i]; // CT_PRIMITIVE[]
					for ( int i = 0; i < 10; ++i )
						to.box_arena_tier[i] = from.box_arena_tier[i]; // CT_PRIMITIVE[]
					for ( int i = 0; i < 10; ++i )
						to.time_to_unlock[i] = from.time_to_unlock[i]; // CT_TIMESTAMP
				}
				template < typename DB, typename T > // db to packet
				static void copy_from( const DB& from, T& to ) {
					to.acct_id = from.acct_id; // CT_PRIMITIVE
					for ( int i = 0; i < 10; ++i )
						to.box_type[i] = from.box_type[i]; // CT_PRIMITIVE[]
					for ( int i = 0; i < 10; ++i )
						to.box_arena_tier[i] = from.box_arena_tier[i]; // CT_PRIMITIVE[]
					for ( int i = 0; i < 10; ++i )
						oTLA::time_db_to_timestamp(to.time_to_unlock[i], from.time_to_unlock[i], (float)0, (float)9); // CT_TIMESTAMP
				}
				template < typename DB, typename T > // packet to db
				static void copy_to( const T& from, DB& to ) {
					to.acct_id = from.acct_id; // CT_PRIMITIVE
					for ( int i = 0; i < 10; ++i )
						to.box_type[i] = from.box_type[i]; // CT_PRIMITIVE[]
					for ( int i = 0; i < 10; ++i )
						to.box_arena_tier[i] = from.box_arena_tier[i]; // CT_PRIMITIVE[]
					for ( int i = 0; i < 10; ++i )
						oTLA::time_db_to_timestamp(to.time_to_unlock[i], from.time_to_unlock[i], (float)9, (float)0);; // CT_TIMESTAMP
				}
				std::basic_string as_string() const {
					std::basic_stringstream ss;
					ss << _T(" in.") << _T("acct_id") << _T(":") << acct_id;
					ss << _T(" in.") << _T("box_type[0]") << _T(":") << box_type[0];
					ss << _T(" in.") << _T("box_type[1]") << _T(":") << box_type[1];
					ss << _T(" in.") << _T("box_type[2]") << _T(":") << box_type[2];
					ss << _T(" in.") << _T("box_type[3]") << _T(":") << box_type[3];
					ss << _T(" in.") << _T("box_type[4]") << _T(":") << box_type[4];
					ss << _T(" in.") << _T("box_type[5]") << _T(":") << box_type[5];
					ss << _T(" in.") << _T("box_type[6]") << _T(":") << box_type[6];
					ss << _T(" in.") << _T("box_type[7]") << _T(":") << box_type[7];
					ss << _T(" in.") << _T("box_type[8]") << _T(":") << box_type[8];
					ss << _T(" in.") << _T("box_type[9]") << _T(":") << box_type[9];
					ss << _T(" in.") << _T("box_arena_tier[0]") << _T(":") << box_arena_tier[0];
					ss << _T(" in.") << _T("box_arena_tier[1]") << _T(":") << box_arena_tier[1];
					ss << _T(" in.") << _T("box_arena_tier[2]") << _T(":") << box_arena_tier[2];
					ss << _T(" in.") << _T("box_arena_tier[3]") << _T(":") << box_arena_tier[3];
					ss << _T(" in.") << _T("box_arena_tier[4]") << _T(":") << box_arena_tier[4];
					ss << _T(" in.") << _T("box_arena_tier[5]") << _T(":") << box_arena_tier[5];
					ss << _T(" in.") << _T("box_arena_tier[6]") << _T(":") << box_arena_tier[6];
					ss << _T(" in.") << _T("box_arena_tier[7]") << _T(":") << box_arena_tier[7];
					ss << _T(" in.") << _T("box_arena_tier[8]") << _T(":") << box_arena_tier[8];
					ss << _T(" in.") << _T("box_arena_tier[9]") << _T(":") << box_arena_tier[9];
					ss << _T(" in.") << _T("time_to_unlock[0]") << _T(":") << time_to_unlock[0];
					ss << _T(" in.") << _T("time_to_unlock[1]") << _T(":") << time_to_unlock[1];
					ss << _T(" in.") << _T("time_to_unlock[2]") << _T(":") << time_to_unlock[2];
					ss << _T(" in.") << _T("time_to_unlock[3]") << _T(":") << time_to_unlock[3];
					ss << _T(" in.") << _T("time_to_unlock[4]") << _T(":") << time_to_unlock[4];
					ss << _T(" in.") << _T("time_to_unlock[5]") << _T(":") << time_to_unlock[5];
					ss << _T(" in.") << _T("time_to_unlock[6]") << _T(":") << time_to_unlock[6];
					ss << _T(" in.") << _T("time_to_unlock[7]") << _T(":") << time_to_unlock[7];
					ss << _T(" in.") << _T("time_to_unlock[8]") << _T(":") << time_to_unlock[8];
					ss << _T(" in.") << _T("time_to_unlock[9]") << _T(":") << time_to_unlock[9];
					return ss.str();
				}
			};

			BEGIN_OTLA_BINDING
				OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_IN_ARG, in.acct_id, "acct_id")
				OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_SET_ARG, out.result, "result")
			END_OTLA_BINDING
		}; // struct sp {

		//
		oTLA::StoredProcedure sp;
		oTLA::Search out;
		oTLA::Search result;
		oTLA::Search result_end;

		struct result_iterator {
			oTLA::Search* s_;
			result_iterator(oTLA::Search* s) : s_(s) {}			
			oTLA::Search::reference operator*() const { return *(*s_); }
			oTLA::Search::pointer operator->() const { return (*s_).operator->(); }
			bool operator!= (const result_iterator & rhs) const { return (*s_) != (*rhs.s_); }
			result_iterator& operator++() { ++(*s_); return *this; }
		};
		result_iterator begin() {
			return result_iterator(&result);
		}
		result_iterator end() {
			return result_iterator(&result_end);
		}
		int size() const {
			return result.Get_Row_Processed_Count();
		}
		
		template < typename UPDATER >
		void open( UPDATER* u, const TCHAR* db_name = nullptr )
		{
			result.SetExternalResultStream(sp.Get_Result_Stream());
			sp.Open(u, sp_name(db_name).c_str(), result);
			out.Open(u,nullptr);
		}
		template < typename T_acct_id >
		explicit sp_get_account_box( char _dummy, const T_acct_id& acct_id ) {
			sp->in.acct_id = acct_id; // DEFAULT
		}
		template < typename T_acct_id >
		void init( const T_acct_id& acct_id ) {
			sp->in.acct_id = acct_id; // DEFAULT
		}
		template < typename PacketType >
		explicit sp_get_account_box( const PacketType* p ) {
			init( 
				p->acct_id
			);
		}
	private:
		sp_get_account_box() = delete;
	};

	/****************************************************************************
	*
	*	stored procedure: sp_account_login
	*/
	struct sp_account_login
	{
		static const char* name_A() { return "sp_account_login"; }
		static const wchar_t* name_W() { return L"sp_account_login"; };
		static const TCHAR* name() { return _T("sp_account_login"); };

		static std::basic_string sp_name( const TCHAR* db_name = nullptr )
		{
			return FormatString(_T("%s.%s"), db_name ? db_name : _T("bb_game"), name()).AsString();
		}

		struct sp_t {
			struct {
				corn::TFixedStringA<50> acct_name; // varchar
				corn::TFixedStringA<50> ip_address; // varchar
				std::uint32_t port; // int

				template < typename U, typename V > // packet to packet
				static void copy(const U& from, V& to) {
					to.acct_name = from.acct_name; // CT_STRING
					to.ip_address = from.ip_address; // CT_STRING
					to.port = from.port; // CT_PRIMITIVE
				}
				template < typename DB, typename T > // db to packet
				static void copy_from( const DB& from, T& to ) {
					to.acct_name = from.acct_name.c_str(); // CT_STRING
					to.ip_address = from.ip_address.c_str(); // CT_STRING
					to.port = from.port; // CT_PRIMITIVE
				}
				template < typename DB, typename T > // packet to db
				static void copy_to( const T& from, DB& to ) {
					to.acct_name = from.acct_name.c_str(); // CT_STRING
					to.ip_address = from.ip_address.c_str(); // CT_STRING
					to.port = from.port; // CT_PRIMITIVE
				}
				std::basic_string as_string() const {
					std::basic_stringstream ss;
					ss << _T(" in.") << _T("acct_name") << _T(":") << acct_name.c_str();
					ss << _T(" in.") << _T("ip_address") << _T(":") << ip_address.c_str();
					ss << _T(" in.") << _T("port") << _T(":") << port;
					return ss.str();
				}
			} in;

			struct out_t {
				std::uint32_t result; // int

				BEGIN_OTLA_BINDING
					OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_FROM_DB, result, "result")
				END_OTLA_BINDING

				template < typename U, typename V > // packet to packet
				static void copy(const U& from, V& to) {
					to.result = from.result; // CT_PRIMITIVE
				}
				template < typename DB, typename T > // db to packet
				static void copy_from( const DB& from, T& to ) {
					to.result = from.result; // CT_PRIMITIVE
				}
				template < typename DB, typename T > // packet to db
				static void copy_to( const T& from, DB& to ) {
					to.result = from.result; // CT_PRIMITIVE
				}
				std::basic_string as_string() const {
					std::basic_stringstream ss;
					ss << _T(" in.") << _T("result") << _T(":") << result;
					return ss.str();
				}
			} out;


			BEGIN_OTLA_BINDING
				OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_IN_ARG, in.acct_name, "acct_name")
				OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_IN_ARG, in.ip_address, "ip_address")
				OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_IN_ARG, in.port, "port")
				OTLA_BIND_ATT_COLUMN_NAME(oTLA::SP_OUT_SET_ARG, out.result, "result")
			END_OTLA_BINDING
		}; // struct sp {

		//
		oTLA::StoredProcedure sp;
		oTLA::Search out;
		
		template < typename UPDATER >
		void open( UPDATER* u, const TCHAR* db_name = nullptr )
		{
			sp.Open(u, sp_name(db_name).c_str());
			out.Open(u,nullptr);
		}
		template < typename T_acct_name, typename T_ip_address, typename T_port >
		explicit sp_account_login( char _dummy, const T_acct_name& acct_name, const T_ip_address& ip_address, const T_port& port ) {
			sp->in.acct_name = acct_name; // DEFAULT
			sp->in.ip_address = ip_address; // DEFAULT
			sp->in.port = port; // DEFAULT
		}
		template < typename T_acct_name, typename T_ip_address, typename T_port >
		void init( const T_acct_name& acct_name, const T_ip_address& ip_address, const T_port& port ) {
			sp->in.acct_name = acct_name; // DEFAULT
			sp->in.ip_address = ip_address; // DEFAULT
			sp->in.port = port; // DEFAULT
		}
		template < typename PacketType >
		explicit sp_account_login( const PacketType* p ) {
			init( 
				p->acct_name, p->ip_address, p->port
			);
		}
	private:
		sp_account_login() = delete;
	};

	// ...

} // namespace
#pragma warning(pop)
gen_cs.cs

/****************************************************************************
 * 	
 *  generated by PacketCompiler.
 *  do not modify this.
 * 
 *  time: 2018-07-11 13:42:11.005
 *  
 */
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace cl_ms {
    /// start of RawCode
    
    public enum ERoomType
    {
        RT_ROOM_DEFAULT = 0,
        RT_ROOM_PVE,
        RT_ROOM_PVP,
        RT_ROOM_END,
        RT_ROOM_TEST = 0xffff,
    }
    
    /// endof RawCode

    /// class Util
    /// 
    /// 
    /// 
    public class Util
    {
        public const UInt64 VERSION = 0x0000000000000020; // 32
        public const UInt64 BUILD_VERSION = 0x01d418d18807a1a0; // 131757577310020000
		
        public const UInt64 SALT_UINT64 = 0x753564cc275f0712;		
        public static byte[] COMPILE_TIME_PASS_BYTES = new byte[] { 0xd8,0x3e,0x84,0x32,0x35,0x62,0xb9,0x7d,0x56,0x0b,0x31,0x62,0xfc,0x3d,0x35,0x2b,0xac,0x3c,0x10,0x2c,0xf7,0x24,0xbc,0x0d,0xf3,0x1e,0xeb,0x76,0x99,0x41,0x82,0x49,0xdc,0x1a,0xbe,0x48,0xb9,0x01,0x94,0x55,0x93,0x49,0x11,0x1b,0x94,0x69,0xc6,0x12,0xea,0x7f,0x84,0x49,0x16,0x18,0xed,0x4e,0xb3,0x14,0xac,0x4e,0x55,0x60,0x4f,0x08 }; // do not modify
        // ...
    }
	public enum Error {
		SUCCESS = 0, // success
		ERR_GENERAL = 1, // error
		ERR_NOT_IMPLEMENTED = 2, // not implemented
		ERR_SESSION_SERVER = 3, // session error
		ERR_HAS_PENDING_REQUEST = 4, // client should wait until last response receive
		ERR_ALREADY_LOGGED_IN = 100, // already logged in
		ERR_WRONG_VERSION = 101, // wrong version
		ERR_FORCE_DISCONNECT_INACTIVE_ACCOUNT = 102, // disconnect inactive account, try to logged in again
		ERR_SESSION_NOT_FOUND = 103, // ERR_SESSION_NOT_FOUND
		// ...
	}
    // send packet list
    public enum Send {
		CM_VERSION_CHECK_REQ = 1000,
		CM_LOGIN_REQ = 1001,
		CM_KEEP_ALIVE_REQ = 1002,
		CM_LIST_CHARACTER_REQ = 1003,
		CM_ROOM_CREATE_OR_JOIN_REQ = 1004,
		CM_ROOM_JOIN_REQ = 1005,
		CM_ROOM_LEAVE_REQ = 1006,
		CM_ROOM_CHAT_REQ = 1007,
		CM_ROOM_READY_REQ = 1008,
		CM_ROOM_KICK_REQ = 1009,
		CM_ROOM_ADD_NPCREQ = 1010,
    }
	// ...	
   /****************************************************************************
    *
    * Packet Classes for Send/Recv
    */
    // '버전 체크'
    public partial class Send_CM_VersionCheckReq : ISend
    {
        public static System.UInt16 Type = (System.UInt16)Send.CM_VERSION_CHECK_REQ;
        public static System.String GetPacketName() { return "CM_VERSION_CHECK_REQ"; }
        public virtual System.UInt16 _Type { get { return Type; } }
        public virtual System.String _Name { get { return GetPacketName(); } }
        public virtual System.UInt16 GetPacketId() { return _Type; }
        // public byte[] GetBytes()
        public UInt64 version; // '버전; 다르면 요청 실패'
        public UInt64 build_version; // '빌드버전; 달라도 성공. 진행 여부는 클라이언트에서 판단'
        public UInt64 client_key; // 'reserved'
    }

    public partial class Send_CM_LoginReq : ISend
    {
        public static System.UInt16 Type = (System.UInt16)Send.CM_LOGIN_REQ;
        public static System.String GetPacketName() { return "CM_LOGIN_REQ"; }
        public virtual System.UInt16 _Type { get { return Type; } }
        public virtual System.String _Name { get { return GetPacketName(); } }
        public virtual System.UInt16 GetPacketId() { return _Type; }
        // public byte[] GetBytes()
        public UInt64 version; // '버전; 다르면 요청 실패'
        public UInt64 build_version; // '빌드버전; 달라도 성공. 진행 여부는 클라이언트에서 판단'
        public const UInt32 acct_name__constrain_max_size = 50; // will assert if the size exceeds 50
        public String acct_name = null; 
        public const UInt32 acct_passwd__constrain_max_size = 16; // will assert if the size exceeds 16
        public String acct_passwd = null; 
    }

    // '버전 체크'
    public partial class Send_CM_KeepAliveReq : ISend
    {
        public static System.UInt16 Type = (System.UInt16)Send.CM_KEEP_ALIVE_REQ;
        public static System.String GetPacketName() { return "CM_KEEP_ALIVE_REQ"; }
        public virtual System.UInt16 _Type { get { return Type; } }
        public virtual System.String _Name { get { return GetPacketName(); } }
        public virtual System.UInt16 GetPacketId() { return _Type; }
        // public byte[] GetBytes()
        public System.DateTime client_time; 
    }

    ...

   /****************************************************************************
    *
    * Serializer for Send/Recv
    */
    // C# Send Serializer
    public partial class Send_CM_VersionCheckReq : ISend
    {
        public virtual byte[] GetBytes()
        {
            System.IO.MemoryStream stream = new System.IO.MemoryStream();
            System.IO.BinaryWriter writer = new System.IO.BinaryWriter(stream);
            System.IO.MemoryStream tail_stream = new System.IO.MemoryStream();
            System.IO.BinaryWriter tail_writer = new System.IO.BinaryWriter(tail_stream);
            int offset = 0;
            
            
            // UInt64 version
            writer.Write( this.version );
            
            // UInt64 build_version
            writer.Write( this.build_version );
            
            // UInt64 client_key
            writer.Write( this.client_key );
            
            if ( offset > 0 )
                writer.Write(tail_stream.ToArray());
            return stream.ToArray();
        }
    }
    // C# Send Serializer
    public partial class Send_CM_LoginReq : ISend
    {
        public virtual byte[] GetBytes()
        {
            System.IO.MemoryStream stream = new System.IO.MemoryStream();
            System.IO.BinaryWriter writer = new System.IO.BinaryWriter(stream);
            System.IO.MemoryStream tail_stream = new System.IO.MemoryStream();
            System.IO.BinaryWriter tail_writer = new System.IO.BinaryWriter(tail_stream);
            int offset = 0;
            
            
            // UInt64 version
            writer.Write( this.version );
            
            // UInt64 build_version
            writer.Write( this.build_version );
            
            // String acct_name
            if ( this.acct_name == null ) this.acct_name = "";
            Trace.Assert(this.acct_name.Length <= Send_CM_LoginReq.acct_name__constrain_max_size ); 
            writer.Write( (System.UInt64)offset );
            byte[] acct_name_buf = Util.MBCS.GetBytes(this.acct_name);
            tail_writer.Write(acct_name_buf);
            tail_writer.Write((byte)0);
            offset += acct_name_buf.Length + 1;
            
            // String acct_passwd
            if ( this.acct_passwd == null ) this.acct_passwd = "";
            Trace.Assert(this.acct_passwd.Length <= Send_CM_LoginReq.acct_passwd__constrain_max_size ); 
            writer.Write( (System.UInt64)offset );
            byte[] acct_passwd_buf = Util.MBCS.GetBytes(this.acct_passwd);
            tail_writer.Write(acct_passwd_buf);
            tail_writer.Write((byte)0);
            offset += acct_passwd_buf.Length + 1;
            
            if ( offset > 0 )
                writer.Write(tail_stream.ToArray());
            return stream.ToArray();
        }
    }

	...

    // C# Recv Serializer
    public partial class Recv_MC_VersionCheckRes
    {
        public void Read(byte[] data, int size)
        {
            System.IO.MemoryStream stream = new System.IO.MemoryStream(data);
            System.IO.BinaryReader reader = new System.IO.BinaryReader(stream);
            List runLaterList = new List();
            long begin_offset = 0;
            
            
            // UInt32 result
            this.result = reader.ReadUInt32();
            
            // UInt64 required_version
            this.required_version = reader.ReadUInt64();
            
            // UInt64 required_build_version
            this.required_build_version = reader.ReadUInt64();
            
            // String redirection_url
            long redirection_url_offset = (long)reader.ReadUInt64();
            runLaterList.Add(() => {
                stream.Position = begin_offset + redirection_url_offset;
                this.redirection_url = Util.ReadCString(reader);
            });
            
            // run all runLaters
            begin_offset = stream.Position;
            foreach (Util.runLater run in runLaterList)
                run();
        }
    }
    // C# Recv Serializer
    public partial class Recv_MC_LoginRes
    {
        public void Read(byte[] data, int size)
        {
            System.IO.MemoryStream stream = new System.IO.MemoryStream(data);
            System.IO.BinaryReader reader = new System.IO.BinaryReader(stream);
            List runLaterList = new List();
            long begin_offset = 0;
            
            
            // UInt32 result
            this.result = reader.ReadUInt32();
            
            // UInt64 required_version
            this.required_version = reader.ReadUInt64();
            
            // UInt64 required_build_version
            this.required_build_version = reader.ReadUInt64();
            
            // String acct_name
            long acct_name_offset = (long)reader.ReadUInt64();
            runLaterList.Add(() => {
                stream.Position = begin_offset + acct_name_offset;
                this.acct_name = Util.ReadCString(reader);
            });
            
            // UInt64 session_id
            this.session_id = reader.ReadUInt64();
            
            // UInt64 acct_id
            this.acct_id = reader.ReadUInt64();
            
            // UInt64 acct_id_external
            this.acct_id_external = reader.ReadUInt64();
            
            // String nickname
            long nickname_offset = (long)reader.ReadUInt64();
            runLaterList.Add(() => {
                stream.Position = begin_offset + nickname_offset;
                this.nickname = Util.ReadCString(reader);
            });
            
            // System.DateTime creation_time
            this.creation_time = System.DateTime.FromFileTime( 0 );
            try { this.creation_time = System.DateTime.FromFileTime( reader.ReadInt64() ); } catch ( System.Exception e ) {}
            
            // UInt32 char_count
            this.char_count = reader.ReadUInt32();
            
            // UInt64 curr_char_id
            this.curr_char_id = reader.ReadUInt64();
            
            // UInt32 gold
            this.gold = reader.ReadUInt32();
            
            // UInt32 ruby
            this.ruby = reader.ReadUInt32();
            
            // UInt32 honor
            this.honor = reader.ReadUInt32();
            
            // UInt32 max_ap
            this.max_ap = reader.ReadUInt32();
            
            // System.DateTime time_to_max_ap
            this.time_to_max_ap = System.DateTime.FromFileTime( 0 );
            try { this.time_to_max_ap = System.DateTime.FromFileTime( reader.ReadInt64() ); } catch ( System.Exception e ) {}
            
            // UInt32 ap_cool_time
            this.ap_cool_time = reader.ReadUInt32();
            
            // System.DateTime last_logged_in
            this.last_logged_in = System.DateTime.FromFileTime( 0 );
            try { this.last_logged_in = System.DateTime.FromFileTime( reader.ReadInt64() ); } catch ( System.Exception e ) {}
            
            // UInt32 acct_level
            this.acct_level = reader.ReadUInt32();
            
            // UInt32 acct_exp
            this.acct_exp = reader.ReadUInt32();
            
            // UInt32 max_inventory_count
            this.max_inventory_count = reader.ReadUInt32();
            
            // UInt32 last_processed_system_mail_id
            this.last_processed_system_mail_id = reader.ReadUInt32();
            
            // System.DateTime time_to_free_product[10]
            this.time_to_free_product = new System.DateTime[10];
            for ( int i = 0; i < 10; ++i )
            {
                this.time_to_free_product[i] = System.DateTime.FromFileTime( 0 );
        		try { this.time_to_free_product[i] = System.DateTime.FromFileTime( reader.ReadInt64() ); } catch ( System.Exception e ) {}
            }
            
            
            // UInt32 max_box_inventory_count
            this.max_box_inventory_count = reader.ReadUInt32();
            
            // run all runLaters
            begin_offset = stream.Position;
            foreach (Util.runLater run in runLaterList)
                run();
        }
    }

} // end of cl_ms

see full input, output source