24.2.4.4 Full-Text Parser 플러그인 작성
MySQL 5.6에서는 MyISAM
에서만 전체 파서 플러그인이 지원됩니다. 전체 파서 플러그인에 대한 설명은 섹션 24.2.3.2 "전문 파서 플러그인" 을 참조하십시오.
전체 파서 서버 플러그인은 내장 전체 파서 대신하거나 그것을 변경하는 데 사용할 수 있습니다. 이 섹션에서는 simple_parser
라는 전문 파서 플러그인을 작성하는 방법에 대해 설명합니다. 이 플러그인은 MySQL의 기본 전체 파서에 의해 사용되는 것보다 간단한 규칙에 따라 구문 분석을 수행 단어는 공백을 포함하지 않는 문자열입니다.
이 단계에서는 MySQL 소스 배포판의 plugin/fulltext
디렉토리의 소스 코드를 사용하고 있기 때문에,이 디렉토리 위치를 변경하십시오. 다음 단계에서는 플러그인 라이브러리를 만드는 방법에 대해 설명합니다.
전체 파서 플러그인을 설명하기 위해 플러그인 소스 파일에서 다음의 헤더 파일을 포함합니다. 플러그인의 기능 및 요구 사항에 따라 다른 MySQL의 헤더 파일이나 일반적인 헤더 파일이 필요할 수도 있습니다.
#include <mysql/plugin.h>
plugin.h
은MYSQL_FTPARSER_PLUGIN
서버 플러그인 유형 및 플러그인을 선언하는 데 필요한 데이터 구조를 정의합니다.플러그인 라이브러리 파일의 라이브러리 디스크립터를 설치합니다.
이 기술자는 서버 플러그인의 일반 플러그인 기술자가 포함되어 있습니다. 전체 파서 플러그인의 경우 유형은
MYSQL_FTPARSER_PLUGIN
이어야합니다. 이것은FULLTEXT
인덱스를 만들 때WITH PARSER
절에서 사용하는 경우 플러그인이 합법적임을 식별하는 값입니다. (다른 플러그인 타입이 어구에 대해서도 유효하지 않습니다.)예를 들어,
simple_parser
라는 단일 전문 파서 플러그 인을 포함하는 라이브러리의 라이브러리 디스크립터는 다음과 같습니다.mysql_declare_plugin(ftexample) { MYSQL_FTPARSER_PLUGIN, /* type */ &simple_parser_descriptor, /* descriptor */ "simple_parser", /* name */ "Oracle Corporation", /* author */ "Simple Full-Text Parser", /* description */ PLUGIN_LICENSE_GPL, /* plugin license */ simple_parser_plugin_init, /* init function (when loaded) */ simple_parser_plugin_deinit,/* deinit function (when unloaded) */ 0x0001, /* version */ simple_status, /* status variables */ simple_system_variables, /* system variables */ NULL, 0 } mysql_declare_plugin_end;
name
멤버 (simple_parser
)는INSTALL PLUGIN
,UNINSTALL PLUGIN
등의 문에서 플러그인을 참조하는 데 사용하는 이름을 보여줍니다. 이것은SHOW PLUGINS
또는INFORMATION_SCHEMA.PLUGINS
에 의해 표시되는 이름이기도합니다.자세한 내용은 섹션 24.2.4.2.1 "서버 플러그인 라이브러리 및 플러그인 기술자" 를 참조하십시오.
유형별 플러그인 디스크립터를 설치합니다.
라이브러리 디스크립터의 각 일반 플러그인 디스크립터는 유형별 디스크립터를 가리 킵니다. 전체 파서 플러그인의 경우 유형별 기술자는
plugin.h
파일의st_mysql_ftparser
구조체의 인스턴스입니다.struct st_mysql_ftparser { int interface_version; int (*parse)(MYSQL_FTPARSER_PARAM *param); int (*init)(MYSQL_FTPARSER_PARAM *param); int (*deinit)(MYSQL_FTPARSER_PARAM *param); };
구조체 정의에 표시된대로 디스크립터는 인터페이스 버전 번호가 3 개의 함수 포인터가 포함되어 있습니다.
인터페이스의 버전 번호는 기호를 사용하여 지정하고
MYSQL_
형식입니다. 전체 파서 플러그인의 경우, 기호는 "xxx
_INTERFACE_VERSIONMYSQL_FTPARSER_INTERFACE_VERSION
"입니다. 소스 코드는include/mysql/plugin_ftparser.h
에 정의되어있는 전문 파서 플러그인의 실제 인터페이스 버전 번호가 있습니다.init
회원 및deinit
멤버 함수를 가리 키도록하거나 함수가 불필요한 경우는 0으로 설정합니다.parse
멤버는 구문 분석을 수행하는 함수를 가리키는해야합니다.simple_parser
선언은 그 기술자는&simple_parser_descriptor
로 표시되어 있습니다. 기술자는 전문 플러그인 인터페이스의 버전 번호 (MYSQL_FTPARSER_INTERFACE_VERSION
의해 지정됩니다) 플러그인의 구문 분석 함수 초기화 함수 및 초기화 해제 함수를 지정합니다.static struct st_mysql_ftparser simple_parser_descriptor= { MYSQL_FTPARSER_INTERFACE_VERSION, /* interface version */ simple_parser_parse, /* parsing function */ simple_parser_init, /* parser init function */ simple_parser_deinit /* parser deinit function */ };
전체 파서 서버 플러그인에는 인덱싱 및 검색의 두 가지 맥락에서 사용됩니다. 모두의 컨텍스트에서 서버 플러그인을 호출 한 각 SQL 문 처리의 시작과 종료시에 초기화 함수 및 초기화 해제 함수를 호출합니다. 그러나 문을 처리하는 동안 서버 컨텍스트에 고유의 방법으로 주요 구문 분석 함수를 호출합니다.
인덱스 설정의 경우, 서버는 인덱스 설정되는 각 열 값에 대해 파서를 호출합니다.
검색의 경우, 서버는 검색 문자열을 구문 분석하는 파서를 호출합니다. 파서는 문에 의해 처리되는 행에서 호출 될 수도 있습니다. 자연 언어 모드에서는 서버가 파서를 호출 할 필요는 없습니다. 쿼리 확장을 사용한 boolean 모드 문구 검색 자연어 검색의 경우 인덱스에없는 정보 컬럼 값을 구문 분석하는 파서가 사용됩니다. 또한
FULLTEXT
인덱스없는 컬럼에 대해 boolean 모드 검색이 실행 된 경우는 내장 파서가 호출됩니다. (플러그인은 특정 인덱스에 연결됩니다. 인덱스가없는 경우 플러그인은 사용되지 않습니다.)
일반 플러그인 기술자 플러그인 선언에는 초기화 함수 및 초기화 해제 함수를 가리키는
init
회원 및deinit
멤버가 있고, 가리키는 대상 유형별 플러그인 디스크립터에도이 있습니다. 그러나 이러한 함수 쌍 목적이 다릅니다 다른 이유로 호출됩니다.일반 플러그인 기술자 플러그인 선언의 경우 초기화 함수 및 초기화 해제 함수는 플러그인이로드 및 언로드 될 때 호출됩니다.
유형별 플러그인 기술자의 경우 초기화 함수 및 초기화 해제 함수는 플러그인이 사용되는 SQL 문마다 호출됩니다.
플러그인 디스크립터에 지정되어있는 각 인터페이스 함수는 성공의 경우는 제로, 그리고 실패의 경우는 0이 아닌 리턴 구문 분석하는 컨텍스트가 포함되어있는
MYSQL_FTPARSER_PARAM
구조체를 가리키는 인수를받습니다. 이 구조체의 정의는 다음과 같습니다.typedef struct st_mysql_ftparser_param { int (*mysql_parse)(struct st_mysql_ftparser_param *, char *doc, int doc_len); int (*mysql_add_word)(struct st_mysql_ftparser_param *, char *word, int word_len, MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info); void *ftparser_state; void *mysql_ftparam; struct charset_info_st *cs; char *doc; int length; int flags; enum enum_ftparser_mode mode; } MYSQL_FTPARSER_PARAM;
구조체 멤버는 다음과 같이 사용됩니다.
mysql_parse
: 서버의 내장 파서를 호출 콜백 함수에 대한 포인터. 플러그인이 내장 파서의 프런트 엔드로 동작하는 경우,이 콜백을 사용합니다. 즉, 플러그인의 구문 분석 함수가 호출 될 때, 그 함수는 입력을 처리하고 텍스트를 추출하고 텍스트를mysql_parse
콜백에 전달합니다.이 콜백 함수의 첫 번째 매개 변수는
param
값 자체입니다.param->mysql_parse(param, ...);
프런트 엔드 플러그인은 텍스트를 추출하여 한 번에 모든 텍스트를 내장 파서에 전달하거나 텍스트를 추출하고 한 번에 텍스트의 일부 분씩을 내장 파서에 전달할 수 있습니다. 그러나이 경우 임베디드 서버는 텍스트의 부분들 사이에 암묵적인 단어 분할이있는 것처럼 처리합니다.
mysql_add_word
: 전체 인덱스 또는 검색어 목록에 단어를 추가하는 콜백 함수의 포인터. 이 콜백은 내장 파서 파서 플러그인으로 대체 한 경우에 사용합니다. 즉, 플러그인의 구문 분석 함수가 호출 될 때 함수가 입력 단어에 구문 분석하고 각 단어에 대해mysql_add_word
콜백이 호출됩니다.이 콜백 함수의 첫 번째 매개 변수는
param
값 자체입니다.param->mysql_add_word(param, ...);
ftparser_state
: 이것은 일반적인 포인터입니다. 플러그인은 자신의 목적을 위해 내부적으로 사용되는 정보를 가리 키도록이를 설정할 수 있습니다.mysql_ftparam
: 이것은 서버에 의해 설정됩니다. 이것은 첫 번째 인수로mysql_parse
또는mysql_add_word
콜백에 전달됩니다.cs
: 텍스트 문자 집합에 대한 정보에 대한 포인터이며, 정보가없는 경우는 0입니다.doc
: 구문 분석되는 텍스트의 포인터.length
: 구문 분석되는 텍스트의 바이트 단위 길이.flags
: 파서 플래그. 특별한 플래그가 없으면 이것은 제로입니다. 현재 제로 이외의 플래그는MYSQL_FTFLAGS_NEED_COPY
뿐이며 이것은mysql_add_word()
가 단어의 사본을 보존 할 필요가있는 (즉, 단어 덮어 쓸 버퍼 내에 있기 때문에 단어 포인터를 사용할 수없는) 것을 의미합니다. 이 멤버는 MySQL 5.1.12에서 추가되었다.이 플래그는 MySQL (파서 플러그인을 호출하기 전에) 파서 플러그인 자체 또는
mysql_parse()
함수가 설정 또는 재설정 할 수 있습니다mode
: 구문 분석 모드. 이 값은 다음 상수 중 하나입니다.MYSQL_FTPARSER_SIMPLE_MODE
: 간단하고 빠른 모드에서 구문 분석하고 인덱스 설정 및 자연 언어 쿼리에 사용됩니다. 파서는 인덱스를 설정하는 단어 만 서버로 전달합니다. 파서가 길이 제한 또는 중지 단어 목록을 사용하여 무시하는 단어를 판별하는 경우 파서는 그런 단어를 서버에 전달하지 않습니다.MYSQL_FTPARSER_WITH_STOPWORDS
: 불용어 모드로 구문 분석합니다. 이 문구 조합에 대한 boolean 검색에 사용됩니다. 파서는 중지 단어와 보통의 길이 제한의 범위 외에있는 단어라도 모든 단어를 서버에 전달합니다.MYSQL_FTPARSER_FULL_BOOLEAN_INFO
: boolean 모드로 구문 분석합니다. 이것은 boolean 쿼리 문자열의 구문 분석에 사용됩니다. 파서는 단어뿐만 아니라 boolean 모드 연산자를 인식하고mysql_add_word
콜백을 사용하여 이러한 토큰으로 서버에 전달합니다. 전달되는 토큰 유형을 서버에 알리기 위해 플러그인MYSQL_FTPARSER_BOOLEAN_INFO
구조체에 값을 설정하여이 구조체에 대한 포인터를 전달해야합니다.
파서가 boolean 모드로 불려 갔을 경우
param->mode
값은MYSQL_FTPARSER_FULL_BOOLEAN_INFO
됩니다. 서버에 토큰 정보를 전달하는 파서가 사용하는MYSQL_FTPARSER_BOOLEAN_INFO
구조는 다음과 같습니다.typedef struct st_mysql_ftparser_boolean_info { enum enum_ft_token_type type; int yesno; int weight_adjust; char wasign; char trunc; /* These are parser state and must be removed. */ char prev; char *quot; } MYSQL_FTPARSER_BOOLEAN_INFO;
파서는 구조체 멤버에 다음과 같이 값을 설정합니다.
type
: 토큰 유형. 허용되는 유형을 다음 표에 나타냅니다.표 24.3 전체 파서 토큰 유형
토큰 값 의미 FT_TOKEN_EOF
데이터의 끝 FT_TOKEN_WORD
일반 단어 FT_TOKEN_LEFT_PAREN
그룹 또는 부분 식의 시작 FT_TOKEN_RIGHT_PAREN
그룹 또는 부분 식의 끝 FT_TOKEN_STOPWORD
stopword
yesno
: 일치가 발생하는 단어가 존재해야하는지 여부. 0의 경우 단어는 옵션입니다 만, 있으면 일치의 관련성이 증가하는 것을 의미합니다. 0보다 큰 값은 단어가 존재해야한다는 것을 의미합니다. 0보다 작은 값은 단어가 존재하지 않는다는 것을 의미합니다.weight_adjust
: 단어의 일치의 중요도를 결정하는 가중치 요소. 이것은 관련성 계산에서 단어의 중요성을 증가 또는 감소시키기 위해 사용할 수 있습니다. 값이 제로의 경우는 가중치에 의한 조정이 없음을 나타냅니다. 0보다 큰 값 또는 작은 값은 가중치가 큰 또는 작은 것을 각각 의미합니다.<
및>
연산자를 사용하는 섹션 12.9.2 "불리 안 전문 검색" 의 예는 가중치가 어떻게 작동하는지 보여줍니다.wasign
: 가중치 요소의 부호. 음수 값은~
boolean 검색 연산자처럼 작용하고 이는 관련성에 대한 단어의 기여도가 마이너스가됩니다.trunc
: boolean 모드*
잘라 연산자가 지정된 경우처럼 데이터를 실행할지 여부.
플러그인
MYSQL_FTPARSER_BOOLEAN_INFO
구조prev
회원 및quot
멤버를 사용하지 마십시오.참고boolean 연산자
@ distance
는 현재 플러그인 파서 프레임 워크에서 지원되지 않습니다. 불리 안 전문 검색 연산자 내용은 섹션 12.9.2 "불리 안 전문 검색" 을 참조하십시오.플러그인 인터페이스 함수를 설정합니다.
라이브러리 디스크립터의 일반 플러그인 디스크립터는 서버가 플러그인을로드 및 언로드 할 때 호출 초기화 함수 및 초기화 해제 함수를 지정합니다.
simple_parser
의 경우,이 함수는 아무것도 실시하지 않지만 성공한 것을 나타 내기 위해 제로를 돌려줍니다.static int simple_parser_plugin_init(void *arg __attribute__((unused))) { return(0); } static int simple_parser_plugin_deinit(void *arg __attribute__((unused))) { return(0); }
이 함수는 실제로 아무것도하지 않기 때문에 이들을 생략하여 플러그인 선언에서 각각 0을 지정할 수 있습니다.
simple_parser
의 유형별 플러그인 디스크립터는 플러그인이 사용되는 경우 서버가 호출 초기화 함수 초기화 해제 함수 및 구문 분석 함수를 지정합니다.simple_parser
의 경우 초기화 함수 및 초기화 해제 함수는 아무것도 실시하지 않습니다.static int simple_parser_init(MYSQL_FTPARSER_PARAM *param __attribute__((unused))) { return(0); } static int simple_parser_deinit(MYSQL_FTPARSER_PARAM *param __attribute__((unused))) { return(0); }
다시 말하지만,이 함수는 아무것도하지 않기 때문에 이들을 생략하여 플러그인 기술자 각각에 0을 지정할 수 있습니다.
주요 구문 분석 함수
simple_parser_parse()
은 내장 전체 파서 대신 작동하기 때문에 텍스트를 단어로 분할하여 각 단어를 서버에 전달해야합니다. 구문 분석 함수의 첫 번째 인수는 구문 분석하는 컨텍스트가 포함 된 구조체에 대한 포인터입니다. 이 구조체는 구문 분석되는 텍스트를 가리키는doc
멤버 및 텍스트의 길이를 나타내는length
멤버가 있습니다. 이 플러그인에 의해 실행되는 간단한 구문 분석에서는 공백이없는 문자열을 단어로 간주하므로 다음과 같이 단어를 식별합니다.static int simple_parser_parse(MYSQL_FTPARSER_PARAM *param) { char *end, *start, *docend= param->doc + param->length; for (end= start= param->doc;; end++) { if (end == docend) { if (end > start) add_word(param, start, end - start); break; } else if (isspace(*end)) { if (end > start) add_word(param, start, end - start); start= end + 1; } } return(0); }
파서는 단어를 검색 할 때마다 함수
add_word()
를 호출하여 단어를 서버에 전달합니다.add_word()
헬퍼 함수에 불과해 플러그인 인터페이스의 일부가 아닙니다. 파서는 구문 분석되는 컨텍스트에 대한 포인터 단어 포인터 및 길이 값을add_word()
에 전달합니다.static void add_word(MYSQL_FTPARSER_PARAM *param, char *word, size_t len) { MYSQL_FTPARSER_BOOLEAN_INFO bool_info= { FT_TOKEN_WORD, 0, 0, 0, 0, ' ', 0 }; param->mysql_add_word(param, word, len, &bool_info); }
boolean 모드 구문 분석의 경우 앞에
st_mysql_ftparser_boolean_info
구조의 설명에 나타낸 바와 같이,add_word()
는bool_info
구조체 멤버에 값을 설정합니다.상태 변수를 설정합니다.
simple_parser
플러그인의 경우 다음 상태 변수의 배열은 하나의 상태 변수를 정적 텍스트 값으로 설정하고 다른 상태 변수를 long 정수 변수에 저장되어있는 값으로 설정하고 있습니다.long number_of_calls= 0; struct st_mysql_show_var simple_status[]= { {"static", (char *)"just a static text", SHOW_CHAR}, {"called", (char *)&number_of_calls, SHOW_LONG}, {0,0,0} };
플러그인이 설치되면 플러그인 이름과
name
값이 밑줄로 결합되어SHOW STATUS
에 표시되는 이름이 형성됩니다. 위의 배열의 경우 생성 된 상태 변수 이름은simple_parser_static
및simple_parser_called
입니다. 이 규칙은 플러그인의 변수를 플러그인 이름을 사용하여 쉽게 볼 수 있다는 것을 의미합니다.mysql>
SHOW STATUS LIKE 'simple_parser%';
+----------------------+--------------------+ | Variable_name | Value | +----------------------+--------------------+ | simple_parser_static | just a static text | | simple_parser_called | 0 | +----------------------+--------------------+플러그인 라이브러리의 오브젝트 파일을 컴파일 및 설치하려면 섹션 24.2.4.3 "플러그인 라이브러리의 컴파일 및 설치" 단계를 사용합니다. 라이브러리 파일을 사용하려면 라이브러리 파일이 플러그인 디렉토리 (
plugin_dir
시스템 변수에 지정된 디렉토리)에 설치되어 있어야합니다.simple_parser
플러그인의 경우 소스에서 MySQL을 빌드 할 때 컴파일 및 설치됩니다. 이것은 바이너리 배포판에 포함됩니다. 빌드 프로세스에서는mypluglib.so
라는 공유 객체 라이브러리가 생성됩니다 (접미사는 플랫폼에 따라 달라질 수 있습니다.)플러그인을 사용하려면 플러그인을 서버에 등록합니다. 예를 들어, 플러그인을 실행시에 등록하려면 다음 문을 사용합니다 (필요에 따라 접미사를 변경합니다).
mysql>
INSTALL PLUGIN simple_parser SONAME 'mypluglib.so';
플러그인 로딩에 대한 추가 정보는 섹션 5.1.8.1 "플러그인 설치 및 제거" 를 참조하십시오.
플러그인의 설치를 확인하려면
INFORMATION_SCHEMA.PLUGINS
테이블을 조사하거나SHOW PLUGINS
문을 사용합니다.플러그인을 테스트하여 올바르게 작동하는지 확인합니다.
문자열 컬럼을 포함하는 테이블을 만들고 파서 플러그 인을 그 컬럼의
FULLTEXT
인덱스에 연결합니다.mysql>
CREATE TABLE t (c VARCHAR(255),
->FULLTEXT (c) WITH PARSER simple_parser
->) ENGINE=MyISAM;
Query OK, 0 rows affected (0.01 sec)이 테이블에 일부 텍스트를 삽입하여 검색을 실행합니다. 이에 따라 파서 플러그인은 공백이 아닌 모든 문자를 단어 문자로 처리하는 것이 확인됩니다.
mysql>
INSERT INTO t VALUES
->('latin1_general_cs is a case-sensitive collation'),
->('I\'d like a case of oranges'),
->('this is sensitive information'),
->('another row'),
->('yet another row');
Query OK, 5 rows affected (0.02 sec) Records: 5 Duplicates: 0 Warnings: 0 mysql>SELECT c FROM t;
+-------------------------------------------------+ | c | +-------------------------------------------------+ | latin1_general_cs is a case-sensitive collation | | I'd like a case of oranges | | this is sensitive information | | another row | | yet another row | +-------------------------------------------------+ 5 rows in set (0.00 sec) mysql>SELECT MATCH(c) AGAINST('case') FROM t;
+--------------------------+ | MATCH(c) AGAINST('case') | +--------------------------+ | 0 | | 1.2968142032623 | | 0 | | 0 | | 0 | +--------------------------+ 5 rows in set (0.00 sec) mysql>SELECT MATCH(c) AGAINST('sensitive') FROM t;
+-------------------------------+ | MATCH(c) AGAINST('sensitive') | +-------------------------------+ | 0 | | 0 | | 1.3253291845322 | | 0 | | 0 | +-------------------------------+ 5 rows in set (0.01 sec) mysql>SELECT MATCH(c) AGAINST('case-sensitive') FROM t;
+------------------------------------+ | MATCH(c) AGAINST('case-sensitive') | +------------------------------------+ | 1.3109166622162 | | 0 | | 0 | | 0 | | 0 | +------------------------------------+ 5 rows in set (0.01 sec) mysql>SELECT MATCH(c) AGAINST('I\'d') FROM t;
+--------------------------+ | MATCH(c) AGAINST('I\'d') | +--------------------------+ | 0 | | 1.2968142032623 | | 0 | | 0 | | 0 | +--------------------------+ 5 rows in set (0.01 sec)내장 파서와는 달리 "case"및 "insensitive"는 "case-insensitive"과 일치하지 않습니다.