summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2015-03-07 13:21:02 +0100
committerSergei Golubchik <serg@mariadb.org>2015-03-07 13:21:02 +0100
commit2db62f686e148f09fe5fd0b385fc71f2a3c4a133 (patch)
treecf1d5d6f0d05f1b50be96d943476173228cbd458
parent143f5d9172647a43cdcf5c27b8a78f32c9f639c0 (diff)
parentd61573d3e5c8f9d85b88f9fa2e79160b159bf67d (diff)
downloadmariadb-git-2db62f686e148f09fe5fd0b385fc71f2a3c4a133.tar.gz
Merge branch '10.0' into 10.1
-rw-r--r--CMakeLists.txt10
-rw-r--r--client/mysqlbinlog.cc9
-rw-r--r--cmake/cpack_source_ignore_files.cmake5
-rw-r--r--cmake/info_macros.cmake.in52
-rw-r--r--cmake/info_src.cmake8
-rw-r--r--cmake/maintainer.cmake2
-rw-r--r--cmake/make_dist.cmake.in19
-rw-r--r--cmake/ssl.cmake34
-rw-r--r--debian/dist/Debian/mariadb-server-10.1.postinst5
-rw-r--r--debian/dist/Ubuntu/mariadb-server-10.1.postinst7
-rw-r--r--extra/yassl/README10
-rw-r--r--extra/yassl/examples/client/client.cpp11
-rw-r--r--extra/yassl/examples/server/server.cpp23
-rw-r--r--extra/yassl/include/openssl/ssl.h2
-rw-r--r--extra/yassl/include/yassl_int.hpp21
-rw-r--r--extra/yassl/src/yassl_imp.cpp29
-rw-r--r--extra/yassl/src/yassl_int.cpp76
-rw-r--r--extra/yassl/taocrypt/src/asn.cpp8
-rw-r--r--extra/yassl/taocrypt/src/integer.cpp10
-rw-r--r--extra/yassl/testsuite/cipher-test.sh130
-rw-r--r--extra/yassl/testsuite/test.hpp42
-rw-r--r--include/mysql.h6
-rw-r--r--include/mysql.h.pp4
-rw-r--r--include/mysql_com.h3
-rw-r--r--include/welcome_copyright_notice.h6
-rw-r--r--libmysql/CMakeLists.txt3
-rw-r--r--libmysql/libmysql.c13
-rw-r--r--mysql-test/extra/binlog_tests/database.test35
-rw-r--r--mysql-test/lib/My/SafeProcess/safe_process.cc18
-rw-r--r--mysql-test/r/create.result2
-rw-r--r--mysql-test/r/ctype_binary.result6
-rw-r--r--mysql-test/r/ctype_latin1.result6
-rw-r--r--mysql-test/r/ctype_utf8.result6
-rw-r--r--mysql-test/r/derived_opt.result40
-rw-r--r--mysql-test/r/derived_view.result6
-rw-r--r--mysql-test/r/error_simulation.result21
-rw-r--r--mysql-test/r/file_contents.result2
-rw-r--r--mysql-test/r/func_set.result2
-rw-r--r--mysql-test/r/gis.result3
-rw-r--r--mysql-test/r/group_by_innodb.result44
-rw-r--r--mysql-test/r/information_schema.result15
-rw-r--r--mysql-test/r/join_cache.result13
-rw-r--r--mysql-test/r/openssl_1.result4
-rw-r--r--mysql-test/r/partition_innodb_plugin.result4
-rw-r--r--mysql-test/r/select_jcl6.result4
-rw-r--r--mysql-test/r/selectivity.result36
-rw-r--r--mysql-test/r/selectivity_innodb.result54
-rw-r--r--mysql-test/r/sp_notembedded.result19
-rw-r--r--mysql-test/r/ssl.result4
-rw-r--r--mysql-test/r/subselect_extra.result2
-rw-r--r--mysql-test/r/subselect_extra_no_semijoin.result2
-rw-r--r--mysql-test/r/subselect_mat.result51
-rw-r--r--mysql-test/r/subselect_sj2_jcl6.result4
-rw-r--r--mysql-test/r/subselect_sj_mat.result51
-rw-r--r--mysql-test/r/table_keyinfo-6838.result12
-rw-r--r--mysql-test/r/temp_table_frm.result4
-rw-r--r--mysql-test/r/tmp_table_count-7586.result83
-rw-r--r--mysql-test/r/view.result15
-rw-r--r--mysql-test/r/view_alias.result8
-rw-r--r--mysql-test/std_data/cacert.pem122
-rw-r--r--mysql-test/std_data/client-cert.pem114
-rw-r--r--mysql-test/std_data/client-key.pem38
-rw-r--r--mysql-test/std_data/server-cert.pem114
-rw-r--r--mysql-test/std_data/server-key.pem38
-rw-r--r--mysql-test/std_data/server8k-cert.pem316
-rw-r--r--mysql-test/std_data/server8k-key.pem194
-rw-r--r--mysql-test/suite/binlog/r/binlog_database.result69
-rw-r--r--mysql-test/suite/innodb/r/binlog_consistent.result11
-rw-r--r--mysql-test/suite/innodb/r/innodb-alter-table-disk-full.result55
-rw-r--r--mysql-test/suite/innodb/r/innodb-fk.result34
-rw-r--r--mysql-test/suite/innodb/r/innodb-mdev-7055.result1
-rw-r--r--mysql-test/suite/innodb/r/innodb-mdev-7408.result12
-rw-r--r--mysql-test/suite/innodb/r/innodb-mdev-7513.result204
-rw-r--r--mysql-test/suite/innodb/r/innodb_bug34300.result2
-rw-r--r--mysql-test/suite/innodb/t/binlog_consistent.test33
-rw-r--r--mysql-test/suite/innodb/t/innodb-alter-table-disk-full.test43
-rw-r--r--mysql-test/suite/innodb/t/innodb-fk.test40
-rw-r--r--mysql-test/suite/innodb/t/innodb-mdev-7055.test23
-rw-r--r--mysql-test/suite/innodb/t/innodb-mdev-7408.opt2
-rw-r--r--mysql-test/suite/innodb/t/innodb-mdev-7408.test16
-rw-r--r--mysql-test/suite/innodb/t/innodb-mdev-7513.test220
-rw-r--r--mysql-test/suite/innodb/t/innodb-mdev7046.test2
-rw-r--r--mysql-test/suite/innodb/t/innodb_bug34300.test5
-rw-r--r--mysql-test/suite/innodb/t/innodb_corrupt_bit.test9
-rw-r--r--mysql-test/suite/plugins/r/server_audit.result139
-rw-r--r--mysql-test/suite/plugins/t/server_audit.test40
-rw-r--r--mysql-test/suite/rpl/r/rpl_drop_db_fail.result16
-rw-r--r--mysql-test/suite/rpl/r/rpl_gtid_basic.result23
-rw-r--r--mysql-test/suite/rpl/r/rpl_gtid_crash.result50
-rw-r--r--mysql-test/suite/rpl/r/rpl_parallel.result74
-rw-r--r--mysql-test/suite/rpl/r/rpl_trigger.result11
-rw-r--r--mysql-test/suite/rpl/r/semisync_future-7591.result19
-rw-r--r--mysql-test/suite/rpl/t/rpl_drop_db_fail.test32
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_basic.test51
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_crash.test71
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel.test55
-rw-r--r--mysql-test/suite/rpl/t/rpl_trigger.test13
-rw-r--r--mysql-test/suite/rpl/t/semisync_future-7591.test31
-rw-r--r--mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff44
-rw-r--r--mysql-test/suite/sys_vars/r/sysvars_innodb.result2
-rw-r--r--mysql-test/t/ctype_binary.test5
-rw-r--r--mysql-test/t/ctype_latin1.test5
-rw-r--r--mysql-test/t/ctype_utf8.test5
-rw-r--r--mysql-test/t/error_simulation-master.opt1
-rw-r--r--mysql-test/t/error_simulation.test36
-rw-r--r--mysql-test/t/file_contents.test5
-rw-r--r--mysql-test/t/gis.test5
-rw-r--r--mysql-test/t/group_by_innodb.test40
-rw-r--r--mysql-test/t/information_schema.test17
-rw-r--r--mysql-test/t/join_cache.test12
-rw-r--r--mysql-test/t/openssl_1.test4
-rw-r--r--mysql-test/t/partition_innodb_plugin.test4
-rw-r--r--mysql-test/t/selectivity.test29
-rw-r--r--mysql-test/t/selectivity_innodb.test30
-rw-r--r--mysql-test/t/sp_notembedded.test20
-rw-r--r--mysql-test/t/subselect_sj_mat.test42
-rw-r--r--mysql-test/t/table_keyinfo-6838.test18
-rw-r--r--mysql-test/t/tmp_table_count-7586.test56
-rw-r--r--mysql-test/t/view.test22
-rw-r--r--mysql-test/t/view_alias.test9
-rw-r--r--mysys/my_default.c2
-rw-r--r--packaging/WiX/custom_ui.wxs4
-rw-r--r--plugin/server_audit/server_audit.c557
-rw-r--r--scripts/mysql_install_db.pl.in4
-rw-r--r--scripts/mysql_install_db.sh4
-rw-r--r--scripts/mysqld_safe.sh14
-rw-r--r--sql-common/client.c4
-rw-r--r--sql/CMakeLists.txt8
-rw-r--r--sql/handler.cc8
-rw-r--r--sql/item.h5
-rw-r--r--sql/item_cmpfunc.h5
-rw-r--r--sql/item_func.cc8
-rw-r--r--sql/item_geofunc.cc8
-rw-r--r--sql/log.cc63
-rw-r--r--sql/log_event.cc14
-rw-r--r--sql/opt_subselect.cc7
-rw-r--r--sql/rpl_parallel.cc31
-rw-r--r--sql/slave.cc18
-rw-r--r--sql/sql_acl.cc26
-rw-r--r--sql/sql_base.cc3
-rw-r--r--sql/sql_db.cc6
-rw-r--r--sql/sql_delete.cc5
-rw-r--r--sql/sql_derived.cc3
-rw-r--r--sql/sql_parse.cc12
-rw-r--r--sql/sql_select.cc56
-rw-r--r--sql/sql_select.h4
-rw-r--r--sql/sql_test.cc2
-rw-r--r--sql/sql_yacc.yy7
-rw-r--r--sql/structs.h1
-rw-r--r--sql/table.cc46
-rw-r--r--sql/table.h20
-rw-r--r--sql/udf_example.c5
-rw-r--r--storage/connect/CMakeLists.txt6
-rw-r--r--storage/connect/array.h1
-rw-r--r--storage/connect/checklvl.h7
-rw-r--r--storage/connect/connect.cc5
-rw-r--r--storage/connect/global.h2
-rw-r--r--storage/connect/ha_connect.cc272
-rw-r--r--storage/connect/json.cpp2217
-rw-r--r--storage/connect/json.h24
-rw-r--r--storage/connect/jsonudf.cpp626
-rw-r--r--storage/connect/myconn.cpp5
-rw-r--r--storage/connect/mysql-test/connect/r/json.result92
-rw-r--r--storage/connect/mysql-test/connect/r/json_udf.result167
-rw-r--r--storage/connect/mysql-test/connect/r/odbc_oracle.result10
-rw-r--r--storage/connect/mysql-test/connect/std_data/biblio.json (renamed from storage/connect/mysql-test/connect/std_data/biblio.jsn)0
-rw-r--r--storage/connect/mysql-test/connect/std_data/expense.json (renamed from storage/connect/mysql-test/connect/std_data/expense.jsn)0
-rw-r--r--storage/connect/mysql-test/connect/std_data/mulexp3.json (renamed from storage/connect/mysql-test/connect/std_data/mulexp3.jsn)0
-rw-r--r--storage/connect/mysql-test/connect/std_data/mulexp4.json (renamed from storage/connect/mysql-test/connect/std_data/mulexp4.jsn)0
-rw-r--r--storage/connect/mysql-test/connect/std_data/mulexp5.json (renamed from storage/connect/mysql-test/connect/std_data/mulexp5.jsn)0
-rw-r--r--storage/connect/mysql-test/connect/t/json.test73
-rw-r--r--storage/connect/mysql-test/connect/t/json_udf.inc36
-rw-r--r--storage/connect/mysql-test/connect/t/json_udf.test93
-rw-r--r--storage/connect/myutil.cpp22
-rw-r--r--storage/connect/odbccat.h14
-rw-r--r--storage/connect/odbconn.cpp148
-rw-r--r--storage/connect/odbconn.h20
-rw-r--r--storage/connect/plgdbutl.cpp2
-rw-r--r--storage/connect/plugutil.c2
-rw-r--r--storage/connect/tabdos.h1
-rw-r--r--storage/connect/tabjson.cpp601
-rw-r--r--storage/connect/tabjson.h30
-rw-r--r--storage/connect/tabmysql.cpp15
-rw-r--r--storage/connect/taboccur.cpp2
-rw-r--r--storage/connect/tabodbc.cpp237
-rw-r--r--storage/connect/tabodbc.h15
-rw-r--r--storage/connect/tabpivot.cpp6
-rw-r--r--storage/connect/tabpivot.h3
-rw-r--r--storage/connect/tabtbl.cpp14
-rw-r--r--storage/connect/tabutil.cpp33
-rw-r--r--storage/connect/tabutil.h9
-rw-r--r--storage/connect/tabxcl.cpp2
-rw-r--r--storage/connect/tabxcl.h1
-rw-r--r--storage/connect/valblk.h6
-rw-r--r--storage/connect/value.cpp11
-rw-r--r--storage/connect/xindex.h1
-rw-r--r--storage/connect/xobject.cpp25
-rw-r--r--storage/connect/xobject.h1
-rw-r--r--storage/federated/ha_federated.cc6
-rw-r--r--storage/innobase/btr/btr0btr.cc6
-rw-r--r--storage/innobase/btr/btr0cur.cc12
-rw-r--r--storage/innobase/dict/dict0dict.cc6
-rw-r--r--storage/innobase/dict/dict0mem.cc60
-rw-r--r--storage/innobase/fil/fil0fil.cc8
-rw-r--r--storage/innobase/fts/fts0ast.cc48
-rw-r--r--storage/innobase/fts/fts0opt.cc2
-rw-r--r--storage/innobase/fts/fts0que.cc44
-rw-r--r--storage/innobase/handler/ha_innodb.cc35
-rw-r--r--storage/innobase/handler/handler0alter.cc21
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.cc10
-rw-r--r--storage/innobase/include/buf0buf.h8
-rw-r--r--storage/innobase/include/buf0buf.ic12
-rw-r--r--storage/innobase/include/db0err.h5
-rw-r--r--storage/innobase/include/fts0ast.h7
-rw-r--r--storage/innobase/include/ha_prototypes.h2
-rw-r--r--storage/innobase/include/lock0priv.h7
-rw-r--r--storage/innobase/include/os0file.h2
-rw-r--r--storage/innobase/include/row0merge.h2
-rw-r--r--storage/innobase/include/sync0rw.ic7
-rw-r--r--storage/innobase/include/trx0roll.h4
-rw-r--r--storage/innobase/include/trx0trx.h14
-rw-r--r--storage/innobase/include/univ.i2
-rw-r--r--storage/innobase/lock/lock0lock.cc46
-rw-r--r--storage/innobase/log/log0log.cc10
-rw-r--r--storage/innobase/log/log0recv.cc1
-rw-r--r--storage/innobase/os/os0file.cc78
-rw-r--r--storage/innobase/rem/rem0rec.cc4
-rw-r--r--storage/innobase/row/row0ftsort.cc2
-rw-r--r--storage/innobase/row/row0merge.cc2
-rw-r--r--storage/innobase/row/row0mysql.cc5
-rw-r--r--storage/innobase/row/row0quiesce.cc3
-rw-r--r--storage/innobase/srv/srv0mon.cc5
-rw-r--r--storage/innobase/srv/srv0srv.cc6
-rw-r--r--storage/innobase/sync/sync0rw.cc14
-rw-r--r--storage/innobase/trx/trx0roll.cc5
-rw-r--r--storage/innobase/ut/ut0ut.cc4
-rw-r--r--storage/mroonga/CMakeLists.txt139
-rw-r--r--storage/mroonga/Makefile.am2
-rw-r--r--storage/mroonga/appveyor.yml51
-rw-r--r--storage/mroonga/configure.ac7
-rw-r--r--storage/mroonga/ha_mroonga.cpp718
-rw-r--r--storage/mroonga/ha_mroonga.hpp16
-rw-r--r--storage/mroonga/lib/mrn_database_manager.cpp44
-rw-r--r--storage/mroonga/lib/mrn_database_manager.hpp5
-rw-r--r--storage/mroonga/lib/mrn_lock.cpp6
-rw-r--r--storage/mroonga/lib/mrn_lock.hpp4
-rw-r--r--storage/mroonga/lib/mrn_parameters_parser.cpp4
-rw-r--r--storage/mroonga/lib/mrn_path_mapper.cpp5
-rw-r--r--storage/mroonga/mrn_err.h6
-rw-r--r--storage/mroonga/mrn_mysql_compat.h11
-rw-r--r--storage/mroonga/mrn_table.cpp79
-rw-r--r--storage/mroonga/mrn_table.hpp4
-rw-r--r--storage/mroonga/mysql-test/mroonga/include/mroonga/check_libgroonga_support_lz4.inc20
-rw-r--r--storage/mroonga/mysql-test/mroonga/include/mroonga/check_libgroonga_support_zlib.inc20
-rw-r--r--storage/mroonga/mysql-test/mroonga/include/mroonga/support_libgroonga_lz4.inc22
-rw-r--r--storage/mroonga/mysql-test/mroonga/include/mroonga/support_libgroonga_zlib.inc22
-rw-r--r--storage/mroonga/mysql-test/mroonga/include/mroonga/unsupport_libgroonga_lz4.inc22
-rw-r--r--storage/mroonga/mysql-test/mroonga/include/mroonga/unsupport_libgroonga_zlib.inc22
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/disabled.def1
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/alter_table_add_index_unique_multiple_column_duplicated.result19
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/alter_table_disable_keys_fulltext_table.result27
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/alter_table_enable_keys_fulltext_table.result28
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_index_fulltext_other_table.result58
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_index_fulltext_vector_other_table.result42
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_support_lz4.result10
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_support_zlib.result10
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_unsupport_lz4.result12
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_unsupport_zlib.result12
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_fulltext_index_comment.result (renamed from storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_fulltext_index.result)0
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_fulltext_index_no_utf8_charset_with_utf8_normalizer.result (renamed from storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_no_utf8_charset_with_utf8_normalizer.result)0
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_fulltext_index_none.result16
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_primary_key_table_comment.result (renamed from storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_table_comment.result)0
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/index_unique_search_after_duplicated.result18
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/information_schema_plugins.result2
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/insert_on_duplicate_key_update_unique_key.result15
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/partition_insert.result42
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/replace_without_key.result10
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_allow_column.result18
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_allow_leading_not.result16
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_allow_update.result18
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_syntax_query.result15
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_syntax_script.result16
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/variable_version.result2
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/alter_table_add_index_unique_multiple_column_duplicated.test39
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/alter_table_disable_keys_fulltext_table.test45
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/alter_table_enable_keys_fulltext_table.test46
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_index_fulltext_other_table.test32
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_index_fulltext_vector_other_table.test54
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_support_lz4.test37
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_support_zlib.test37
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_unsupport_lz4.test37
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_unsupport_zlib.test37
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_fulltext_index_comment.test (renamed from storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_fulltext_index.test)0
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_fulltext_index_no_utf8_charset_with_utf8_normalizer.test (renamed from storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_no_utf8_charset_with_utf8_normalizer.test)0
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_fulltext_index_none.test42
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_primary_key_table_comment.test (renamed from storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_table_comment.test)0
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/index_unique_search_after_duplicated.test40
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/insert_on_duplicate_key_update_unique_key.test11
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/partition_insert.test49
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/replace_without_key.test35
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_allow_column.test43
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_allow_leading_not.test41
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_allow_update.test43
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_syntax_query.test40
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_syntax_script.test41
-rw-r--r--storage/mroonga/packages/Makefile.am7
-rw-r--r--storage/mroonga/packages/apt/Makefile.am67
-rw-r--r--storage/mroonga/packages/apt/Vagrantfile29
-rwxr-xr-xstorage/mroonga/packages/apt/build-deb.sh78
-rw-r--r--storage/mroonga/packages/apt/env.sh.in15
-rwxr-xr-xstorage/mroonga/packages/apt/sign-packages.sh42
-rwxr-xr-xstorage/mroonga/packages/apt/sign-repository.sh46
-rwxr-xr-xstorage/mroonga/packages/apt/update-repository.sh130
-rwxr-xr-xstorage/mroonga/packages/check-utility.sh665
-rw-r--r--storage/mroonga/packages/debian/apparmor/mysql-server-mroonga5
-rw-r--r--storage/mroonga/packages/debian/changelog391
-rw-r--r--storage/mroonga/packages/debian/compat1
-rw-r--r--storage/mroonga/packages/debian/control.in51
-rw-r--r--storage/mroonga/packages/debian/copyright27
-rw-r--r--storage/mroonga/packages/debian/mysql-server-mroonga-doc.install1
-rw-r--r--storage/mroonga/packages/debian/mysql-server-mroonga.install3
-rwxr-xr-xstorage/mroonga/packages/debian/mysql-server-mroonga.postinst72
-rwxr-xr-xstorage/mroonga/packages/debian/mysql-server-mroonga.postrm38
-rwxr-xr-xstorage/mroonga/packages/debian/mysql-server-mroonga.prerm10
-rwxr-xr-xstorage/mroonga/packages/debian/rules39
-rw-r--r--storage/mroonga/packages/rpm/Makefile.am2
-rw-r--r--storage/mroonga/packages/rpm/centos/Makefile.am9
-rw-r--r--storage/mroonga/packages/rpm/centos/mariadb-mroonga.spec.in396
-rw-r--r--storage/mroonga/packages/rpm/centos/mysql55-mroonga.spec.in218
-rw-r--r--storage/mroonga/packages/rpm/centos/mysql56-community-mroonga.spec.in222
-rw-r--r--storage/mroonga/packages/source/Makefile.am123
-rw-r--r--storage/mroonga/packages/source/patches/mariadb-10.0.3-windows-build.diff9
-rw-r--r--storage/mroonga/packages/ubuntu/Makefile.am24
-rwxr-xr-xstorage/mroonga/packages/ubuntu/upload.rb168
-rw-r--r--storage/mroonga/packages/windows/Makefile.am12
-rw-r--r--storage/mroonga/packages/windows/README.md20
-rw-r--r--storage/mroonga/packages/windows/build-vc2010-msi-32.bat8
-rw-r--r--storage/mroonga/packages/windows/build-vc2010-msi-64.bat8
-rw-r--r--storage/mroonga/packages/windows/build-vc2010-zip-32.bat8
-rw-r--r--storage/mroonga/packages/windows/build-vc2010-zip-64.bat8
-rw-r--r--storage/mroonga/packages/windows/build-vc2010.bat4
-rw-r--r--storage/mroonga/packages/windows/build-vc2013-msi-32.bat8
-rw-r--r--storage/mroonga/packages/windows/build-vc2013-msi-64.bat8
-rw-r--r--storage/mroonga/packages/windows/build-vc2013-zip-32.bat8
-rw-r--r--storage/mroonga/packages/windows/build-vc2013-zip-64.bat8
-rw-r--r--storage/mroonga/packages/windows/build-vc2013.bat4
-rw-r--r--storage/mroonga/packages/yum/Makefile.am63
-rw-r--r--storage/mroonga/packages/yum/Vagrantfile50
-rwxr-xr-xstorage/mroonga/packages/yum/build-in-vm.sh60
-rwxr-xr-xstorage/mroonga/packages/yum/build-rpm.sh108
-rw-r--r--storage/mroonga/packages/yum/env.sh.in27
-rwxr-xr-xstorage/mroonga/packages/yum/sign-rpm.sh52
-rwxr-xr-xstorage/mroonga/packages/yum/update-repository.sh29
-rw-r--r--storage/mroonga/plugin_version2
-rw-r--r--storage/mroonga/required_groonga_version2
-rwxr-xr-xstorage/mroonga/tools/travis/install.sh8
-rw-r--r--storage/mroonga/udf/mrn_udf_command.cpp8
-rw-r--r--storage/mroonga/udf/mrn_udf_escape.cpp4
-rw-r--r--storage/mroonga/udf/mrn_udf_snippet.cpp4
-rw-r--r--storage/mroonga/vendor/groonga/CMakeLists.txt132
-rw-r--r--storage/mroonga/vendor/groonga/Makefile.am1
-rw-r--r--storage/mroonga/vendor/groonga/appveyor.yml17
-rwxr-xr-xstorage/mroonga/vendor/groonga/autogen.sh5
-rw-r--r--storage/mroonga/vendor/groonga/base_version2
-rw-r--r--storage/mroonga/vendor/groonga/benchmark/bench-geo-distance.c2
-rw-r--r--storage/mroonga/vendor/groonga/benchmark/bench-geo-select.c2
-rw-r--r--storage/mroonga/vendor/groonga/benchmark/bench-range-select.c2
-rw-r--r--storage/mroonga/vendor/groonga/build/ac_macros/check_functions.m45
-rw-r--r--storage/mroonga/vendor/groonga/build/ac_macros/check_headers.m42
-rw-r--r--storage/mroonga/vendor/groonga/config.h.cmake10
-rw-r--r--storage/mroonga/vendor/groonga/config.sh.in1
-rw-r--r--storage/mroonga/vendor/groonga/configure.ac175
-rw-r--r--storage/mroonga/vendor/groonga/examples/Makefile.am1
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/Makefile.am34
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/edict/Makefile.am4
-rwxr-xr-xstorage/mroonga/vendor/groonga/examples/dictionary/edict/edict-import.sh21
-rwxr-xr-xstorage/mroonga/vendor/groonga/examples/dictionary/edict/edict2grn.rb56
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/eijiro/Makefile.am4
-rwxr-xr-xstorage/mroonga/vendor/groonga/examples/dictionary/eijiro/eijiro-import.sh12
-rwxr-xr-xstorage/mroonga/vendor/groonga/examples/dictionary/eijiro/eijiro2grn.rb61
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/gene95/Makefile.am4
-rwxr-xr-xstorage/mroonga/vendor/groonga/examples/dictionary/gene95/gene-import.sh26
-rwxr-xr-xstorage/mroonga/vendor/groonga/examples/dictionary/gene95/gene2grn.rb46
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/html/css/dictionary.css3
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.pngbin0 -> 180 bytes
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.pngbin0 -> 178 bytes
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.pngbin0 -> 120 bytes
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.pngbin0 -> 105 bytes
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_75_dadada_1x400.pngbin0 -> 111 bytes
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.pngbin0 -> 110 bytes
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.pngbin0 -> 119 bytes
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.pngbin0 -> 101 bytes
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_222222_256x240.pngbin0 -> 4369 bytes
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_2e83ff_256x240.pngbin0 -> 4369 bytes
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_454545_256x240.pngbin0 -> 4369 bytes
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_888888_256x240.pngbin0 -> 4369 bytes
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_cd0a0a_256x240.pngbin0 -> 4369 bytes
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/jquery-ui-1.8.12.custom.css578
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/html/index.html28
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/html/js/dictionary.js82
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-1.7.2.js9404
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-ui-1.8.18.custom.js11802
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-ui-1.8.18.custom.min.js356
-rwxr-xr-xstorage/mroonga/vendor/groonga/examples/dictionary/init-db.sh10
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/jmdict/Makefile.am3
-rwxr-xr-xstorage/mroonga/vendor/groonga/examples/dictionary/jmdict/jmdict.rb42
-rw-r--r--storage/mroonga/vendor/groonga/examples/dictionary/readme.txt71
-rw-r--r--storage/mroonga/vendor/groonga/groonga-httpd-conf.sh.in4
-rw-r--r--storage/mroonga/vendor/groonga/include/CMakeLists.txt8
-rw-r--r--storage/mroonga/vendor/groonga/include/groonga.h2093
-rw-r--r--storage/mroonga/vendor/groonga/include/groonga/Makefile.am11
-rw-r--r--storage/mroonga/vendor/groonga/include/groonga/command.h79
-rw-r--r--storage/mroonga/vendor/groonga/include/groonga/expr.h108
-rw-r--r--storage/mroonga/vendor/groonga/include/groonga/groonga.h1994
-rw-r--r--storage/mroonga/vendor/groonga/include/groonga/ii.h46
-rw-r--r--storage/mroonga/vendor/groonga/include/groonga/nfkc.h6
-rw-r--r--storage/mroonga/vendor/groonga/include/groonga/obj.h37
-rw-r--r--storage/mroonga/vendor/groonga/include/groonga/output.h108
-rw-r--r--storage/mroonga/vendor/groonga/include/groonga/plugin.h29
-rw-r--r--storage/mroonga/vendor/groonga/include/groonga/request_canceler.h39
-rw-r--r--storage/mroonga/vendor/groonga/include/groonga/scorer.h88
-rw-r--r--storage/mroonga/vendor/groonga/include/groonga/token.h136
-rw-r--r--storage/mroonga/vendor/groonga/include/groonga/token_filter.h10
-rw-r--r--storage/mroonga/vendor/groonga/include/groonga/tokenizer.h115
-rw-r--r--storage/mroonga/vendor/groonga/include/groonga/util.h (renamed from storage/mroonga/vendor/groonga/lib/util.h)34
-rw-r--r--storage/mroonga/vendor/groonga/lib/CMakeLists.txt59
-rw-r--r--storage/mroonga/vendor/groonga/lib/Makefile.am33
-rw-r--r--storage/mroonga/vendor/groonga/lib/com.c138
-rw-r--r--storage/mroonga/vendor/groonga/lib/command.c194
-rw-r--r--storage/mroonga/vendor/groonga/lib/ctx.c257
-rw-r--r--storage/mroonga/vendor/groonga/lib/ctx_impl_mrb.c155
-rw-r--r--storage/mroonga/vendor/groonga/lib/dat.cpp27
-rw-r--r--storage/mroonga/vendor/groonga/lib/dat/Makefile.am3
-rw-r--r--storage/mroonga/vendor/groonga/lib/dat/dat.hpp12
-rw-r--r--storage/mroonga/vendor/groonga/lib/dat/file-impl.cpp12
-rw-r--r--storage/mroonga/vendor/groonga/lib/db.c2183
-rw-r--r--storage/mroonga/vendor/groonga/lib/error.c31
-rw-r--r--storage/mroonga/vendor/groonga/lib/expr.c1631
-rw-r--r--storage/mroonga/vendor/groonga/lib/geo.c42
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn.h (renamed from storage/mroonga/vendor/groonga/lib/groonga_in.h)369
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_com.h (renamed from storage/mroonga/vendor/groonga/lib/com.h)14
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_ctx.h (renamed from storage/mroonga/vendor/groonga/lib/ctx.h)134
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_ctx_impl.h (renamed from storage/mroonga/vendor/groonga/lib/ctx_impl.h)19
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_ctx_impl_mrb.h (renamed from storage/mroonga/vendor/groonga/lib/ctx_impl_mrb.h)4
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_dat.h (renamed from storage/mroonga/vendor/groonga/lib/dat.h)22
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_db.h (renamed from storage/mroonga/vendor/groonga/lib/db.h)61
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_ecmascript.c (renamed from storage/mroonga/vendor/groonga/lib/ecmascript.c)300
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_ecmascript.h (renamed from storage/mroonga/vendor/groonga/lib/ecmascript.h)0
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_ecmascript.lemon (renamed from storage/mroonga/vendor/groonga/lib/ecmascript.lemon)0
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_error.h (renamed from storage/mroonga/vendor/groonga/lib/error.h)8
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_expr.h (renamed from storage/mroonga/vendor/groonga/lib/expr.h)6
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_geo.h (renamed from storage/mroonga/vendor/groonga/lib/geo.h)10
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_hash.h (renamed from storage/mroonga/vendor/groonga/lib/hash.h)9
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_ii.h (renamed from storage/mroonga/vendor/groonga/lib/ii.h)25
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_io.h (renamed from storage/mroonga/vendor/groonga/lib/io.h)38
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_mrb.h (renamed from storage/mroonga/vendor/groonga/lib/mrb.h)7
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_normalizer.h (renamed from storage/mroonga/vendor/groonga/lib/normalizer_in.h)20
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_output.h (renamed from storage/mroonga/vendor/groonga/lib/output.h)38
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_pat.h (renamed from storage/mroonga/vendor/groonga/lib/pat.h)9
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_plugin.h (renamed from storage/mroonga/vendor/groonga/lib/plugin_in.h)21
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_proc.h (renamed from storage/mroonga/vendor/groonga/lib/proc.h)4
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_request_canceler.h31
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_rset.h115
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_scorer.h49
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_scorers.h33
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_snip.h (renamed from storage/mroonga/vendor/groonga/lib/snip.h)10
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_store.h (renamed from storage/mroonga/vendor/groonga/lib/store.h)19
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_str.h (renamed from storage/mroonga/vendor/groonga/lib/str.h)9
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_string.h (renamed from storage/mroonga/vendor/groonga/lib/string_in.h)16
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_token_cursor.h (renamed from storage/mroonga/vendor/groonga/lib/token.h)53
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_tokenizers.h38
-rw-r--r--storage/mroonga/vendor/groonga/lib/grn_util.h36
-rw-r--r--storage/mroonga/vendor/groonga/lib/hash.c8
-rw-r--r--storage/mroonga/vendor/groonga/lib/ii.c721
-rw-r--r--storage/mroonga/vendor/groonga/lib/io.c833
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb.c94
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.c4
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.h4
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_array.c60
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_array.h34
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.c115
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.h11
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_column.c39
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_column.h2
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_command.c180
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_command.h36
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_command_input.c122
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_command_input.h34
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.c104
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.h9
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.c43
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.h4
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_database.c124
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_database.h34
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_double_array_trie.c60
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_double_array_trie.h34
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_error.c161
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_error.h2
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.c256
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.h4
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.c2
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.h2
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_hash_table.c60
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_hash_table.h34
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_id.c7
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_id.h2
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.c2
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.h2
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_index_cursor.c128
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_index_cursor.h34
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.c4
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.h2
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_object.c (renamed from storage/mroonga/vendor/groonga/lib/mrb/mrb_obj.c)67
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_object.h34
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.c2
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.h2
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_patricia_trie.c59
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_patricia_trie.h34
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.c14
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.h2
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_table.c226
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_table.h34
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor.c211
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor.h34
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor_flags.c60
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor_flags.h34
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_type.c60
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_type.h (renamed from storage/mroonga/vendor/groonga/lib/mrb/mrb_obj.h)12
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.c2
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.h2
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_void.c4
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_void.h2
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_writer.c223
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/mrb_writer.h34
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/scripts/command.rb35
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/grndb.rb169
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/scripts/context.rb37
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/scripts/context/rc.rb242
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/scripts/database.rb39
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/scripts/error.rb16
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/scripts/index_cursor.rb18
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/post.rb14
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/pre.rb1
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/scripts/logger.rb6
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/scripts/plugin_loader.rb14
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/scripts/require.rb68
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info.rb3
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_builder.rb28
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data.rb65
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/scripts/sources.am13
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/scripts/table_cursor.rb26
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/scripts/writer.rb21
-rw-r--r--storage/mroonga/vendor/groonga/lib/mrb/sources.am32
-rw-r--r--storage/mroonga/vendor/groonga/lib/nfkc.c5
-rw-r--r--storage/mroonga/vendor/groonga/lib/normalizer.c4
-rw-r--r--storage/mroonga/vendor/groonga/lib/obj.c106
-rw-r--r--storage/mroonga/vendor/groonga/lib/operator.c596
-rw-r--r--storage/mroonga/vendor/groonga/lib/output.c202
-rw-r--r--storage/mroonga/vendor/groonga/lib/pat.c16
-rw-r--r--storage/mroonga/vendor/groonga/lib/plugin.c395
-rw-r--r--storage/mroonga/vendor/groonga/lib/proc.c2029
-rw-r--r--storage/mroonga/vendor/groonga/lib/request_canceler.c123
-rw-r--r--storage/mroonga/vendor/groonga/lib/rset.c324
-rw-r--r--storage/mroonga/vendor/groonga/lib/scorer.c134
-rw-r--r--storage/mroonga/vendor/groonga/lib/scorers.c57
-rw-r--r--storage/mroonga/vendor/groonga/lib/snip.c6
-rw-r--r--storage/mroonga/vendor/groonga/lib/sources.am65
-rw-r--r--storage/mroonga/vendor/groonga/lib/store.c174
-rw-r--r--storage/mroonga/vendor/groonga/lib/str.c26
-rw-r--r--storage/mroonga/vendor/groonga/lib/string.c10
-rw-r--r--storage/mroonga/vendor/groonga/lib/token_cursor.c357
-rw-r--r--storage/mroonga/vendor/groonga/lib/token_filter.c4
-rw-r--r--storage/mroonga/vendor/groonga/lib/tokenizer.c37
-rw-r--r--storage/mroonga/vendor/groonga/lib/tokenizers.c (renamed from storage/mroonga/vendor/groonga/lib/token.c)393
-rw-r--r--storage/mroonga/vendor/groonga/lib/util.c191
-rw-r--r--storage/mroonga/vendor/groonga/nginx_version2
-rw-r--r--storage/mroonga/vendor/groonga/plugins/CMakeLists.txt9
-rw-r--r--storage/mroonga/vendor/groonga/plugins/Makefile.am10
-rw-r--r--storage/mroonga/vendor/groonga/plugins/query_expanders/CMakeLists.txt4
-rw-r--r--storage/mroonga/vendor/groonga/plugins/query_expanders/tsv.c10
-rw-r--r--storage/mroonga/vendor/groonga/plugins/ruby/CMakeLists.txt8
-rw-r--r--storage/mroonga/vendor/groonga/plugins/ruby/ruby_plugin.h10
-rw-r--r--storage/mroonga/vendor/groonga/plugins/ruby_scripts.am2
-rw-r--r--storage/mroonga/vendor/groonga/plugins/sharding.rb3
-rw-r--r--storage/mroonga/vendor/groonga/plugins/sharding/CMakeLists.txt22
-rw-r--r--storage/mroonga/vendor/groonga/plugins/sharding/Makefile.am9
-rw-r--r--storage/mroonga/vendor/groonga/plugins/sharding/logical_count.rb160
-rw-r--r--storage/mroonga/vendor/groonga/plugins/sharding/logical_enumerator.rb170
-rw-r--r--storage/mroonga/vendor/groonga/plugins/sharding/logical_range_filter.rb186
-rw-r--r--storage/mroonga/vendor/groonga/plugins/sharding/sources.am4
-rw-r--r--storage/mroonga/vendor/groonga/plugins/suggest/CMakeLists.txt4
-rw-r--r--storage/mroonga/vendor/groonga/plugins/suggest/suggest.c47
-rw-r--r--storage/mroonga/vendor/groonga/plugins/table/CMakeLists.txt4
-rw-r--r--storage/mroonga/vendor/groonga/plugins/table/table.c8
-rw-r--r--storage/mroonga/vendor/groonga/plugins/token_filters/CMakeLists.txt17
-rw-r--r--storage/mroonga/vendor/groonga/plugins/token_filters/Makefile.am8
-rw-r--r--storage/mroonga/vendor/groonga/plugins/token_filters/stem.c275
-rw-r--r--storage/mroonga/vendor/groonga/plugins/token_filters/stem_sources.am2
-rw-r--r--storage/mroonga/vendor/groonga/plugins/token_filters/stop_word.c4
-rw-r--r--storage/mroonga/vendor/groonga/plugins/tokenizers/CMakeLists.txt8
-rw-r--r--storage/mroonga/vendor/groonga/plugins/tokenizers/mecab.c24
-rw-r--r--storage/mroonga/vendor/groonga/src/CMakeLists.txt12
-rw-r--r--storage/mroonga/vendor/groonga/src/Makefile.am19
-rw-r--r--storage/mroonga/vendor/groonga/src/grndb.c137
-rw-r--r--storage/mroonga/vendor/groonga/src/grndb_sources.am2
-rw-r--r--storage/mroonga/vendor/groonga/src/grnslap.c8
-rw-r--r--storage/mroonga/vendor/groonga/src/groonga.c487
-rw-r--r--storage/mroonga/vendor/groonga/src/groonga_benchmark.c41
-rw-r--r--storage/mroonga/vendor/groonga/src/groonga_mruby.c84
-rw-r--r--storage/mroonga/vendor/groonga/src/groonga_mruby_sources.am2
-rw-r--r--storage/mroonga/vendor/groonga/src/httpd/nginx-module/ngx_http_groonga_module.c269
-rw-r--r--storage/mroonga/vendor/groonga/src/suggest/CMakeLists.txt16
-rw-r--r--storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_create_dataset.c2
-rw-r--r--storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_httpd.c2
-rw-r--r--storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_learner.c2
-rwxr-xr-xstorage/mroonga/vendor/groonga/tools/travis-before-script.sh62
-rwxr-xr-xstorage/mroonga/vendor/groonga/tools/travis-install.sh31
-rwxr-xr-xstorage/mroonga/vendor/groonga/tools/travis-script.sh24
-rw-r--r--storage/mroonga/vendor/groonga/vendor/Makefile.am1
-rw-r--r--storage/mroonga/vendor/groonga/vendor/mruby/CMakeLists.txt2
-rw-r--r--storage/mroonga/vendor/groonga/vendor/mruby/Makefile.am32
-rw-r--r--storage/mroonga/vendor/groonga/vendor/mruby/build_config.rb3
-rw-r--r--storage/mroonga/vendor/groonga/vendor/onigmo/Makefile.am11
-rw-r--r--storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/AUTHORS1
-rw-r--r--storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/CMakeLists.txt23
-rw-r--r--storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/ChangeLog0
-rw-r--r--storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/INSTALL1
-rw-r--r--storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/NEWS1
-rw-r--r--storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/README1
-rw-r--r--storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/README.md18
-rw-r--r--storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/configure.ac34
-rw-r--r--storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/doc/text/Makefile.am5
-rw-r--r--storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/doc/text/news.md12
-rw-r--r--storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/normalizers/CMakeLists.txt18
-rw-r--r--storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/normalizers/mysql.c10
-rw-r--r--storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/apt/Vagrantfile5
-rwxr-xr-xstorage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/apt/build-deb.sh2
-rw-r--r--storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/changelog12
-rw-r--r--storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/control20
-rw-r--r--storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/copyright98
-rwxr-xr-xstorage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/rules2
-rw-r--r--storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/watch2
-rw-r--r--storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/rpm/centos/groonga-normalizer-mysql.spec.in7
-rw-r--r--storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/rpm/fedora/groonga-normalizer-mysql.spec.in7
-rw-r--r--storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/ubuntu/Makefile.am2
-rw-r--r--storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/yum/Makefile.am1
-rw-r--r--storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/yum/Vagrantfile8
-rw-r--r--storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/version2
-rw-r--r--storage/mroonga/version2
-rw-r--r--storage/mroonga/version_in_hex2
-rw-r--r--storage/mroonga/version_major2
-rw-r--r--storage/mroonga/version_micro2
-rw-r--r--storage/spider/CMakeLists.txt5
-rw-r--r--storage/spider/ha_spider.cc87
-rw-r--r--storage/spider/ha_spider.h7
-rw-r--r--storage/spider/spd_conn.cc1
-rw-r--r--storage/spider/spd_copy_tables.cc1
-rw-r--r--storage/spider/spd_db_conn.cc97
-rw-r--r--storage/spider/spd_db_handlersocket.cc3
-rw-r--r--storage/spider/spd_db_include.h9
-rw-r--r--storage/spider/spd_db_mysql.cc8
-rw-r--r--storage/spider/spd_db_oracle.cc3
-rw-r--r--storage/spider/spd_direct_sql.cc1
-rw-r--r--storage/spider/spd_i_s.cc1
-rw-r--r--storage/spider/spd_include.h8
-rw-r--r--storage/spider/spd_malloc.cc1
-rw-r--r--storage/spider/spd_param.cc1
-rw-r--r--storage/spider/spd_ping_table.cc1
-rw-r--r--storage/spider/spd_sys_table.cc1
-rw-r--r--storage/spider/spd_table.cc99
-rw-r--r--storage/spider/spd_table.h5
-rw-r--r--storage/spider/spd_trx.cc1
-rw-r--r--storage/tokudb/CMakeLists.txt2
-rw-r--r--storage/tokudb/doc2/sysbench.update.ma10.tokudb754.loglog.pngbin6947 -> 7209 bytes
-rw-r--r--storage/tokudb/doc2/sysbench.update.ma10.tokudb754.pngbin7351 -> 7527 bytes
-rw-r--r--storage/tokudb/ha_tokudb.cc43
-rw-r--r--storage/tokudb/ha_tokudb_admin.cc39
-rw-r--r--storage/tokudb/hatoku_defines.h3
-rw-r--r--storage/tokudb/hatoku_hton.cc50
-rw-r--r--storage/tokudb/hatoku_hton.h9
-rw-r--r--storage/tokudb/mysql-test/rpl/disabled.def3
-rw-r--r--storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_ff.result14
-rw-r--r--storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_ft.result14
-rw-r--r--storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_tf.result14
-rw-r--r--storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_tt.result14
-rw-r--r--storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_ff-slave.opt1
-rw-r--r--storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_ff.test53
-rw-r--r--storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_ft-slave.opt1
-rw-r--r--storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_ft.test53
-rw-r--r--storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_tf-slave.opt1
-rw-r--r--storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_tf.test53
-rw-r--r--storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_tt-slave.opt1
-rw-r--r--storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_tt.test53
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/r/db788-optimize-index-name.result19
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/r/db801.result18
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/r/memcache_dirty.result14
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/db788-optimize-index-name.test21
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/db801.test50
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/memcache_dirty.test25
-rw-r--r--storage/tokudb/scripts/common.sh24
-rwxr-xr-xstorage/tokudb/scripts/make.mysql.bash15
-rwxr-xr-xstorage/tokudb/scripts/make.mysql.debug.env.bash6
-rw-r--r--storage/xtradb/CMakeLists.txt8
-rw-r--r--storage/xtradb/btr/btr0btr.cc6
-rw-r--r--storage/xtradb/buf/buf0buf.cc11
-rw-r--r--storage/xtradb/buf/buf0flu.cc6
-rw-r--r--storage/xtradb/buf/buf0lru.cc2
-rw-r--r--storage/xtradb/buf/buf0rea.cc8
-rw-r--r--storage/xtradb/fil/fil0fil.cc7
-rw-r--r--storage/xtradb/handler/ha_innodb.cc23
-rw-r--r--storage/xtradb/handler/i_s.cc5
-rw-r--r--storage/xtradb/ibuf/ibuf0ibuf.cc6
-rw-r--r--storage/xtradb/include/buf0flu.h4
-rw-r--r--storage/xtradb/include/lock0priv.h7
-rw-r--r--storage/xtradb/include/sync0rw.ic7
-rw-r--r--storage/xtradb/include/sync0sync.h1
-rw-r--r--storage/xtradb/include/trx0trx.h15
-rw-r--r--storage/xtradb/include/univ.i2
-rw-r--r--storage/xtradb/lock/lock0lock.cc43
-rw-r--r--storage/xtradb/os/os0file.cc16
-rw-r--r--storage/xtradb/rem/rem0rec.cc4
-rw-r--r--storage/xtradb/row/row0mysql.cc1
-rw-r--r--storage/xtradb/srv/srv0start.cc39
-rw-r--r--storage/xtradb/sync/sync0rw.cc14
-rw-r--r--support-files/mysql.server.sh3
-rw-r--r--vio/viosslfactories.c6
-rw-r--r--win/packaging/heidisql.cmake2
-rw-r--r--win/packaging/heidisql.wxi.in28
728 files changed, 54939 insertions, 9767 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 196b60731da..3ca49a9ee4b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -335,6 +335,11 @@ CHECK_JEMALLOC()
CHECK_PCRE()
+IF(CMAKE_CROSSCOMPILING)
+ SET(IMPORT_EXECUTABLES "IMPORTFILE-NOTFOUND" CACHE FILEPATH "Path to import_executables.cmake from a native build")
+ INCLUDE(${IMPORT_EXECUTABLES})
+ENDIF()
+
#
# Setup maintainer mode options. Platform checks are
# not run with the warning options as to not perturb fragile checks
@@ -427,7 +432,8 @@ CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/include/mysql_version.h.in
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/sql/sql_builtin.cc.in
${CMAKE_BINARY_DIR}/sql/sql_builtin.cc)
CONFIGURE_FILE(
- ${CMAKE_SOURCE_DIR}/cmake/info_macros.cmake.in ${CMAKE_BINARY_DIR}/info_macros.cmake @ONLY)
+ ${CMAKE_SOURCE_DIR}/cmake/info_macros.cmake.in
+ ${CMAKE_BINARY_DIR}/info_macros.cmake @ONLY)
IF(DEB)
CONFIGURE_FILE(
@@ -439,7 +445,7 @@ ENDIF(DEB)
INCLUDE(${CMAKE_BINARY_DIR}/info_macros.cmake)
# Source: This can be done during the cmake phase, all information is
# available, but should be repeated on each "make" just in case someone
-# does "cmake ; make ; bzr pull ; make".
+# does "cmake ; make ; git pull ; make".
CREATE_INFO_SRC(${CMAKE_BINARY_DIR}/Docs)
ADD_CUSTOM_TARGET(INFO_SRC ALL
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/cmake/info_src.cmake
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index 7c93e8d3ebd..7a54a693cb4 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -49,6 +49,8 @@
#include "mysqld.h"
+#include <algorithm>
+
Rpl_filter *binlog_filter= 0;
#define BIN_LOG_HEADER_SIZE 4
@@ -67,6 +69,7 @@ ulong server_id = 0;
ulong bytes_sent = 0L, bytes_received = 0L;
ulong mysqld_net_retry_count = 10L;
ulong open_files_limit;
+ulong opt_binlog_rows_event_max_size;
uint test_flags = 0;
static uint opt_protocol= 0;
static FILE *result_file;
@@ -1436,6 +1439,12 @@ that may lead to an endless loop.",
"Used to reserve file descriptors for use by this program.",
&open_files_limit, &open_files_limit, 0, GET_ULONG,
REQUIRED_ARG, MY_NFILE, 8, OS_FILE_LIMIT, 0, 1, 0},
+ {"binlog-row-event-max-size", 0,
+ "The maximum size of a row-based binary log event in bytes. Rows will be "
+ "grouped into events smaller than this size if possible. "
+ "This value must be a multiple of 256.",
+ &opt_binlog_rows_event_max_size, &opt_binlog_rows_event_max_size, 0,
+ GET_ULONG, REQUIRED_ARG, UINT_MAX, 256, ULONG_MAX, 0, 256, 0},
{"verify-binlog-checksum", 'c', "Verify checksum binlog events.",
(uchar**) &opt_verify_binlog_checksum, (uchar**) &opt_verify_binlog_checksum,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
diff --git a/cmake/cpack_source_ignore_files.cmake b/cmake/cpack_source_ignore_files.cmake
index 7ee496245f8..0654fa38388 100644
--- a/cmake/cpack_source_ignore_files.cmake
+++ b/cmake/cpack_source_ignore_files.cmake
@@ -1,4 +1,4 @@
-# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -14,9 +14,6 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
SET(CPACK_SOURCE_IGNORE_FILES
-\\\\.bzr/
-\\\\.bzr-mysql
-\\\\.bzrignore
\\\\.git/
\\\\.gitignore
CMakeCache\\\\.txt
diff --git a/cmake/info_macros.cmake.in b/cmake/info_macros.cmake.in
index 321ff7d4799..89b04666c96 100644
--- a/cmake/info_macros.cmake.in
+++ b/cmake/info_macros.cmake.in
@@ -1,4 +1,4 @@
-# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -23,11 +23,13 @@
# If further variables are used in this file, add them to this list.
SET(VERSION "@VERSION@")
+SET(MAJOR_VERSION "@MAJOR_VERSION@")
+SET(MINOR_VERSION "@MINOR_VERSION@")
+SET(PATCH_VERSION "@PATCH_VERSION@")
SET(CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@")
SET(CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@")
SET(CMAKE_GENERATOR "@CMAKE_GENERATOR@")
SET(CMAKE_SIZEOF_VOID_P "@CMAKE_SIZEOF_VOID_P@")
-SET(BZR_EXECUTABLE "@BZR_EXECUTABLE@")
SET(GIT_EXECUTABLE "@GIT_EXECUTABLE@")
SET(CMAKE_CROSSCOMPILING "@CMAKE_CROSSCOMPILING@")
SET(CMAKE_HOST_SYSTEM "@CMAKE_HOST_SYSTEM@")
@@ -37,39 +39,51 @@ SET(CMAKE_SYSTEM_PROCESSOR "@CMAKE_SYSTEM_PROCESSOR@")
# Create an "INFO_SRC" file with information about the source (only).
-# We use "bzr version-info", if possible, and the "VERSION" contents.
+# We use "git log", if possible, and the "VERSION" contents.
#
-# Outside development (BZR tree), the "INFO_SRC" file will not be modified
+# Outside development (git tree), the "INFO_SRC" file will not be modified
# provided it exists (from "make dist" or a source tarball creation).
MACRO(CREATE_INFO_SRC target_dir)
SET(INFO_SRC "${target_dir}/INFO_SRC")
- IF(EXISTS ${CMAKE_SOURCE_DIR}/.bzr)
- # Sources are in a BZR repository: Always update.
+ SET(PERLSCRIPT
+ "use warnings; use POSIX qw(strftime); "
+ "print strftime \"%F %T %z\", localtime;")
+ EXECUTE_PROCESS(
+ COMMAND perl -e "${PERLSCRIPT}"
+ RESULT_VARIABLE result
+ OUTPUT_VARIABLE bdate
+ ERROR_VARIABLE error
+ )
+ IF(error)
+ MESSAGE(STATUS "Could not determine build-date: <${error}>")
+ ENDIF()
+
+ IF(GIT_EXECUTABLE AND EXISTS ${CMAKE_SOURCE_DIR}/.git)
+ # Sources are in a GIT repository: Always update.
EXECUTE_PROCESS(
- COMMAND ${BZR_EXECUTABLE} version-info ${CMAKE_SOURCE_DIR}
- OUTPUT_VARIABLE VERSION_INFO
- RESULT_VARIABLE RESULT
+ COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ OUTPUT_VARIABLE bname
)
- FILE(WRITE ${INFO_SRC} "${VERSION_INFO}\n")
- # to debug, add: FILE(APPEND ${INFO_SRC} "\nResult ${RESULT}\n")
- # For better readability ...
- FILE(APPEND ${INFO_SRC} "\nMariaDB source ${VERSION}\n")
- ELSEIF(EXISTS ${CMAKE_SOURCE_DIR}/.git)
- # Sources are in a GIT repository: Always update.
+
EXECUTE_PROCESS(
- COMMAND ${GIT_EXECUTABLE} log -1 "--format=commit: %H%nauthor: %an <%ae>%ndate: %aD%nbranch: %d"
+ COMMAND ${GIT_EXECUTABLE} log -1
+ --pretty="commit: %H%ndate: %ci%nbuild-date: ${bdate} %nshort: %h%nbranch: ${bname}"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE VERSION_INFO
- RESULT_VARIABLE RESULT
)
+
+ ## Output from git is quoted with "", remove them.
+ STRING(REPLACE "\"" "" VERSION_INFO "${VERSION_INFO}")
FILE(WRITE ${INFO_SRC} "${VERSION_INFO}\n")
# to debug, add: FILE(APPEND ${INFO_SRC} "\nResult ${RESULT}\n")
# For better readability ...
- FILE(APPEND ${INFO_SRC} "\nMariaDB source ${VERSION}\n")
+ FILE(APPEND ${INFO_SRC}
+ "MariaDB source ${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}\n")
ELSEIF(EXISTS ${INFO_SRC})
- # Outside a BZR tree, there is no need to change an existing "INFO_SRC",
+ # Outside a git tree, there is no need to change an existing "INFO_SRC",
# it cannot be improved.
ELSEIF(EXISTS ${CMAKE_SOURCE_DIR}/Docs/INFO_SRC)
# If we are building from a source distribution, it also contains "INFO_SRC".
diff --git a/cmake/info_src.cmake b/cmake/info_src.cmake
index 97776b70901..ce9873cc9d0 100644
--- a/cmake/info_src.cmake
+++ b/cmake/info_src.cmake
@@ -1,4 +1,4 @@
-# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -16,11 +16,11 @@
# The sole purpose of this cmake control file is to create the "INFO_SRC" file.
-# As long as and "bzr pull" (or "bzr commit") is followed by a "cmake",
+# As long as and "git pull" (or "git commit") is followed by a "cmake",
# the call in top level "CMakeLists.txt" is sufficient.
# This file is to provide a separate target for the "make" phase,
-# to ensure the BZR revision-id is correct even after a sequence
-# cmake ; make ; bzr pull ; make
+# to ensure the git commit hash is correct even after a sequence
+# cmake ; make ; git pull ; make
# Get the macros which handle the "INFO_*" files.
diff --git a/cmake/maintainer.cmake b/cmake/maintainer.cmake
index bee151ad8f0..d905ec189ae 100644
--- a/cmake/maintainer.cmake
+++ b/cmake/maintainer.cmake
@@ -35,7 +35,7 @@ IF(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
ENDIF()
# Turn on Werror (warning => error) when using maintainer mode.
-IF(FALSE AND MYSQL_MAINTAINER_MODE MATCHES "ON")
+IF(MYSQL_MAINTAINER_MODE MATCHES "ERR")
SET(MY_C_WARNING_FLAGS "${MY_C_WARNING_FLAGS} -DFORCE_INIT_OF_VARS -Werror")
SET(MY_CXX_WARNING_FLAGS "${MY_CXX_WARNING_FLAGS} -DFORCE_INIT_OF_VARS -Werror")
ENDIF()
diff --git a/cmake/make_dist.cmake.in b/cmake/make_dist.cmake.in
index b8c8877ef61..c561baaa415 100644
--- a/cmake/make_dist.cmake.in
+++ b/cmake/make_dist.cmake.in
@@ -22,7 +22,6 @@ SET(CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@")
SET(CPACK_SOURCE_PACKAGE_FILE_NAME "@CPACK_SOURCE_PACKAGE_FILE_NAME@")
SET(CMAKE_CPACK_COMMAND "@CMAKE_CPACK_COMMAND@")
SET(CMAKE_COMMAND "@CMAKE_COMMAND@")
-SET(BZR_EXECUTABLE "@BZR_EXECUTABLE@")
SET(GIT_EXECUTABLE "@GIT_EXECUTABLE@")
SET(GTAR_EXECUTABLE "@GTAR_EXECUTABLE@")
SET(TAR_EXECUTABLE "@TAR_EXECUTABLE@")
@@ -53,22 +52,8 @@ IF(GIT_EXECUTABLE)
ENDIF()
ENDIF()
-IF(BZR_EXECUTABLE AND NOT GIT_EXECUTABLE)
- MESSAGE(STATUS "Running bzr export")
- EXECUTE_PROCESS(
- COMMAND "${BZR_EXECUTABLE}" export
- ${PACKAGE_DIR}
- WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
- RESULT_VARIABLE RESULT
- )
-
- IF(NOT RESULT EQUAL 0)
- SET(BZR_EXECUTABLE)
- ENDIF()
-ENDIF()
-
-IF(NOT BZR_EXECUTABLE AND NOT GIT_EXECUTABLE)
- MESSAGE(STATUS "bzr not found or source dir is not a repo, use CPack")
+IF(NOT GIT_EXECUTABLE)
+ MESSAGE(STATUS "git not found or source dir is not a repo, use CPack")
IF(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
# In-source build is the worst option, we have to cleanup source tree.
diff --git a/cmake/ssl.cmake b/cmake/ssl.cmake
index f6d2936b818..2f2ffa70318 100644
--- a/cmake/ssl.cmake
+++ b/cmake/ssl.cmake
@@ -159,23 +159,6 @@ MACRO (MYSQL_CHECK_SSL)
LIST(REVERSE CMAKE_FIND_LIBRARY_SUFFIXES)
ENDIF()
- # Verify version number. Version information looks like:
- # #define OPENSSL_VERSION_NUMBER 0x1000103fL
- # Encoded as MNNFFPPS: major minor fix patch status
- FILE(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h"
- OPENSSL_VERSION_NUMBER
- REGEX "^#define[\t ]+OPENSSL_VERSION_NUMBER[\t ]+0x[0-9].*"
- )
- STRING(REGEX REPLACE
- "^.*OPENSSL_VERSION_NUMBER[\t ]+0x([0-9]).*$" "\\1"
- OPENSSL_MAJOR_VERSION "${OPENSSL_VERSION_NUMBER}"
- )
-
- MESSAGE(STATUS "OPENSSL_INCLUDE_DIR = ${OPENSSL_INCLUDE_DIR}")
- MESSAGE(STATUS "OPENSSL_LIBRARIES = ${OPENSSL_LIBRARIES}")
- MESSAGE(STATUS "CRYPTO_LIBRARY = ${CRYPTO_LIBRARY}")
- MESSAGE(STATUS "OPENSSL_MAJOR_VERSION = ${OPENSSL_MAJOR_VERSION}")
-
INCLUDE(CheckSymbolExists)
SET(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
CHECK_SYMBOL_EXISTS(SHA512_DIGEST_LENGTH "openssl/sha.h"
@@ -190,6 +173,23 @@ MACRO (MYSQL_CHECK_SSL)
IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
SET(SSL_LIBRARIES ${SSL_LIBRARIES} ${LIBDL})
ENDIF()
+
+ # Verify version number. Version information looks like:
+ # #define OPENSSL_VERSION_NUMBER 0x1000103fL
+ # Encoded as MNNFFPPS: major minor fix patch status
+ FILE(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h"
+ OPENSSL_VERSION_NUMBER
+ REGEX "^#define[\t ]+OPENSSL_VERSION_NUMBER[\t ]+0x[0-9].*"
+ )
+ STRING(REGEX REPLACE
+ "^.*OPENSSL_VERSION_NUMBER[\t ]+0x([0-9]).*$" "\\1"
+ OPENSSL_MAJOR_VERSION "${OPENSSL_VERSION_NUMBER}"
+ )
+
+ MESSAGE(STATUS "OPENSSL_INCLUDE_DIR = ${OPENSSL_INCLUDE_DIR}")
+ MESSAGE(STATUS "OPENSSL_LIBRARIES = ${OPENSSL_LIBRARIES}")
+ MESSAGE(STATUS "CRYPTO_LIBRARY = ${CRYPTO_LIBRARY}")
+ MESSAGE(STATUS "OPENSSL_MAJOR_VERSION = ${OPENSSL_MAJOR_VERSION}")
MESSAGE(STATUS "SSL_LIBRARIES = ${SSL_LIBRARIES}")
SET(SSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR})
SET(SSL_INTERNAL_INCLUDE_DIRS "")
diff --git a/debian/dist/Debian/mariadb-server-10.1.postinst b/debian/dist/Debian/mariadb-server-10.1.postinst
index 88de8a5126a..fff75988353 100644
--- a/debian/dist/Debian/mariadb-server-10.1.postinst
+++ b/debian/dist/Debian/mariadb-server-10.1.postinst
@@ -21,7 +21,7 @@ invoke() {
fi
}
-MYSQL_BOOTSTRAP="/usr/sbin/mysqld --bootstrap --user=mysql --skip-grant-tables --default-storage-engine=myisam"
+MYSQL_BOOTSTRAP="/usr/sbin/mysqld --bootstrap --user=mysql --disable-log-bin --skip-grant-tables --default-storage-engine=myisam"
test_mysql_access() {
mysql --no-defaults -u root -h localhost </dev/null >/dev/null 2>&1
@@ -40,6 +40,7 @@ set_mysql_rootpw() {
# this avoids us having to call "test" or "[" on $rootpw
cat << EOF > $tfile
USE mysql;
+SET sql_log_bin=0;
UPDATE user SET password=PASSWORD("$rootpw") WHERE user='root';
FLUSH PRIVILEGES;
EOF
@@ -144,7 +145,7 @@ EOF
# Debian: beware of the bashisms...
# Debian: can safely run on upgrades with existing databases
set +e
- /bin/bash /usr/bin/mysql_install_db --rpm --user=mysql 2>&1 | $ERR_LOGGER
+ /bin/bash /usr/bin/mysql_install_db --rpm --user=mysql --disable-log-bin 2>&1 | $ERR_LOGGER
set -e
## On every reconfiguration the maintenance user is recreated.
diff --git a/debian/dist/Ubuntu/mariadb-server-10.1.postinst b/debian/dist/Ubuntu/mariadb-server-10.1.postinst
index 73e125b9651..b30dc5963be 100644
--- a/debian/dist/Ubuntu/mariadb-server-10.1.postinst
+++ b/debian/dist/Ubuntu/mariadb-server-10.1.postinst
@@ -21,7 +21,7 @@ invoke() {
fi
}
-MYSQL_BOOTSTRAP="/usr/sbin/mysqld --bootstrap --user=mysql --skip-grant-tables --default-storage-engine=myisam"
+MYSQL_BOOTSTRAP="/usr/sbin/mysqld --bootstrap --user=mysql --disable-log-bin --skip-grant-tables --default-storage-engine=myisam"
test_mysql_access() {
mysql --no-defaults -u root -h localhost </dev/null >/dev/null 2>&1
@@ -41,6 +41,7 @@ set_mysql_rootpw() {
# this avoids us having to call "test" or "[" on $rootpw
cat << EOF > $tfile
USE mysql;
+SET sql_log_bin=0;
UPDATE user SET password=PASSWORD("$rootpw") WHERE user='root';
FLUSH PRIVILEGES;
EOF
@@ -145,7 +146,7 @@ EOF
# Debian: beware of the bashisms...
# Debian: can safely run on upgrades with existing databases
set +e
- /bin/bash /usr/bin/mysql_install_db --rpm --user=mysql 2>&1 | $ERR_LOGGER
+ /bin/bash /usr/bin/mysql_install_db --rpm --user=mysql --disable-log-bin 2>&1 | $ERR_LOGGER
set -e
## On every reconfiguration the maintenance user is recreated.
@@ -213,7 +214,7 @@ EOF
# admin might already have chosen to remove one or more plugins. Newlines are necessary.
install_plugins=`/bin/echo -e \
"USE mysql;\n" \
- "CREATE TABLE plugin (name char(64) COLLATE utf8_bin NOT NULL DEFAULT '', " \
+ "CREATE TABLE IF NOT EXISTS plugin (name char(64) COLLATE utf8_bin NOT NULL DEFAULT '', " \
" dl char(128) COLLATE utf8_bin NOT NULL DEFAULT '', " \
" PRIMARY KEY (name)) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='MySQL plugins';" `
diff --git a/extra/yassl/README b/extra/yassl/README
index 30c7af4a702..da399c3d141 100644
--- a/extra/yassl/README
+++ b/extra/yassl/README
@@ -12,6 +12,16 @@ before calling SSL_new();
*** end Note ***
+yaSSL Release notes, version 2.3.7 (12/10/2014)
+ This release of yaSSL fixes the potential to process duplicate handshake
+ messages by explicitly marking/checking received handshake messages.
+
+yaSSL Release notes, version 2.3.6 (11/25/2014)
+
+ This release of yaSSL fixes some valgrind warnings/errors including
+ uninitialized reads and off by one index errors induced from fuzzing
+ the handshake. These were reported by Oracle.
+
yaSSL Release notes, version 2.3.5 (9/29/2014)
This release of yaSSL fixes an RSA Padding check vulnerability reported by
diff --git a/extra/yassl/examples/client/client.cpp b/extra/yassl/examples/client/client.cpp
index fc05b66aaf7..102ed61734c 100644
--- a/extra/yassl/examples/client/client.cpp
+++ b/extra/yassl/examples/client/client.cpp
@@ -18,6 +18,10 @@
/* client.cpp */
+// takes an optional command line argument of cipher list to make scripting
+// easier
+
+
#include "../../testsuite/test.hpp"
//#define TEST_RESUME
@@ -73,11 +77,16 @@ void client_test(void* args)
#ifdef NON_BLOCKING
tcp_set_nonblocking(sockfd);
#endif
-
SSL_METHOD* method = TLSv1_client_method();
SSL_CTX* ctx = SSL_CTX_new(method);
set_certs(ctx);
+ if (argc >= 2) {
+ printf("setting cipher list to %s\n", argv[1]);
+ if (SSL_CTX_set_cipher_list(ctx, argv[1]) != SSL_SUCCESS) {
+ ClientError(ctx, NULL, sockfd, "set_cipher_list error\n");
+ }
+ }
SSL* ssl = SSL_new(ctx);
SSL_set_fd(ssl, sockfd);
diff --git a/extra/yassl/examples/server/server.cpp b/extra/yassl/examples/server/server.cpp
index 173ce8fb548..1540f6d3689 100644
--- a/extra/yassl/examples/server/server.cpp
+++ b/extra/yassl/examples/server/server.cpp
@@ -18,6 +18,9 @@
/* server.cpp */
+// takes 2 optional command line argument to make scripting
+// if the first command line argument is 'n' client auth is disabled
+// if the second command line argument is 'd' DSA certs are used instead of RSA
#include "../../testsuite/test.hpp"
@@ -69,6 +72,9 @@ THREAD_RETURN YASSL_API server_test(void* args)
char** argv = 0;
set_args(argc, argv, *static_cast<func_args*>(args));
+#ifdef SERVER_READY_FILE
+ set_file_ready("server_ready", *static_cast<func_args*>(args));
+#endif
tcp_accept(sockfd, clientfd, *static_cast<func_args*>(args));
tcp_close(sockfd);
@@ -77,8 +83,21 @@ THREAD_RETURN YASSL_API server_test(void* args)
SSL_CTX* ctx = SSL_CTX_new(method);
//SSL_CTX_set_cipher_list(ctx, "RC4-SHA:RC4-MD5");
- SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, 0);
- set_serverCerts(ctx);
+
+ // should we disable client auth
+ if (argc >= 2 && argv[1][0] == 'n')
+ printf("disabling client auth\n");
+ else
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, 0);
+
+ // are we using DSA certs
+ if (argc >= 3 && argv[2][0] == 'd') {
+ printf("using DSA certs\n");
+ set_dsaServerCerts(ctx);
+ }
+ else {
+ set_serverCerts(ctx);
+ }
DH* dh = set_tmpDH(ctx);
SSL* ssl = SSL_new(ctx);
diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h
index f819d76adc7..404ffa29275 100644
--- a/extra/yassl/include/openssl/ssl.h
+++ b/extra/yassl/include/openssl/ssl.h
@@ -34,7 +34,7 @@
#include "rsa.h"
-#define YASSL_VERSION "2.3.5"
+#define YASSL_VERSION "2.3.7"
#if defined(__cplusplus)
diff --git a/extra/yassl/include/yassl_int.hpp b/extra/yassl/include/yassl_int.hpp
index d04e0d56bf8..269976a6eaa 100644
--- a/extra/yassl/include/yassl_int.hpp
+++ b/extra/yassl/include/yassl_int.hpp
@@ -107,6 +107,25 @@ enum AcceptState {
};
+// track received messages to explicitly disallow duplicate messages
+struct RecvdMessages {
+ uint8 gotClientHello_;
+ uint8 gotServerHello_;
+ uint8 gotCert_;
+ uint8 gotServerKeyExchange_;
+ uint8 gotCertRequest_;
+ uint8 gotServerHelloDone_;
+ uint8 gotCertVerify_;
+ uint8 gotClientKeyExchange_;
+ uint8 gotFinished_;
+ RecvdMessages() : gotClientHello_(0), gotServerHello_(0), gotCert_(0),
+ gotServerKeyExchange_(0), gotCertRequest_(0),
+ gotServerHelloDone_(0), gotCertVerify_(0),
+ gotClientKeyExchange_(0), gotFinished_(0)
+ {}
+};
+
+
// combines all states
class States {
RecordLayerState recordLayer_;
@@ -115,6 +134,7 @@ class States {
ServerState serverState_;
ConnectState connectState_;
AcceptState acceptState_;
+ RecvdMessages recvdMessages_;
char errorString_[MAX_ERROR_SZ];
YasslError what_;
public:
@@ -137,6 +157,7 @@ public:
AcceptState& UseAccept();
char* useString();
void SetError(YasslError);
+ int SetMessageRecvd(HandShakeType);
private:
States(const States&); // hide copy
States& operator=(const States&); // and assign
diff --git a/extra/yassl/src/yassl_imp.cpp b/extra/yassl/src/yassl_imp.cpp
index 25e00d45d2b..5d5632f3ba4 100644
--- a/extra/yassl/src/yassl_imp.cpp
+++ b/extra/yassl/src/yassl_imp.cpp
@@ -242,6 +242,7 @@ void EncryptedPreMasterSecret::read(SSL& ssl, input_buffer& input)
}
opaque preMasterSecret[SECRET_LEN];
+ memset(preMasterSecret, 0, sizeof(preMasterSecret));
rsa.decrypt(preMasterSecret, secret_, length_,
ssl.getCrypto().get_random());
@@ -300,6 +301,11 @@ void ClientDiffieHellmanPublic::read(SSL& ssl, input_buffer& input)
tmp[1] = input[AUTO];
ato16(tmp, keyLength);
+ if (keyLength < dh.get_agreedKeyLength()/2) {
+ ssl.SetError(bad_input);
+ return;
+ }
+
alloc(keyLength);
input.read(Yc_, keyLength);
if (input.get_error()) {
@@ -408,6 +414,10 @@ void DH_Server::read(SSL& ssl, input_buffer& input)
tmp[1] = input[AUTO];
ato16(tmp, length);
+ if (length == 0) {
+ ssl.SetError(bad_input);
+ return;
+ }
signature_ = NEW_YS byte[length];
input.read(signature_, length);
if (input.get_error()) {
@@ -864,6 +874,12 @@ void ChangeCipherSpec::Process(input_buffer& input, SSL& ssl)
return;
}
+ // detect duplicate change_cipher
+ if (ssl.getSecurity().get_parms().pending_ == false) {
+ ssl.order_error();
+ return;
+ }
+
ssl.useSecurity().use_parms().pending_ = false;
if (ssl.getSecurity().get_resuming()) {
if (ssl.getSecurity().get_parms().entity_ == client_end)
@@ -2047,12 +2063,8 @@ input_buffer& operator>>(input_buffer& input, CertificateRequest& request)
tmp[0] = input[AUTO];
tmp[1] = input[AUTO];
ato16(tmp, dnSz);
-
- DistinguishedName dn;
- request.certificate_authorities_.push_back(dn = NEW_YS
- byte[REQUEST_HEADER + dnSz]);
- memcpy(dn, tmp, REQUEST_HEADER);
- input.read(&dn[REQUEST_HEADER], dnSz);
+
+ input.set_current(input.get_current() + dnSz);
sz -= dnSz + REQUEST_HEADER;
@@ -2191,6 +2203,11 @@ input_buffer& operator>>(input_buffer& input, CertificateVerify& request)
ato16(tmp, sz);
request.set_length(sz);
+ if (sz == 0) {
+ input.set_error();
+ return input;
+ }
+
request.signature_ = NEW_YS byte[sz];
input.read(request.signature_, sz);
diff --git a/extra/yassl/src/yassl_int.cpp b/extra/yassl/src/yassl_int.cpp
index cbda9f97d83..8dad9ce052c 100644
--- a/extra/yassl/src/yassl_int.cpp
+++ b/extra/yassl/src/yassl_int.cpp
@@ -255,6 +255,77 @@ void States::SetError(YasslError ye)
}
+// mark message recvd, check for duplicates, return 0 on success
+int States::SetMessageRecvd(HandShakeType hst)
+{
+ switch (hst) {
+ case hello_request:
+ break; // could send more than one
+
+ case client_hello:
+ if (recvdMessages_.gotClientHello_)
+ return -1;
+ recvdMessages_.gotClientHello_ = 1;
+ break;
+
+ case server_hello:
+ if (recvdMessages_.gotServerHello_)
+ return -1;
+ recvdMessages_.gotServerHello_ = 1;
+ break;
+
+ case certificate:
+ if (recvdMessages_.gotCert_)
+ return -1;
+ recvdMessages_.gotCert_ = 1;
+ break;
+
+ case server_key_exchange:
+ if (recvdMessages_.gotServerKeyExchange_)
+ return -1;
+ recvdMessages_.gotServerKeyExchange_ = 1;
+ break;
+
+ case certificate_request:
+ if (recvdMessages_.gotCertRequest_)
+ return -1;
+ recvdMessages_.gotCertRequest_ = 1;
+ break;
+
+ case server_hello_done:
+ if (recvdMessages_.gotServerHelloDone_)
+ return -1;
+ recvdMessages_.gotServerHelloDone_ = 1;
+ break;
+
+ case certificate_verify:
+ if (recvdMessages_.gotCertVerify_)
+ return -1;
+ recvdMessages_.gotCertVerify_ = 1;
+ break;
+
+ case client_key_exchange:
+ if (recvdMessages_.gotClientKeyExchange_)
+ return -1;
+ recvdMessages_.gotClientKeyExchange_ = 1;
+ break;
+
+ case finished:
+ if (recvdMessages_.gotFinished_)
+ return -1;
+ recvdMessages_.gotFinished_ = 1;
+ break;
+
+
+ default:
+ return -1;
+
+ }
+
+ return 0;
+}
+
+
sslFactory::sslFactory() :
messageFactory_(InitMessageFactory),
handShakeFactory_(InitHandShakeFactory),
@@ -1199,6 +1270,11 @@ void SSL::verifyState(const HandShakeHeader& hsHeader)
return;
}
+ if (states_.SetMessageRecvd(hsHeader.get_handshakeType()) != 0) {
+ order_error();
+ return;
+ }
+
if (secure_.get_parms().entity_ == client_end)
verifyClientState(hsHeader.get_handshakeType());
else
diff --git a/extra/yassl/taocrypt/src/asn.cpp b/extra/yassl/taocrypt/src/asn.cpp
index 15f8d81f5cc..624148bdac8 100644
--- a/extra/yassl/taocrypt/src/asn.cpp
+++ b/extra/yassl/taocrypt/src/asn.cpp
@@ -680,7 +680,7 @@ word32 CertDecoder::GetSignature()
}
sigLength_ = GetLength(source_);
- if (sigLength_ == 0 || source_.IsLeft(sigLength_) == false) {
+ if (sigLength_ <= 1 || source_.IsLeft(sigLength_) == false) {
source_.SetError(CONTENT_E);
return 0;
}
@@ -1011,11 +1011,17 @@ bool CertDecoder::ConfirmSignature(Source& pub)
RSA_PublicKey pubKey(pub);
RSAES_Encryptor enc(pubKey);
+ if (pubKey.FixedCiphertextLength() != sigLength_) {
+ source_.SetError(SIG_LEN_E);
+ return false;
+ }
+
return enc.SSL_Verify(build.get_buffer(), build.size(), signature_);
}
else { // DSA
// extract r and s from sequence
byte seqDecoded[DSA_SIG_SZ];
+ memset(seqDecoded, 0, sizeof(seqDecoded));
DecodeDSA_Signature(seqDecoded, signature_, sigLength_);
DSA_PublicKey pubKey(pub);
diff --git a/extra/yassl/taocrypt/src/integer.cpp b/extra/yassl/taocrypt/src/integer.cpp
index b7fbb7f96cf..fb8d9276bd9 100644
--- a/extra/yassl/taocrypt/src/integer.cpp
+++ b/extra/yassl/taocrypt/src/integer.cpp
@@ -2605,18 +2605,20 @@ void Integer::Decode(Source& source)
void Integer::Decode(const byte* input, unsigned int inputLen, Signedness s)
{
unsigned int idx(0);
- byte b = input[idx++];
+ byte b = 0;
+ if (inputLen>0)
+ b = input[idx]; // peek
sign_ = ((s==SIGNED) && (b & 0x80)) ? NEGATIVE : POSITIVE;
while (inputLen>0 && (sign_==POSITIVE ? b==0 : b==0xff))
{
- inputLen--;
- b = input[idx++];
+ idx++; // skip
+ if (--inputLen>0)
+ b = input[idx]; // peek
}
reg_.CleanNew(RoundupSize(BytesToWords(inputLen)));
- --idx;
for (unsigned int i=inputLen; i > 0; i--)
{
b = input[idx++];
diff --git a/extra/yassl/testsuite/cipher-test.sh b/extra/yassl/testsuite/cipher-test.sh
new file mode 100644
index 00000000000..5ce29459d07
--- /dev/null
+++ b/extra/yassl/testsuite/cipher-test.sh
@@ -0,0 +1,130 @@
+#!/bin/bash
+
+# test all yassl cipher suties
+#
+
+
+server_pid=$no_pid
+
+
+do_cleanup() {
+ echo "in cleanup"
+
+ if [[ $server_pid != $no_pid ]]
+ then
+ echo "killing server"
+ kill -9 $server_pid
+ fi
+}
+
+do_trap() {
+ echo "got trap"
+ do_cleanup
+ exit -1
+}
+
+trap do_trap INT TERM
+
+
+# make sure example server and client are built
+if test ! -s ../examples/server/server; then
+ echo "Please build yaSSL first, example server missing"
+ exit -1
+fi
+
+if test ! -s ../examples/client/client; then
+ echo "Please build yaSSL first, example client missing"
+ exit -1
+fi
+
+
+# non DSA suites
+for suite in {"DHE-RSA-AES256-SHA","AES256-SHA","DHE-RSA-AES128-SHA","AES128-SHA","AES256-RMD","AES128-RMD","DES-CBC3-RMD","DHE-RSA-AES256-RMD","DHE-RSA-AES128-RMD","DHE-RSA-DES-CBC3-RMD","RC4-SHA","RC4-MD5","DES-CBC3-SHA","DES-CBC-SHA","EDH-RSA-DES-CBC3-SHA","EDH-RSA-DES-CBC-SHA"}
+do
+ for client_auth in {y,n}
+ do
+ echo "Trying $suite client auth = $client_auth ..."
+
+ if test -e server_ready; then
+ echo -e "removing exisitng server_ready file"
+ rm server_ready
+ fi
+ ../examples/server/server $client_auth &
+ server_pid=$!
+
+ while [ ! -s server_ready ]; do
+ echo -e "waiting for server_ready file..."
+ sleep 0.1
+ done
+
+ ../examples/client/client $suite
+ client_result=$?
+
+ wait $server_pid
+ server_result=$?
+
+ server_pid=$no_pid
+
+ if [[ $client_result != 0 ]]
+ then
+ echo "Client Error"
+ exit $client_result
+ fi
+
+ if [[ $server_result != 0 ]]
+ then
+ echo "Server Error"
+ exit $server_result
+ fi
+
+ done # end client auth loop
+done # end non dsa suite list
+echo -e "Non DSA Loop SUCCESS"
+
+
+
+# DSA suites
+for suite in {"DHE-DSS-AES256-SHA","DHE-DSS-AES128-SHA","DHE-DSS-AES256-RMD","DHE-DSS-AES128-RMD","DHE-DSS-DES-CBC3-RMD","EDH-DSS-DES-CBC3-SHA","EDH-DSS-DES-CBC-SHA"}
+do
+ for client_auth in {y,n}
+ do
+ echo "Trying $suite client auth = $client_auth ..."
+
+ if test -e server_ready; then
+ echo -e "removing exisitng server_ready file"
+ rm server_ready
+ fi
+ # d signifies DSA
+ ../examples/server/server $client_auth d &
+ server_pid=$!
+
+ while [ ! -s server_ready ]; do
+ echo -e "waiting for server_ready file..."
+ sleep 0.1
+ done
+
+ ../examples/client/client $suite
+ client_result=$?
+
+ wait $server_pid
+ server_result=$?
+
+ server_pid=$no_pid
+
+ if [[ $client_result != 0 ]]
+ then
+ echo "Client Error"
+ exit $client_result
+ fi
+
+ if [[ $server_result != 0 ]]
+ then
+ echo "Server Error"
+ exit $server_result
+ fi
+
+ done # end client auth loop
+done # end dsa suite list
+echo -e "DSA Loop SUCCESS"
+
+exit 0
diff --git a/extra/yassl/testsuite/test.hpp b/extra/yassl/testsuite/test.hpp
index 33f398ae269..52f6ed79526 100644
--- a/extra/yassl/testsuite/test.hpp
+++ b/extra/yassl/testsuite/test.hpp
@@ -131,9 +131,10 @@ struct func_args {
int argc;
char** argv;
int return_code;
+ const char* file_ready;
tcp_ready* signal_;
- func_args(int c = 0, char** v = 0) : argc(c), argv(v) {}
+ func_args(int c = 0, char** v = 0) : argc(c), argv(v), file_ready(0) {}
void SetSignal(tcp_ready* p) { signal_ = p; }
};
@@ -146,6 +147,7 @@ void join_thread(THREAD_TYPE);
// yaSSL
const char* const yasslIP = "127.0.0.1";
const unsigned short yasslPort = 11111;
+const unsigned short proxyPort = 12345;
// client
@@ -172,13 +174,13 @@ const char* const svrKey3 = "../../../certs/server-key.pem";
// server dsa
const char* const dsaCert = "../certs/dsa-cert.pem";
-const char* const dsaKey = "../certs/dsa512.der";
+const char* const dsaKey = "../certs/dsa1024.der";
const char* const dsaCert2 = "../../certs/dsa-cert.pem";
-const char* const dsaKey2 = "../../certs/dsa512.der";
+const char* const dsaKey2 = "../../certs/dsa1024.der";
const char* const dsaCert3 = "../../../certs/dsa-cert.pem";
-const char* const dsaKey3 = "../../../certs/dsa512.der";
+const char* const dsaKey3 = "../../../certs/dsa1024.der";
// CA
@@ -222,6 +224,13 @@ inline void store_ca(SSL_CTX* ctx)
if (SSL_CTX_load_verify_locations(ctx, certSuite, 0) != SSL_SUCCESS)
if (SSL_CTX_load_verify_locations(ctx, certDebug,0) != SSL_SUCCESS)
err_sys("failed to use certificate: certs/client-cert.pem");
+
+ // DSA cert
+ if (SSL_CTX_load_verify_locations(ctx, dsaCert, 0) != SSL_SUCCESS)
+ if (SSL_CTX_load_verify_locations(ctx, dsaCert2, 0) != SSL_SUCCESS)
+ if (SSL_CTX_load_verify_locations(ctx, dsaCert3, 0) != SSL_SUCCESS)
+ err_sys("failed to use certificate: certs/dsa-cert.pem");
+
}
@@ -298,7 +307,7 @@ inline void set_dsaServerCerts(SSL_CTX* ctx)
!= SSL_SUCCESS)
if (SSL_CTX_use_PrivateKey_file(ctx, dsaKey3,SSL_FILETYPE_ASN1)
!= SSL_SUCCESS)
- err_sys("failed to use key file: certs/dsa512.der");
+ err_sys("failed to use key file: certs/dsa1024.der");
}
@@ -310,6 +319,12 @@ inline void set_args(int& argc, char**& argv, func_args& args)
}
+inline void set_file_ready(const char* name, func_args& args)
+{
+ args.file_ready = name;
+}
+
+
inline void tcp_set_nonblocking(SOCKET_T& sockfd)
{
#ifdef NON_BLOCKING
@@ -349,7 +364,11 @@ inline void tcp_socket(SOCKET_T& sockfd, SOCKADDR_IN_T& addr)
*/ // end external testing later
#else
addr.sin_family = AF_INET_V;
+#ifdef YASSL_PROXY_PORT
+ addr.sin_port = htons(proxyPort);
+#else
addr.sin_port = htons(yasslPort);
+#endif
addr.sin_addr.s_addr = inet_addr(yasslIP);
#endif
@@ -401,6 +420,16 @@ inline void tcp_listen(SOCKET_T& sockfd)
}
+inline void create_ready_file(func_args& args)
+{
+ FILE* f = fopen(args.file_ready, "w+");
+
+ if (f) {
+ fputs("ready", f);
+ fclose(f);
+ }
+}
+
inline void tcp_accept(SOCKET_T& sockfd, SOCKET_T& clientfd, func_args& args)
{
@@ -418,6 +447,9 @@ inline void tcp_accept(SOCKET_T& sockfd, SOCKET_T& clientfd, func_args& args)
pthread_mutex_unlock(&ready.mutex_);
#endif
+ if (args.file_ready)
+ create_ready_file(args);
+
clientfd = accept(sockfd, (sockaddr*)&client, (ACCEPT_THIRD_T)&client_len);
if (clientfd == (SOCKET_T) -1) {
diff --git a/include/mysql.h b/include/mysql.h
index 63e86937063..d9d9739dd1f 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -865,6 +865,12 @@ my_socket STDCALL mysql_get_socket(const MYSQL *mysql);
unsigned int STDCALL mysql_get_timeout_value(const MYSQL *mysql);
unsigned int STDCALL mysql_get_timeout_value_ms(const MYSQL *mysql);
+/********************************************************************
+ mysql_net_ functions - low-level API to MySQL protocol
+*********************************************************************/
+unsigned long STDCALL mysql_net_read_packet(MYSQL *mysql);
+unsigned long STDCALL mysql_net_field_length(unsigned char **packet);
+
/* status return codes */
#define MYSQL_NO_DATA 100
#define MYSQL_DATA_TRUNCATED 101
diff --git a/include/mysql.h.pp b/include/mysql.h.pp
index dd794e856e1..8ad94a03056 100644
--- a/include/mysql.h.pp
+++ b/include/mysql.h.pp
@@ -132,13 +132,11 @@ void scramble_323(char *to, const char *message, const char *password);
my_bool check_scramble_323(const unsigned char *reply, const char *message,
unsigned long *salt);
void get_salt_from_password_323(unsigned long *res, const char *password);
-void make_password_from_salt_323(char *to, const unsigned long *salt);
void make_scrambled_password(char *to, const char *password);
void scramble(char *to, const char *message, const char *password);
my_bool check_scramble(const unsigned char *reply, const char *message,
const unsigned char *hash_stage2);
void get_salt_from_password(unsigned char *res, const char *password);
-void make_password_from_salt(char *to, const unsigned char *hash_stage2);
char *octet2hex(char *to, const char *str, unsigned int len);
char *get_tty_password(const char *opt_message);
void get_tty_password_buff(const char *opt_message, char *to, size_t length);
@@ -747,3 +745,5 @@ int mysql_close_cont(MYSQL *sock, int status);
my_socket mysql_get_socket(const MYSQL *mysql);
unsigned int mysql_get_timeout_value(const MYSQL *mysql);
unsigned int mysql_get_timeout_value_ms(const MYSQL *mysql);
+unsigned long mysql_net_read_packet(MYSQL *mysql);
+unsigned long mysql_net_field_length(unsigned char **packet);
diff --git a/include/mysql_com.h b/include/mysql_com.h
index 0da24bc35a3..fe014233dc7 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -605,14 +605,11 @@ void scramble_323(char *to, const char *message, const char *password);
my_bool check_scramble_323(const unsigned char *reply, const char *message,
unsigned long *salt);
void get_salt_from_password_323(unsigned long *res, const char *password);
-void make_password_from_salt_323(char *to, const unsigned long *salt);
-
void make_scrambled_password(char *to, const char *password);
void scramble(char *to, const char *message, const char *password);
my_bool check_scramble(const unsigned char *reply, const char *message,
const unsigned char *hash_stage2);
void get_salt_from_password(unsigned char *res, const char *password);
-void make_password_from_salt(char *to, const unsigned char *hash_stage2);
char *octet2hex(char *to, const char *str, unsigned int len);
/* end of password.c */
diff --git a/include/welcome_copyright_notice.h b/include/welcome_copyright_notice.h
index 956a9f1c17a..096d42446bc 100644
--- a/include/welcome_copyright_notice.h
+++ b/include/welcome_copyright_notice.h
@@ -1,5 +1,5 @@
-/* Copyright (c) 2011, 2014, Oracle and/or its affiliates.
- Copyright (c) 2011, 2012, Monty Program Ab
+/* Copyright (c) 2011, 2015, Oracle and/or its affiliates.
+ Copyright (c) 2011, 2015, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,7 +17,7 @@
#ifndef _welcome_copyright_notice_h_
#define _welcome_copyright_notice_h_
-#define COPYRIGHT_NOTICE_CURRENT_YEAR "2014"
+#define COPYRIGHT_NOTICE_CURRENT_YEAR "2015"
/*
This define specifies copyright notice which is displayed by every MySQL
diff --git a/libmysql/CMakeLists.txt b/libmysql/CMakeLists.txt
index bb85b47f863..9dd58bebbbe 100644
--- a/libmysql/CMakeLists.txt
+++ b/libmysql/CMakeLists.txt
@@ -259,6 +259,9 @@ mariadb_dyncol_column_count
mariadb_dyncol_prepare_decimal
#
mariadb_deinitialize_ssl
+# low-level API to MySQL protocol
+mysql_net_read_packet
+mysql_net_field_length
# Added in MariaDB-10.0 to stay compatible with MySQL-5.6, yuck!
mysql_options4
)
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index a0bfe4e0d4f..a878b2fae44 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -4901,3 +4901,16 @@ my_bool STDCALL mysql_read_query_result(MYSQL *mysql)
return (*mysql->methods->read_query_result)(mysql);
}
+/********************************************************************
+ mysql_net_ functions - low-level API to MySQL protocol
+*********************************************************************/
+ulong STDCALL mysql_net_read_packet(MYSQL *mysql)
+{
+ return cli_safe_read(mysql);
+}
+
+ulong STDCALL mysql_net_field_length(uchar **packet)
+{
+ return net_field_length(packet);
+}
+
diff --git a/mysql-test/extra/binlog_tests/database.test b/mysql-test/extra/binlog_tests/database.test
index d071415bf65..cd0266434ff 100644
--- a/mysql-test/extra/binlog_tests/database.test
+++ b/mysql-test/extra/binlog_tests/database.test
@@ -31,12 +31,47 @@ source include/show_binlog_events.inc;
FLUSH STATUS;
+--echo
+--echo # 'DROP TABLE IF EXISTS <deleted tables>' is binlogged
+--echo # when 'DROP DATABASE' fails and at least one table is deleted
+--echo # from the database.
+RESET MASTER;
+CREATE DATABASE testing_1;
+USE testing_1;
+CREATE TABLE t1(c1 INT);
+CREATE TABLE t2(c1 INT);
+
+let $prefix= `SELECT UUID()`;
+--echo # Create a file in the database directory
+--replace_result $prefix FAKE_FILE
+eval SELECT 'hello' INTO OUTFILE 'fake_file.$prefix';
+
+--echo
+--echo # 'DROP DATABASE' will fail if there is any other file in the the
+--echo # database directory
+
+# Use '/' instead of '\' in the error message. On windows platform, dir is
+# formed with '\'.
+--replace_regex /\\testing_1\\*/\/testing_1\// /66/39/
+--error 1010
+DROP DATABASE testing_1;
+let $wait_binlog_event= DROP TABLE IF EXIST;
+source include/wait_for_binlog_event.inc;
+let $MYSQLD_DATADIR= `SELECT @@datadir`;
+
+--echo
+--echo # Remove the fake file.
+--remove_file $MYSQLD_DATADIR/testing_1/fake_file.$prefix
+--echo # Now we can drop the database.
+DROP DATABASE testing_1;
+
--echo #
--echo # Bug#11765416 58381: FAILED DROP DATABASE CAN BREAK STATEMENT
--echo # BASED REPLICATION
--echo #
+USE test;
--disable_warnings
DROP DATABASE IF EXISTS db1;
DROP TABLE IF EXISTS t3;
diff --git a/mysql-test/lib/My/SafeProcess/safe_process.cc b/mysql-test/lib/My/SafeProcess/safe_process.cc
index d6110f5f8c8..feb3eb4df66 100644
--- a/mysql-test/lib/My/SafeProcess/safe_process.cc
+++ b/mysql-test/lib/My/SafeProcess/safe_process.cc
@@ -125,7 +125,7 @@ extern "C" void handle_abort(int sig)
message("Got signal %d, child_pid: %d, sending ABRT", sig, child_pid);
if (child_pid > 0) {
- kill (-child_pid, SIGABRT); // Don't wait for it to terminate
+ kill(-child_pid, SIGABRT); // Don't wait for it to terminate
}
}
@@ -226,6 +226,18 @@ int main(int argc, char* const argv[] )
sleep(1);
}
+ /*
+ Child: Make this process it's own process group to be able to kill
+ it and any its children that hasn't changed a group themselves)
+
+ Parent: Detach from the parent's process group, so that killing a parent
+ group wouldn't kill us (if we're killed, there's no one to kill our child
+ processes that run in their own process group). There's a loop below
+ that monitors the parent, it's enough.
+ */
+ setpgid(0, 0);
+
+
if (child_pid == 0)
{
close(pfd[0]); // Close unused read end
@@ -236,10 +248,6 @@ int main(int argc, char* const argv[] )
signal(SIGHUP, SIG_DFL);
signal(SIGCHLD, SIG_DFL);
- // Make this process it's own process group to be able to kill
- // it and any childs(that hasn't changed group themself)
- setpgid(0, 0);
-
if (nocore)
{
struct rlimit corelim = { 0, 0 };
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index e90dba00206..186d8936e03 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -323,7 +323,7 @@ Level Code Message
Note 1050 Table 't1' already exists
show status like "Opened_tables";
Variable_name Value
-Opened_tables 2
+Opened_tables 1
select * from t1;
a b
1 1
diff --git a/mysql-test/r/ctype_binary.result b/mysql-test/r/ctype_binary.result
index e9a1fb1bc2c..7037fc1b383 100644
--- a/mysql-test/r/ctype_binary.result
+++ b/mysql-test/r/ctype_binary.result
@@ -3008,5 +3008,11 @@ Warnings:
Note 1003 select `test`.`t1`.`c1` AS `c1` from `test`.`t1` where ('%' = concat(`test`.`t1`.`c1`))
DROP TABLE t1;
#
+# MDEV-7629 Regression: Bit and hex string literals changed column names in 10.0.14
+#
+SELECT _binary 0x7E, _binary X'7E', _binary B'01111110';
+_binary 0x7E _binary X'7E' _binary B'01111110'
+~ ~ ~
+#
# End of 10.0 tests
#
diff --git a/mysql-test/r/ctype_latin1.result b/mysql-test/r/ctype_latin1.result
index 32afceb37e0..339e2e0787d 100644
--- a/mysql-test/r/ctype_latin1.result
+++ b/mysql-test/r/ctype_latin1.result
@@ -7907,5 +7907,11 @@ HEX(a) a
3F23 ?#
DROP TABLE t1;
#
+# MDEV-7629 Regression: Bit and hex string literals changed column names in 10.0.14
+#
+SELECT _latin1 0x7E, _latin1 X'7E', _latin1 B'01111110';
+_latin1 0x7E _latin1 X'7E' _latin1 B'01111110'
+~ ~ ~
+#
# End of 10.0 tests
#
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index db0c45e369c..4b23b010c79 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -6259,6 +6259,12 @@ EXECUTE stmt USING @b,@b;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation 'concat'
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
+#
+# MDEV-7629 Regression: Bit and hex string literals changed column names in 10.0.14
+#
+SELECT _utf8 0x7E, _utf8 X'7E', _utf8 B'01111110';
+_utf8 0x7E _utf8 X'7E' _utf8 B'01111110'
+~ ~ ~
# Start of ctype_unescape.inc
SET @query=_binary'SELECT CHARSET(\'test\'),@@character_set_client,@@character_set_connection';
PREPARE stmt FROM @query;
diff --git a/mysql-test/r/derived_opt.result b/mysql-test/r/derived_opt.result
index a2e08eacebc..04a76c2cbc8 100644
--- a/mysql-test/r/derived_opt.result
+++ b/mysql-test/r/derived_opt.result
@@ -413,64 +413,64 @@ create VIEW v27 AS select tab1_v27.f1,tab1_v27.f2 from t0 tab1_v27 join v26 tab2
EXPLAIN SELECT CAST(f1 AS SIGNED INTEGER) AS f1, CAST(f2 AS CHAR) AS f2 FROM v27;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE tab1_v27 ALL NULL NULL NULL NULL 5 Using where
-1 SIMPLE tab1_v26 hash_ALL NULL #hash#$hj 63 test1.tab1_v27.f1,test1.tab1_v27.f2 5 Using where; Using join buffer (flat, BNLH join)
+1 SIMPLE tab1_v26 hash_ALL NULL #hash#$hj 62 test1.tab1_v27.f1,test1.tab1_v27.f2 5 Using where; Using join buffer (flat, BNLH join)
1 SIMPLE tab1_v25 hash_ALL NULL #hash#$hj 31 test1.tab1_v26.f1 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v24 hash_ALL NULL #hash#$hj 60 test1.tab1_v25.f1,test1.tab1_v25.f2 5 Using where; Using join buffer (incremental, BNLH join)
-1 SIMPLE tab1_v23 hash_ALL NULL #hash#$hj 63 test1.tab1_v24.f1,test1.tab1_v24.f2 5 Using where; Using join buffer (incremental, BNLH join)
+1 SIMPLE tab1_v23 hash_ALL NULL #hash#$hj 62 test1.tab1_v24.f1,test1.tab1_v24.f2 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v22 hash_ALL NULL #hash#$hj 31 test1.tab1_v23.f1 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v21 hash_ALL NULL #hash#$hj 60 test1.tab1_v22.f1,test1.tab1_v22.f2 5 Using where; Using join buffer (incremental, BNLH join)
-1 SIMPLE tab1_v20 hash_ALL NULL #hash#$hj 63 test1.tab1_v21.f1,test1.tab1_v21.f2 5 Using where; Using join buffer (incremental, BNLH join)
+1 SIMPLE tab1_v20 hash_ALL NULL #hash#$hj 62 test1.tab1_v21.f1,test1.tab1_v21.f2 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v19 hash_ALL NULL #hash#$hj 31 test1.tab1_v20.f1 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v18 hash_ALL NULL #hash#$hj 60 test1.tab1_v19.f1,test1.tab1_v19.f2 5 Using where; Using join buffer (incremental, BNLH join)
-1 SIMPLE tab1_v17 hash_ALL NULL #hash#$hj 63 test1.tab1_v18.f1,test1.tab1_v18.f2 5 Using where; Using join buffer (incremental, BNLH join)
+1 SIMPLE tab1_v17 hash_ALL NULL #hash#$hj 62 test1.tab1_v18.f1,test1.tab1_v18.f2 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v16 hash_ALL NULL #hash#$hj 31 test1.tab1_v17.f1 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v15 hash_ALL NULL #hash#$hj 60 test1.tab1_v16.f1,test1.tab1_v16.f2 5 Using where; Using join buffer (incremental, BNLH join)
-1 SIMPLE tab1_v14 hash_ALL NULL #hash#$hj 63 test1.tab1_v15.f1,test1.tab1_v15.f2 5 Using where; Using join buffer (incremental, BNLH join)
+1 SIMPLE tab1_v14 hash_ALL NULL #hash#$hj 62 test1.tab1_v15.f1,test1.tab1_v15.f2 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v13 hash_ALL NULL #hash#$hj 31 test1.tab1_v14.f1 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v12 hash_ALL NULL #hash#$hj 60 test1.tab1_v13.f1,test1.tab1_v13.f2 5 Using where; Using join buffer (incremental, BNLH join)
-1 SIMPLE tab1_v11 hash_ALL NULL #hash#$hj 63 test1.tab1_v12.f1,test1.tab1_v12.f2 5 Using where; Using join buffer (incremental, BNLH join)
+1 SIMPLE tab1_v11 hash_ALL NULL #hash#$hj 62 test1.tab1_v12.f1,test1.tab1_v12.f2 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v10 hash_ALL NULL #hash#$hj 31 test1.tab1_v11.f1 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v9 hash_ALL NULL #hash#$hj 60 test1.tab1_v10.f1,test1.tab1_v10.f2 5 Using where; Using join buffer (incremental, BNLH join)
-1 SIMPLE tab1_v8 hash_ALL NULL #hash#$hj 63 test1.tab1_v9.f1,test1.tab1_v9.f2 5 Using where; Using join buffer (incremental, BNLH join)
+1 SIMPLE tab1_v8 hash_ALL NULL #hash#$hj 62 test1.tab1_v9.f1,test1.tab1_v9.f2 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v7 hash_ALL NULL #hash#$hj 31 test1.tab1_v8.f1 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v6 hash_ALL NULL #hash#$hj 60 test1.tab1_v7.f1,test1.tab1_v7.f2 5 Using where; Using join buffer (incremental, BNLH join)
-1 SIMPLE tab1_v5 hash_ALL NULL #hash#$hj 63 test1.tab1_v6.f1,test1.tab1_v6.f2 5 Using where; Using join buffer (incremental, BNLH join)
+1 SIMPLE tab1_v5 hash_ALL NULL #hash#$hj 62 test1.tab1_v6.f1,test1.tab1_v6.f2 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v4 hash_ALL NULL #hash#$hj 31 test1.tab1_v5.f1 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v3 hash_ALL NULL #hash#$hj 60 test1.tab1_v4.f1,test1.tab1_v4.f2 5 Using where; Using join buffer (incremental, BNLH join)
-1 SIMPLE tab1_v2 hash_ALL NULL #hash#$hj 63 test1.tab1_v3.f1,test1.tab1_v3.f2 5 Using where; Using join buffer (incremental, BNLH join)
+1 SIMPLE tab1_v2 hash_ALL NULL #hash#$hj 62 test1.tab1_v3.f1,test1.tab1_v3.f2 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v1 hash_ALL NULL #hash#$hj 31 test1.tab1_v2.f1 5 Using where; Using join buffer (incremental, BNLH join)
-1 SIMPLE t1 hash_ALL NULL #hash#$hj 85 test1.tab1_v1.f1,test1.tab1_v1.f2 5 Using where; Using join buffer (incremental, BNLH join)
+1 SIMPLE t1 hash_ALL NULL #hash#$hj 84 test1.tab1_v1.f1,test1.tab1_v1.f2 5 Using where; Using join buffer (incremental, BNLH join)
# This used to hang forever:
EXPLAIN SELECT CAST(f1 AS SIGNED INTEGER) AS f1, CAST(f2 AS CHAR) AS f2 FROM v27;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE tab1_v27 ALL NULL NULL NULL NULL 5 Using where
-1 SIMPLE tab1_v26 hash_ALL NULL #hash#$hj 63 test1.tab1_v27.f1,test1.tab1_v27.f2 5 Using where; Using join buffer (flat, BNLH join)
+1 SIMPLE tab1_v26 hash_ALL NULL #hash#$hj 62 test1.tab1_v27.f1,test1.tab1_v27.f2 5 Using where; Using join buffer (flat, BNLH join)
1 SIMPLE tab1_v25 hash_ALL NULL #hash#$hj 31 test1.tab1_v26.f1 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v24 hash_ALL NULL #hash#$hj 60 test1.tab1_v25.f1,test1.tab1_v25.f2 5 Using where; Using join buffer (incremental, BNLH join)
-1 SIMPLE tab1_v23 hash_ALL NULL #hash#$hj 63 test1.tab1_v24.f1,test1.tab1_v24.f2 5 Using where; Using join buffer (incremental, BNLH join)
+1 SIMPLE tab1_v23 hash_ALL NULL #hash#$hj 62 test1.tab1_v24.f1,test1.tab1_v24.f2 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v22 hash_ALL NULL #hash#$hj 31 test1.tab1_v23.f1 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v21 hash_ALL NULL #hash#$hj 60 test1.tab1_v22.f1,test1.tab1_v22.f2 5 Using where; Using join buffer (incremental, BNLH join)
-1 SIMPLE tab1_v20 hash_ALL NULL #hash#$hj 63 test1.tab1_v21.f1,test1.tab1_v21.f2 5 Using where; Using join buffer (incremental, BNLH join)
+1 SIMPLE tab1_v20 hash_ALL NULL #hash#$hj 62 test1.tab1_v21.f1,test1.tab1_v21.f2 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v19 hash_ALL NULL #hash#$hj 31 test1.tab1_v20.f1 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v18 hash_ALL NULL #hash#$hj 60 test1.tab1_v19.f1,test1.tab1_v19.f2 5 Using where; Using join buffer (incremental, BNLH join)
-1 SIMPLE tab1_v17 hash_ALL NULL #hash#$hj 63 test1.tab1_v18.f1,test1.tab1_v18.f2 5 Using where; Using join buffer (incremental, BNLH join)
+1 SIMPLE tab1_v17 hash_ALL NULL #hash#$hj 62 test1.tab1_v18.f1,test1.tab1_v18.f2 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v16 hash_ALL NULL #hash#$hj 31 test1.tab1_v17.f1 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v15 hash_ALL NULL #hash#$hj 60 test1.tab1_v16.f1,test1.tab1_v16.f2 5 Using where; Using join buffer (incremental, BNLH join)
-1 SIMPLE tab1_v14 hash_ALL NULL #hash#$hj 63 test1.tab1_v15.f1,test1.tab1_v15.f2 5 Using where; Using join buffer (incremental, BNLH join)
+1 SIMPLE tab1_v14 hash_ALL NULL #hash#$hj 62 test1.tab1_v15.f1,test1.tab1_v15.f2 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v13 hash_ALL NULL #hash#$hj 31 test1.tab1_v14.f1 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v12 hash_ALL NULL #hash#$hj 60 test1.tab1_v13.f1,test1.tab1_v13.f2 5 Using where; Using join buffer (incremental, BNLH join)
-1 SIMPLE tab1_v11 hash_ALL NULL #hash#$hj 63 test1.tab1_v12.f1,test1.tab1_v12.f2 5 Using where; Using join buffer (incremental, BNLH join)
+1 SIMPLE tab1_v11 hash_ALL NULL #hash#$hj 62 test1.tab1_v12.f1,test1.tab1_v12.f2 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v10 hash_ALL NULL #hash#$hj 31 test1.tab1_v11.f1 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v9 hash_ALL NULL #hash#$hj 60 test1.tab1_v10.f1,test1.tab1_v10.f2 5 Using where; Using join buffer (incremental, BNLH join)
-1 SIMPLE tab1_v8 hash_ALL NULL #hash#$hj 63 test1.tab1_v9.f1,test1.tab1_v9.f2 5 Using where; Using join buffer (incremental, BNLH join)
+1 SIMPLE tab1_v8 hash_ALL NULL #hash#$hj 62 test1.tab1_v9.f1,test1.tab1_v9.f2 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v7 hash_ALL NULL #hash#$hj 31 test1.tab1_v8.f1 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v6 hash_ALL NULL #hash#$hj 60 test1.tab1_v7.f1,test1.tab1_v7.f2 5 Using where; Using join buffer (incremental, BNLH join)
-1 SIMPLE tab1_v5 hash_ALL NULL #hash#$hj 63 test1.tab1_v6.f1,test1.tab1_v6.f2 5 Using where; Using join buffer (incremental, BNLH join)
+1 SIMPLE tab1_v5 hash_ALL NULL #hash#$hj 62 test1.tab1_v6.f1,test1.tab1_v6.f2 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v4 hash_ALL NULL #hash#$hj 31 test1.tab1_v5.f1 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v3 hash_ALL NULL #hash#$hj 60 test1.tab1_v4.f1,test1.tab1_v4.f2 5 Using where; Using join buffer (incremental, BNLH join)
-1 SIMPLE tab1_v2 hash_ALL NULL #hash#$hj 63 test1.tab1_v3.f1,test1.tab1_v3.f2 5 Using where; Using join buffer (incremental, BNLH join)
+1 SIMPLE tab1_v2 hash_ALL NULL #hash#$hj 62 test1.tab1_v3.f1,test1.tab1_v3.f2 5 Using where; Using join buffer (incremental, BNLH join)
1 SIMPLE tab1_v1 hash_ALL NULL #hash#$hj 31 test1.tab1_v2.f1 5 Using where; Using join buffer (incremental, BNLH join)
-1 SIMPLE t1 hash_ALL NULL #hash#$hj 85 test1.tab1_v1.f1,test1.tab1_v1.f2 5 Using where; Using join buffer (incremental, BNLH join)
+1 SIMPLE t1 hash_ALL NULL #hash#$hj 84 test1.tab1_v1.f1,test1.tab1_v1.f2 5 Using where; Using join buffer (incremental, BNLH join)
use test;
drop database test1;
set join_cache_level=@tmp_jcl;
diff --git a/mysql-test/r/derived_view.result b/mysql-test/r/derived_view.result
index e359a8f89c5..fa0a69a487d 100644
--- a/mysql-test/r/derived_view.result
+++ b/mysql-test/r/derived_view.result
@@ -770,7 +770,7 @@ SELECT * FROM t1, t2, v1 WHERE t2.a=t1.a AND t2.a=v1.a AND t2.a=v1.b;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 system NULL NULL NULL NULL 1
1 PRIMARY t2 ref a a 4 const 1 Using index
-1 PRIMARY <derived2> ref key0 key0 10 const,const 1
+1 PRIMARY <derived2> ref key0 key0 8 const,const 1
2 DERIVED t3 ALL NULL NULL NULL NULL 12 Using temporary; Using filesort
SELECT * FROM t1, t2, v1 WHERE t2.a=t1.a AND t2.a=v1.a AND t2.a=v1.b;
a a a b
@@ -1518,7 +1518,7 @@ WHERE t3.b IN (SELECT v1.b FROM v1, t2
WHERE t2.c = v1.c AND t2.c = v1.b AND v1.b = t3.c);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 system NULL NULL NULL NULL 1
-1 PRIMARY <derived3> ref key1 key1 10 const,const 0 Start temporary
+1 PRIMARY <derived3> ref key1 key1 8 const,const 0 Start temporary
1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using where; End temporary; Using join buffer (flat, BNL join)
3 DERIVED t1 ALL NULL NULL NULL NULL 3
SELECT * FROM t3
@@ -1596,7 +1596,7 @@ EXPLAIN
SELECT v1.a FROM v1,v2 WHERE v2.b = v1.b ORDER BY 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3 Using where; Using filesort
-1 PRIMARY <derived3> ref key0 key0 5 v1.b 2
+1 PRIMARY <derived3> ref key0 key0 4 v1.b 2
3 DERIVED t2 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort
2 DERIVED t1 ALL NULL NULL NULL NULL 3 Using temporary; Using filesort
DROP VIEW v1,v2;
diff --git a/mysql-test/r/error_simulation.result b/mysql-test/r/error_simulation.result
index 006c51d1880..edb97d4ab2e 100644
--- a/mysql-test/r/error_simulation.result
+++ b/mysql-test/r/error_simulation.result
@@ -100,3 +100,24 @@ DROP TABLE t1,t2;
#
# End of 5.1 tests
#
+#
+# BUG#11747548:DETECT ORPHAN TEMP-POOL FILES, AND HANDLE GRACEFULLY.
+#
+#Set up.
+CREATE TABLE pid_table(pid_no INT);
+CREATE TABLE t1 (a BLOB);
+INSERT INTO t1 VALUES (1), (2);
+#Create MYD and MYI files for intrinsic temp table.
+LOAD DATA LOCAL INFILE 'pid_file' INTO TABLE pid_table;
+#Reports an error since the temp file already exists.
+SELECT a FROM t1 ORDER BY rand(1);
+a
+1
+2
+#With patch, the query executes successfully.
+SELECT a FROM t1 ORDER BY rand(1);
+a
+1
+2
+#cleanup
+DROP TABLE t1, pid_table;
diff --git a/mysql-test/r/file_contents.result b/mysql-test/r/file_contents.result
index cbf37e0f15c..2b5e6e6229b 100644
--- a/mysql-test/r/file_contents.result
+++ b/mysql-test/r/file_contents.result
@@ -1,6 +1,6 @@
Checking 'INFO_SRC' and 'INFO_BIN'
-INFO_SRC: Found MariaDB version number / Found revision id
+INFO_SRC: Found MariaDB version number / Found GIT revision id
INFO_BIN: Found 'Compiler ... used' line / Found 'Feature flags' line
End of tests
diff --git a/mysql-test/r/func_set.result b/mysql-test/r/func_set.result
index 93757800505..dfc3faf3fac 100644
--- a/mysql-test/r/func_set.result
+++ b/mysql-test/r/func_set.result
@@ -5,7 +5,7 @@ explain extended select INTERVAL(55,10,20,30,40,50,60,70,80,90,100),interval(3,1
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select interval((55,10,20,30,40,50,60,70,80,90,100)) AS `INTERVAL(55,10,20,30,40,50,60,70,80,90,100)`,interval((3,1,(1 + 1),(((1 + 1) + 1) + 1))) AS `interval(3,1,1+1,1+1+1+1)`,field('IBM','NCA','ICL','SUN','IBM','DIGITAL') AS `field("IBM","NCA","ICL","SUN","IBM","DIGITAL")`,field('A','B','C') AS `field("A","B","C")`,elt(2,'ONE','TWO','THREE') AS `elt(2,"ONE","TWO","THREE")`,interval((0,1,2,3,4)) AS `interval(0,1,2,3,4)`,(elt(1,1,2,3) | 0) AS `elt(1,1,2,3)|0`,(elt(1,1.1,1.2,1.3) + 0) AS `elt(1,1.1,1.2,1.3)+0`
+Note 1003 select interval(55,10,20,30,40,50,60,70,80,90,100) AS `INTERVAL(55,10,20,30,40,50,60,70,80,90,100)`,interval(3,1,(1 + 1),(((1 + 1) + 1) + 1)) AS `interval(3,1,1+1,1+1+1+1)`,field('IBM','NCA','ICL','SUN','IBM','DIGITAL') AS `field("IBM","NCA","ICL","SUN","IBM","DIGITAL")`,field('A','B','C') AS `field("A","B","C")`,elt(2,'ONE','TWO','THREE') AS `elt(2,"ONE","TWO","THREE")`,interval(0,1,2,3,4) AS `interval(0,1,2,3,4)`,(elt(1,1,2,3) | 0) AS `elt(1,1,2,3)|0`,(elt(1,1.1,1.2,1.3) + 0) AS `elt(1,1.1,1.2,1.3)+0`
SELECT INTERVAL(13, 7, 14, 21, 28, 35, 42, 49, 56);
INTERVAL(13, 7, 14, 21, 28, 35, 42, 49, 56)
1
diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result
index f28d9e7b659..06e95a84ac9 100644
--- a/mysql-test/r/gis.result
+++ b/mysql-test/r/gis.result
@@ -1686,6 +1686,9 @@ create table t1 (pt point);
insert into t1 values(Geomfromtext('POLYGON((1 1, 2 2, 2 1, 1 1))'));
ERROR 22007: Incorrect POINT value: 'POLYGON' for column 'pt' at row 1
drop table t1;
+SELECT st_astext(ST_Buffer(ST_PolygonFromText('POLYGON((3 5, 2 4, 2 5, 3 5))'), -100));
+st_astext(ST_Buffer(ST_PolygonFromText('POLYGON((3 5, 2 4, 2 5, 3 5))'), -100))
+GEOMETRYCOLLECTION EMPTY
End of 5.5 tests
SHOW CREATE TABLE information_schema.geometry_columns;
Table Create Table
diff --git a/mysql-test/r/group_by_innodb.result b/mysql-test/r/group_by_innodb.result
index 1098579a82d..381e0d7493c 100644
--- a/mysql-test/r/group_by_innodb.result
+++ b/mysql-test/r/group_by_innodb.result
@@ -79,4 +79,48 @@ oidGroup oid oid
1 3 3
1 4 NULL
DROP TABLE t1, t2;
+#
+# MDEV-7193: Incorrect Query Result (MySQL Bug 68897) in MariaDB 10.0.14
+# (fixed by MDEV-5719)
+#
+CREATE TABLE `t1` (
+`param` int(11) NOT NULL,
+`idx` int(11) NOT NULL,
+`text` varchar(255) default NULL,
+PRIMARY KEY (`param`,`idx`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+INSERT INTO `t1` (`param`, `idx`, `text`) VALUES
+(1, 0, 'select'),
+(1, 1, 'Kabel mit Stecker 5-polig'),
+(1, 2, 'Kabel ohne Stecker'),
+(2, 0, 'number'),
+(2, 1, '22'),
+(2, 2, '25');
+CREATE TABLE `t2` (
+`id` int PRIMARY KEY
+);
+INSERT INTO t2 VALUES (1),(2),(3),(4);
+SELECT t2.id AS id, T.text AS xtext,GROUP_CONCAT(T3.text) AS optionen
+FROM t2
+LEFT JOIN t1 AS T ON(T.param=t2.id AND T.idx=0 )
+LEFT JOIN t1 AS T3 ON(T3.param=t2.id AND T3.idx>0 )
+GROUP BY t2.id
+ORDER BY id ASC;
+id xtext optionen
+1 select Kabel mit Stecker 5-polig,Kabel ohne Stecker
+2 number 22,25
+3 NULL NULL
+4 NULL NULL
+SELECT t2.id AS id, T.text AS xtext,GROUP_CONCAT(T3.text) AS optionen
+FROM t2
+LEFT JOIN t1 AS T ON(T.param=t2.id AND T.idx=0 )
+LEFT JOIN t1 AS T3 ON(T3.param=t2.id AND T3.idx>0 )
+GROUP BY t2.id
+ORDER BY id DESC;
+id xtext optionen
+4 NULL NULL
+3 NULL NULL
+2 number 22,25
+1 select Kabel mit Stecker 5-polig,Kabel ohne Stecker
+DROP TABLE t1, t2;
# End of tests
diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result
index 5ceb57969ce..3bfb8d84904 100644
--- a/mysql-test/r/information_schema.result
+++ b/mysql-test/r/information_schema.result
@@ -2010,6 +2010,21 @@ drop view v1;
# Clean-up.
drop database mysqltest;
#
+# Test for bug #16869534 - "QUERYING SUBSET OF COLUMNS DOESN'T USE TABLE
+# CACHE; OPENED_TABLES INCREASES"
+#
+SELECT * FROM INFORMATION_SCHEMA.TABLES;
+SELECT VARIABLE_VALUE INTO @val1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE
+VARIABLE_NAME LIKE 'Opened_tables';
+SELECT ENGINE FROM INFORMATION_SCHEMA.TABLES;
+# The below SELECT query should give same output as above SELECT query.
+SELECT VARIABLE_VALUE INTO @val2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE
+VARIABLE_NAME LIKE 'Opened_tables';
+# The below select should return '1'
+SELECT @val1 = @val2;
+@val1 = @val2
+1
+#
# End of 5.5 tests
#
#
diff --git a/mysql-test/r/join_cache.result b/mysql-test/r/join_cache.result
index 456e17a91f7..c1dbef08c04 100644
--- a/mysql-test/r/join_cache.result
+++ b/mysql-test/r/join_cache.result
@@ -5874,4 +5874,17 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 11 Using where
set join_buffer_space_limit=default;
drop table t1;
+#
+# MDEV-6687: Assertion `0' failed in Protocol::end_statement on query
+#
+SET join_cache_level = 3;
+# The following should have
+# - table order PROFILING,user,
+# - table user accessed with hash_ALL:
+explain
+SELECT * FROM INFORMATION_SCHEMA.PROFILING, mysql.user WHERE password_expired = PAGE_FAULTS_MINOR;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE PROFILING ALL NULL NULL NULL NULL NULL Using where
+1 SIMPLE user hash_ALL NULL #hash#$hj 1 information_schema.PROFILING.PAGE_FAULTS_MINOR 4 Using where; Using join buffer (flat, BNLH join)
+set join_cache_level=default;
set @@optimizer_switch=@save_optimizer_switch;
diff --git a/mysql-test/r/openssl_1.result b/mysql-test/r/openssl_1.result
index 4627f03a8a3..5009a3e0815 100644
--- a/mysql-test/r/openssl_1.result
+++ b/mysql-test/r/openssl_1.result
@@ -3,8 +3,8 @@ create table t1(f1 int);
insert into t1 values (5);
grant select on test.* to ssl_user1@localhost require SSL;
grant select on test.* to ssl_user2@localhost require cipher "DHE-RSA-AES256-SHA";
-grant select on test.* to ssl_user3@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/ST=Uppsala/O=MySQL AB";
-grant select on test.* to ssl_user4@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/ST=Uppsala/O=MySQL AB" ISSUER "/C=SE/ST=Uppsala/L=Uppsala/O=MySQL AB";
+grant select on test.* to ssl_user3@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/ST=Stockholm/L=Stockholm/O=Oracle/OU=MySQL/CN=Client";
+grant select on test.* to ssl_user4@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/ST=Stockholm/L=Stockholm/O=Oracle/OU=MySQL/CN=Client" ISSUER "/C=SE/ST=Stockholm/L=Stockholm/O=Oracle/OU=MySQL/CN=CA";
grant select on test.* to ssl_user5@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "xxx";
flush privileges;
connect(localhost,ssl_user2,,test,MASTER_PORT,MASTER_SOCKET);
diff --git a/mysql-test/r/partition_innodb_plugin.result b/mysql-test/r/partition_innodb_plugin.result
index 7a84745e611..7057bb0a55b 100644
--- a/mysql-test/r/partition_innodb_plugin.result
+++ b/mysql-test/r/partition_innodb_plugin.result
@@ -141,12 +141,12 @@ ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
# First table reported in 'SHOW ENGINE InnoDB STATUS'
SHOW ENGINE InnoDB STATUS;
Type Name Status
-InnoDB index `PRIMARY` of table `test`.`t``\""e` /* Partition `p0``\""e`, Subpartition `sp0``\""e` */
+InnoDB index `PRIMARY` of table `test`.`t``\""e` /* Partition `p0``\""e`, Subpartition `sp0``\""e` */
set @old_sql_mode = @@sql_mode;
set sql_mode = 'ANSI_QUOTES';
SHOW ENGINE InnoDB STATUS;
Type Name Status
-InnoDB index `PRIMARY` of table `test`.`t``\""e` /* Partition `p0``\""e`, Subpartition `sp0``\""e` */
+InnoDB index `PRIMARY` of table `test`.`t``\""e` /* Partition `p0``\""e`, Subpartition `sp0``\""e` */
set @@sql_mode = @old_sql_mode;
# con1
ROLLBACK;
diff --git a/mysql-test/r/select_jcl6.result b/mysql-test/r/select_jcl6.result
index 3b51efa26b0..e1014002784 100644
--- a/mysql-test/r/select_jcl6.result
+++ b/mysql-test/r/select_jcl6.result
@@ -4423,7 +4423,7 @@ INSERT INTO t1 VALUES
EXPLAIN SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2
-1 SIMPLE t2 hash_ALL a #hash#$hj 14 test.t1.a 2 Using where; Using join buffer (flat, BNLH join)
+1 SIMPLE t2 hash_ALL a #hash#$hj 2 test.t1.a 2 Using where; Using join buffer (flat, BNLH join)
SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2;
1
1
@@ -4433,7 +4433,7 @@ SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2;
EXPLAIN SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2 FORCE INDEX(a);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2
-1 SIMPLE t2 hash_ALL a #hash#$hj 14 test.t1.a 2 Using where; Using join buffer (flat, BNLH join)
+1 SIMPLE t2 hash_ALL a #hash#$hj 2 test.t1.a 2 Using where; Using join buffer (flat, BNLH join)
SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2 FORCE INDEX(a);
1
1
diff --git a/mysql-test/r/selectivity.result b/mysql-test/r/selectivity.result
index 3f2343fa365..620bdc6bd50 100644
--- a/mysql-test/r/selectivity.result
+++ b/mysql-test/r/selectivity.result
@@ -1409,4 +1409,40 @@ Note 1003 select `test`.`a`.`a` AS `a`,`test`.`a`.`b` AS `b`,`test`.`b`.`a` AS `
set histogram_size=@save_histogram_size;
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
drop table t0,t1,t2;
+#
+# Bug mdev-7316: a conjunct in WHERE with selectivity == 0
+#
+CREATE TABLE t1 (a varchar(16), b int, PRIMARY KEY(a), KEY(b)) ENGINE=INNODB;
+Warnings:
+Warning 1286 Unknown storage engine 'INNODB'
+Warning 1266 Using storage engine MyISAM for table 't1'
+INSERT INTO t1 VALUES
+('USAChinese',10), ('USAEnglish',20), ('USAFrench',30);
+CREATE TABLE t2 (i int) ENGINE=INNODB;
+Warnings:
+Warning 1286 Unknown storage engine 'INNODB'
+Warning 1266 Using storage engine MyISAM for table 't2'
+INSERT INTO t2 VALUES
+(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(1),(2),(3),(4);
+ANALYZE TABLE t1, t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status OK
+test.t2 analyze status Engine-independent statistics collected
+test.t2 analyze status OK
+set use_stat_tables='preferably';
+set optimizer_use_condition_selectivity=3;
+EXPLAIN EXTENDED
+SELECT * FROM t1, t2
+WHERE a <> 'USARussian' AND b IS NULL;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ref PRIMARY,b b 5 const 1 100.00 Using index condition; Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 14 100.00 Using join buffer (flat, BNL join)
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`i` AS `i` from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`a` <> 'USARussian') and isnull(`test`.`t1`.`b`))
+SELECT * FROM t1, t2
+WHERE a <> 'USARussian' AND b IS NULL;
+a b i
+set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
+DROP TABLE t1,t2;
set use_stat_tables=@save_use_stat_tables;
diff --git a/mysql-test/r/selectivity_innodb.result b/mysql-test/r/selectivity_innodb.result
index 0b7f1c950e5..0acbb465ba8 100644
--- a/mysql-test/r/selectivity_innodb.result
+++ b/mysql-test/r/selectivity_innodb.result
@@ -1419,6 +1419,36 @@ Note 1003 select `test`.`a`.`a` AS `a`,`test`.`a`.`b` AS `b`,`test`.`b`.`a` AS `
set histogram_size=@save_histogram_size;
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
drop table t0,t1,t2;
+#
+# Bug mdev-7316: a conjunct in WHERE with selectivity == 0
+#
+CREATE TABLE t1 (a varchar(16), b int, PRIMARY KEY(a), KEY(b)) ENGINE=INNODB;
+INSERT INTO t1 VALUES
+('USAChinese',10), ('USAEnglish',20), ('USAFrench',30);
+CREATE TABLE t2 (i int) ENGINE=INNODB;
+INSERT INTO t2 VALUES
+(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(1),(2),(3),(4);
+ANALYZE TABLE t1, t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status OK
+test.t2 analyze status Engine-independent statistics collected
+test.t2 analyze status OK
+set use_stat_tables='preferably';
+set optimizer_use_condition_selectivity=3;
+EXPLAIN EXTENDED
+SELECT * FROM t1, t2
+WHERE a <> 'USARussian' AND b IS NULL;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ref PRIMARY,b b 5 const 2 66.67 Using where; Using index
+1 SIMPLE t2 ALL NULL NULL NULL NULL 14 100.00 Using join buffer (flat, BNL join)
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`i` AS `i` from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`a` <> 'USARussian') and isnull(`test`.`t1`.`b`))
+SELECT * FROM t1, t2
+WHERE a <> 'USARussian' AND b IS NULL;
+a b i
+set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
+DROP TABLE t1,t2;
set use_stat_tables=@save_use_stat_tables;
set optimizer_switch=@save_optimizer_switch_for_selectivity_test;
set @tmp_ust= @@use_stat_tables;
@@ -1482,6 +1512,30 @@ select * from t1 where col2 != true;
col1 col2
drop table t1;
#
+# MDEV-7413: optimizer_use_condition_selectivity > 2 crashes 10.0.15+maria-1~wheezy
+#
+CREATE TABLE t1 (
+parent_id int,
+child_group_id int,
+child_user_id int,
+KEY (parent_id,child_group_id,child_user_id)
+) ENGINE=InnoDB;
+CREATE TABLE t2 (
+id int,
+lower_group_name varchar(255),
+directory_id int(20),
+UNIQUE KEY (directory_id)
+) ENGINE=InnoDB;
+CREATE TABLE t3 (id int) ENGINE=InnoDB;
+insert into t1 values (1,1,1),(2,2,2);
+insert into t2 values (10,'foo',10),(20,'bar',20);
+insert into t3 values (101),(102);
+set use_stat_tables = PREFERABLY, optimizer_use_condition_selectivity = 3;
+select * from t1, t2, t3
+where t1.child_user_id=t3.id and t1.child_group_id is null and t2.lower_group_name='foo' and t1.parent_id=t2.id and t2.directory_id=10;
+parent_id child_group_id child_user_id id lower_group_name directory_id id
+drop table t1,t2,t3;
+#
# End of 10.0 tests
#
set use_stat_tables= @tmp_ust;
diff --git a/mysql-test/r/sp_notembedded.result b/mysql-test/r/sp_notembedded.result
index 410441b63e3..3cc4ff4238b 100644
--- a/mysql-test/r/sp_notembedded.result
+++ b/mysql-test/r/sp_notembedded.result
@@ -284,4 +284,23 @@ DROP EVENT teste_bug11763507;
# ------------------------------------------------------------------
# -- End of 5.1 tests
# ------------------------------------------------------------------
+grant create routine on test.* to foo1@localhost identified by 'foo';
+update mysql.user set password = replace(password, '*', '-') where user='foo1';
+show grants;
+Grants for foo1@localhost
+GRANT USAGE ON *.* TO 'foo1'@'localhost' IDENTIFIED BY PASSWORD '*F3A2A51A9B0F2BE2468926B4132313728C250DBF'
+GRANT CREATE ROUTINE ON `test`.* TO 'foo1'@'localhost'
+flush privileges;
+show grants;
+Grants for foo1@localhost
+GRANT USAGE ON *.* TO 'foo1'@'localhost' IDENTIFIED BY PASSWORD '-F3A2A51A9B0F2BE2468926B4132313728C250DBF'
+GRANT CREATE ROUTINE ON `test`.* TO 'foo1'@'localhost'
+create procedure spfoo() select 1;
+show grants;
+Grants for foo1@localhost
+GRANT USAGE ON *.* TO 'foo1'@'localhost' IDENTIFIED BY PASSWORD '-F3A2A51A9B0F2BE2468926B4132313728C250DBF'
+GRANT CREATE ROUTINE ON `test`.* TO 'foo1'@'localhost'
+GRANT EXECUTE, ALTER ROUTINE ON PROCEDURE `test`.`spfoo` TO 'foo1'@'localhost'
+drop procedure spfoo;
+drop user foo1@localhost;
set @@global.concurrent_insert= @old_concurrent_insert;
diff --git a/mysql-test/r/ssl.result b/mysql-test/r/ssl.result
index 0997e8d3e13..6f0ba6a4e1e 100644
--- a/mysql-test/r/ssl.result
+++ b/mysql-test/r/ssl.result
@@ -3,10 +3,10 @@ Variable_name Value
Ssl_cipher DHE-RSA-AES256-SHA
SHOW STATUS LIKE 'Ssl_server_not_before';
Variable_name Value
-Ssl_server_not_before Jan 29 13:33:36 2015 GMT
+Ssl_server_not_before Dec 5 04:48:40 2014 GMT
SHOW STATUS LIKE 'Ssl_server_not_after';
Variable_name Value
-Ssl_server_not_after Jan 24 13:33:36 2035 GMT
+Ssl_server_not_after Dec 1 04:48:40 2029 GMT
drop table if exists t1,t2,t3,t4;
CREATE TABLE t1 (
Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL,
diff --git a/mysql-test/r/subselect_extra.result b/mysql-test/r/subselect_extra.result
index 7616dd429b7..48b80e02e1a 100644
--- a/mysql-test/r/subselect_extra.result
+++ b/mysql-test/r/subselect_extra.result
@@ -447,7 +447,7 @@ WHERE t3.b IN (SELECT v1.b FROM v1, t2
WHERE t2.c = v1.c AND t2.c = v1.b AND v1.b = t3.c);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 system NULL NULL NULL NULL 1
-1 PRIMARY <derived3> ref key1 key1 10 const,const 0 Start temporary
+1 PRIMARY <derived3> ref key1 key1 8 const,const 0 Start temporary
1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using where; End temporary; Using join buffer (flat, BNL join)
3 DERIVED t1 ALL NULL NULL NULL NULL 3
SELECT * FROM t3
diff --git a/mysql-test/r/subselect_extra_no_semijoin.result b/mysql-test/r/subselect_extra_no_semijoin.result
index d178e45d07e..e5b36055c91 100644
--- a/mysql-test/r/subselect_extra_no_semijoin.result
+++ b/mysql-test/r/subselect_extra_no_semijoin.result
@@ -450,7 +450,7 @@ WHERE t2.c = v1.c AND t2.c = v1.b AND v1.b = t3.c);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using where
2 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 1
-2 DEPENDENT SUBQUERY <derived3> ref key1 key1 10 const,const 0 Using where
+2 DEPENDENT SUBQUERY <derived3> ref key1 key1 8 const,const 0 Using where
3 DERIVED t1 ALL NULL NULL NULL NULL 3
SELECT * FROM t3
WHERE t3.b IN (SELECT v1.b FROM v1, t2
diff --git a/mysql-test/r/subselect_mat.result b/mysql-test/r/subselect_mat.result
index 3385612874b..40c0c21ae40 100644
--- a/mysql-test/r/subselect_mat.result
+++ b/mysql-test/r/subselect_mat.result
@@ -2146,6 +2146,57 @@ drop database mysqltest2;
drop database mysqltest3;
drop database mysqltest4;
# End of 5.5 tests
+#
+# MDEV-7220: Materialization strategy is not used for REPLACE ... SELECT
+#
+create table t0(a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t1 (a int, b int, c int);
+insert into t1
+select A.a+B.a*10+C.a*100, A.a+B.a*10+C.a*100, A.a+B.a*10+C.a*100
+from t0 A, t0 B, t0 C;
+create table t2 (a int, b int, c int);
+insert into t2 select A.a, A.a, A.a from t1 A;
+insert into t2 select * from t2;
+insert into t2 select * from t2;
+create table t3 as select * from t2 limit 1;
+# The testcase only makes sense if the following uses Materialization:
+explain
+select * from t1 where (a,b) in (select max(a),b from t2 group by b);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 1000 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.b 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 4000 Using temporary
+flush status;
+replace into t3
+select * from t1 where (a,b) in (select max(a),b from t2 group by b);
+# Sequential reads:
+# 1K is read from t1
+# 4K is read from t2
+# 1K groups is read from the tmp. table
+#
+# Lookups:
+# 4K lookups in group by table
+# 1K lookups in temp.table
+#
+# Writes:
+# 2x 1K writes to temporary tables (grouping table and subquery materialization table
+#
+# The point is that neither counter should be in the millions (this
+# will happen if Materialization is not used
+show status where Variable_name like 'Handler_read%' or Variable_name like 'Handler_%write%';
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 5000
+Handler_read_last 0
+Handler_read_next 0
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_deleted 0
+Handler_read_rnd_next 6003
+Handler_tmp_write 2000
+Handler_write 1000
+drop table t0,t1,t2,t3;
set @subselect_mat_test_optimizer_switch_value=null;
set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
set optimizer_switch='mrr=on,mrr_sort_keys=on,index_condition_pushdown=on';
diff --git a/mysql-test/r/subselect_sj2_jcl6.result b/mysql-test/r/subselect_sj2_jcl6.result
index c45ab02a646..ee8aa39d095 100644
--- a/mysql-test/r/subselect_sj2_jcl6.result
+++ b/mysql-test/r/subselect_sj2_jcl6.result
@@ -891,7 +891,7 @@ WHERE t3.b IN (SELECT b FROM t4);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 1
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
-1 PRIMARY t2 hash_ALL NULL #hash#$hj 5 test.t3.a 1 Using where; Using join buffer (flat, BNLH join)
+1 PRIMARY t2 hash_ALL NULL #hash#$hj 4 test.t3.a 1 Using where; Using join buffer (flat, BNLH join)
1 PRIMARY <derived3> ALL NULL NULL NULL NULL 2 Using join buffer (incremental, BNL join)
2 MATERIALIZED t4 ALL NULL NULL NULL NULL 2
3 DERIVED t1 ALL NULL NULL NULL NULL 1
@@ -1161,7 +1161,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ref PRIMARY PRIMARY 5 const 1 Using where; Using index
1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Start temporary; Using join buffer (flat, BNL join)
1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (incremental, BNL join)
-1 PRIMARY t4 hash_index NULL #hash#$hj:PRIMARY 55:59 test.t3.t3_c 2 Using where; End temporary; Using join buffer (incremental, BNLH join)
+1 PRIMARY t4 hash_index NULL #hash#$hj:PRIMARY 54:59 test.t3.t3_c 2 Using where; End temporary; Using join buffer (incremental, BNLH join)
DROP TABLE t1,t2,t3,t4;
#
# MDEV-6263: Wrong result when using IN subquery with order by
diff --git a/mysql-test/r/subselect_sj_mat.result b/mysql-test/r/subselect_sj_mat.result
index 38690a2d6a1..d5150f047d7 100644
--- a/mysql-test/r/subselect_sj_mat.result
+++ b/mysql-test/r/subselect_sj_mat.result
@@ -2186,3 +2186,54 @@ drop database mysqltest2;
drop database mysqltest3;
drop database mysqltest4;
# End of 5.5 tests
+#
+# MDEV-7220: Materialization strategy is not used for REPLACE ... SELECT
+#
+create table t0(a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t1 (a int, b int, c int);
+insert into t1
+select A.a+B.a*10+C.a*100, A.a+B.a*10+C.a*100, A.a+B.a*10+C.a*100
+from t0 A, t0 B, t0 C;
+create table t2 (a int, b int, c int);
+insert into t2 select A.a, A.a, A.a from t1 A;
+insert into t2 select * from t2;
+insert into t2 select * from t2;
+create table t3 as select * from t2 limit 1;
+# The testcase only makes sense if the following uses Materialization:
+explain
+select * from t1 where (a,b) in (select max(a),b from t2 group by b);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 1000 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.b 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 4000 Using temporary
+flush status;
+replace into t3
+select * from t1 where (a,b) in (select max(a),b from t2 group by b);
+# Sequential reads:
+# 1K is read from t1
+# 4K is read from t2
+# 1K groups is read from the tmp. table
+#
+# Lookups:
+# 4K lookups in group by table
+# 1K lookups in temp.table
+#
+# Writes:
+# 2x 1K writes to temporary tables (grouping table and subquery materialization table
+#
+# The point is that neither counter should be in the millions (this
+# will happen if Materialization is not used
+show status where Variable_name like 'Handler_read%' or Variable_name like 'Handler_%write%';
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 5000
+Handler_read_last 0
+Handler_read_next 0
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_deleted 0
+Handler_read_rnd_next 6003
+Handler_tmp_write 2000
+Handler_write 1000
+drop table t0,t1,t2,t3;
diff --git a/mysql-test/r/table_keyinfo-6838.result b/mysql-test/r/table_keyinfo-6838.result
new file mode 100644
index 00000000000..55b035069ce
--- /dev/null
+++ b/mysql-test/r/table_keyinfo-6838.result
@@ -0,0 +1,12 @@
+CREATE TABLE t1 (i INT, state VARCHAR(997)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (2,'Louisiana'),(9,'Maine');
+CREATE TABLE t2 (state VARCHAR(997), j INT) ENGINE=MyISAM;
+INSERT INTO t2 VALUES ('Louisiana',9),('Alaska',5);
+INSERT INTO t2 SELECT t2.* FROM t2 JOIN t2 AS t3 JOIN t2 AS t4 JOIN t2 AS t5 JOIN t2 AS t6;
+SET @@max_heap_table_size= 16384;
+set @@optimizer_switch='derived_merge=OFF';
+set @@optimizer_switch='extended_keys=ON';
+SELECT * FROM t1 AS t1_1 LEFT JOIN ( t1 AS t1_2 INNER JOIN (SELECT * FROM t2) v2 ON t1_2.i = j ) ON t1_1.state = v2.state LIMIT 1;
+i state i state state j
+2 Louisiana 9 Maine Louisiana 9
+DROP TABLE t1, t2;
diff --git a/mysql-test/r/temp_table_frm.result b/mysql-test/r/temp_table_frm.result
index 4f60ccc32c8..19c66380af2 100644
--- a/mysql-test/r/temp_table_frm.result
+++ b/mysql-test/r/temp_table_frm.result
@@ -7,7 +7,7 @@ variable_name session_status.variable_value - t1.variable_value
OPENED_FILES 0
OPENED_PLUGIN_LIBRARIES 0
OPENED_TABLE_DEFINITIONS 2
-OPENED_TABLES 2
+OPENED_TABLES 1
OPENED_VIEWS 0
truncate table t2;
select variable_name, session_status.variable_value - t1.variable_value
@@ -16,6 +16,6 @@ variable_name session_status.variable_value - t1.variable_value
OPENED_FILES 0
OPENED_PLUGIN_LIBRARIES 0
OPENED_TABLE_DEFINITIONS 2
-OPENED_TABLES 2
+OPENED_TABLES 1
OPENED_VIEWS 0
drop table t1;
diff --git a/mysql-test/r/tmp_table_count-7586.result b/mysql-test/r/tmp_table_count-7586.result
new file mode 100644
index 00000000000..0c526e0d4a3
--- /dev/null
+++ b/mysql-test/r/tmp_table_count-7586.result
@@ -0,0 +1,83 @@
+create table t2 (a int);
+insert into t2 values (1),(2),(3);
+create view v2 as select a from t2;
+flush status;
+select * from v2;
+a
+1
+2
+3
+show status like '%Created_tmp%';
+Variable_name Value
+Created_tmp_disk_tables 0
+Created_tmp_files 0
+Created_tmp_tables 0
+explain select * from v2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3
+select * from (select * from t2) T1;
+a
+1
+2
+3
+show status like '%Created_tmp%';
+Variable_name Value
+Created_tmp_disk_tables 0
+Created_tmp_files 0
+Created_tmp_tables 0
+explain select * from (select * from t2) T1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3
+drop view v2;
+drop table t2;
+CREATE TABLE t1(a int);
+INSERT INTO t1 values(1),(2);
+CREATE TABLE t2(a int);
+INSERT INTO t2 values(1),(2);
+EXPLAIN SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a HAVING a > 1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 test.t1.a 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using temporary
+truncate table performance_schema.events_statements_history_long;
+flush status;
+CREATE TABLE t3 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a HAVING a > 1);
+# Performance schema should be the same as "Created_tmp_tables" variable below
+select sum(created_tmp_tables) from performance_schema.events_statements_history_long;
+sum(created_tmp_tables)
+2
+show status like '%Created_tmp%';
+Variable_name Value
+Created_tmp_disk_tables 0
+Created_tmp_files 0
+Created_tmp_tables 2
+drop table t3;
+EXPLAIN SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2
+truncate table performance_schema.events_statements_history_long;
+flush status;
+CREATE TABLE t3 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a);
+# Performance schema should be the same as "Created_tmp_tables" variable below
+select sum(created_tmp_tables) from performance_schema.events_statements_history_long;
+sum(created_tmp_tables)
+1
+show status like '%Created_tmp%';
+Variable_name Value
+Created_tmp_disk_tables 0
+Created_tmp_files 0
+Created_tmp_tables 1
+drop table t1,t2,t3;
+truncate table performance_schema.events_statements_history_long;
+flush status;
+# Performance schema should be the same as "Created_tmp_tables" variable below
+select sum(created_tmp_tables) from performance_schema.events_statements_history_long;
+sum(created_tmp_tables)
+0
+show status like '%Created_tmp%';
+Variable_name Value
+Created_tmp_disk_tables 0
+Created_tmp_files 0
+Created_tmp_tables 0
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result
index 23d1d76ca26..083ed9686d4 100644
--- a/mysql-test/r/view.result
+++ b/mysql-test/r/view.result
@@ -4908,7 +4908,7 @@ Opened_views 3
show status like 'Opened_table%';
Variable_name Value
Opened_table_definitions 2
-Opened_tables 3
+Opened_tables 2
#
# MDEV-486 LP BUG#1010116 Incorrect query results in
# view and derived tables
@@ -5396,6 +5396,19 @@ DROP VIEW v1;
DROP TABLE t1, t2;
create view v1 as select 1;
drop view v1;
+#
+# MDEV-7260: Crash in get_best_combination when executing multi-table
+# UPDATE with nested views
+#
+CREATE TABLE `t1` (`id` bigint(20));
+INSERT INTO `t1` VALUES (1),(2);
+CREATE TABLE `t2` (`id` bigint(20));
+CREATE TABLE `t3` (`id` bigint(20), `flag` tinyint(4));
+create view v1 as select id from t1;
+create view v2 as select t2.* from (t2 left join v1 using (id));
+update t3 left join v2 using (id) set flag=flag+1;
+drop view v2, v1;
+drop table t1, t2, t3;
# -----------------------------------------------------------------
# -- End of 5.5 tests.
# -----------------------------------------------------------------
diff --git a/mysql-test/r/view_alias.result b/mysql-test/r/view_alias.result
index 72c4bf29f25..e07b40dba13 100644
--- a/mysql-test/r/view_alias.result
+++ b/mysql-test/r/view_alias.result
@@ -109,3 +109,11 @@ DROP VIEW v1;
CREATE VIEW v1 AS select `test`.`t1`.`a` AS `a` from `test`.`t1` where exists(select ' a ' AS `alias` from `test`.`t1` group by ' a ');
DROP VIEW v1;
DROP TABLE t1, t2;
+create view v1 as select interval(55,10) as my_col;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select interval(55,10) AS `my_col` latin1 latin1_swedish_ci
+select * from v1;
+my_col
+1
+drop view v1;
diff --git a/mysql-test/std_data/cacert.pem b/mysql-test/std_data/cacert.pem
index 4e676a206ab..a0ba67444ef 100644
--- a/mysql-test/std_data/cacert.pem
+++ b/mysql-test/std_data/cacert.pem
@@ -1,77 +1,79 @@
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 18344029820145564920 (0xfe9315ee3af2fcf8)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=SE, ST=Uppsala, L=Uppsala, O=MySQL AB
+ Serial Number: 16263805969935345171 (0xe1b4a55c3ddfa613)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=SE, ST=Stockholm, L=Stockholm, O=Oracle, OU=MySQL, CN=CA
Validity
- Not Before: Jan 29 13:33:36 2015 GMT
- Not After : Jan 24 13:33:36 2035 GMT
- Subject: C=SE, ST=Uppsala, L=Uppsala, O=MySQL AB
+ Not Before: Dec 5 04:48:11 2014 GMT
+ Not After : Dec 1 04:48:11 2030 GMT
+ Subject: C=SE, ST=Stockholm, L=Stockholm, O=Oracle, OU=MySQL, CN=CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:ad:79:3b:d1:c4:f3:fd:72:e8:4a:9e:54:db:44:
- 86:c7:57:a9:53:2e:01:5a:5b:04:b8:b7:15:02:28:
- b2:e8:8a:8d:0e:32:29:a6:cc:63:00:fb:e4:7a:ec:
- 27:b0:09:8f:4d:34:95:c5:9e:2e:92:20:8b:ec:88:
- d3:08:75:c7:c0:61:46:60:79:bb:0f:5f:e4:08:d7:
- b2:20:08:1a:71:a9:ea:f2:d6:55:40:26:82:9b:2c:
- 6a:00:66:74:58:ea:e8:6c:77:74:81:10:3b:78:7f:
- 20:75:9c:ac:7a:63:af:0e:b6:7b:e8:94:13:00:b8:
- 7d:33:7a:c7:49:1f:b2:84:ce:0d:89:4a:97:ee:61:
- 0a:1d:8b:a7:8b:45:90:dc:cc:e6:56:dc:aa:28:b2:
- cb:83:09:e7:7b:9a:7c:3e:da:4f:11:d0:b2:95:0d:
- 96:c0:b0:41:63:2d:2b:45:2f:6d:46:38:5a:b0:93:
- e6:07:af:d1:2f:15:ff:84:f3:05:62:a5:28:1a:a4:
- 40:23:3d:c6:77:60:2c:55:7d:fd:af:da:4a:e8:fb:
- 16:03:9a:67:4b:76:a6:ec:96:ba:46:86:f2:fb:7c:
- eb:2c:59:5c:af:e7:79:50:26:05:d4:71:c3:d5:62:
- d5:2b:17:35:d3:32:4e:b4:df:30:7d:8b:fd:ba:c3:
- a6:5d
+ 00:b4:95:bd:24:92:73:06:22:01:13:28:0e:09:a3:
+ 94:05:96:54:9d:dc:8f:83:39:f3:64:7a:31:70:f6:
+ d9:c4:14:19:75:87:a6:b1:ea:52:ed:40:54:5a:f6:
+ 9c:13:8e:d8:76:8f:5a:65:a5:20:19:19:bd:51:9d:
+ ba:35:ce:9a:a9:58:0a:fc:11:6e:1d:cb:a8:f1:92:
+ 79:ee:aa:fc:e3:32:5e:aa:0d:0b:23:34:95:e9:d3:
+ 8e:3f:72:93:90:bc:2c:b0:04:75:4f:a4:4a:a0:32:
+ db:ac:89:ac:34:9b:d0:07:e3:81:e9:ca:5b:26:f0:
+ f5:de:fe:d5:5e:a0:54:26:dd:ec:58:07:6e:b9:e5:
+ 97:f6:20:6d:d8:4a:c0:50:cc:81:e6:d2:3f:c7:47:
+ 70:8b:15:89:65:71:2e:47:c3:42:76:b5:ee:16:0e:
+ 26:97:6a:a3:1c:ad:90:53:50:b0:b1:6d:1d:b0:b8:
+ 6d:df:3c:ee:bd:3b:87:e8:db:4d:3a:72:78:dd:db:
+ 40:3d:c9:20:46:b8:4e:33:bb:76:b7:4f:b2:79:da:
+ 03:cc:f9:75:c0:1d:4c:51:0a:b9:9b:25:34:50:11:
+ 97:df:82:46:02:a9:bc:98:51:3e:c3:df:57:ad:b7:
+ 28:be:de:65:ce:2b:f3:2c:22:f5:af:31:28:1c:ef:
+ 10:09
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
- D0:25:36:E4:E6:DB:8B:6E:4F:8A:4D:20:48:A4:21:3A:58:7E:EF:C4
+ 94:65:A1:A3:87:CF:BF:C1:74:BB:D8:84:97:B6:6B:EE:B2:90:73:B2
X509v3 Authority Key Identifier:
- keyid:D0:25:36:E4:E6:DB:8B:6E:4F:8A:4D:20:48:A4:21:3A:58:7E:EF:C4
+ keyid:94:65:A1:A3:87:CF:BF:C1:74:BB:D8:84:97:B6:6B:EE:B2:90:73:B2
X509v3 Basic Constraints:
CA:TRUE
- Signature Algorithm: sha1WithRSAEncryption
- 8d:9f:56:93:67:4b:77:e1:4c:f0:3c:6b:9c:8a:a0:a5:3d:5d:
- a7:21:72:5e:bc:4c:88:16:61:95:3d:e6:34:da:a6:b0:8c:6e:
- 94:4c:69:ea:c6:8a:fa:2c:3d:bf:f9:8e:b5:d1:69:ac:a1:46:
- 12:95:bc:fd:67:21:1e:ca:0f:49:77:f8:54:29:aa:06:5b:08:
- 0b:8e:0b:4f:9d:52:da:03:9e:a1:31:1b:4a:bb:df:cb:d7:ba:
- b1:20:d7:77:bc:3b:87:e4:ae:46:59:13:88:cd:76:ab:15:68:
- c5:90:d7:01:fb:7b:16:30:7f:f8:1e:c5:3d:a3:e2:61:d9:35:
- fe:70:af:9a:47:12:59:26:27:b1:f6:a2:d8:99:80:a1:a4:a3:
- a3:77:ad:40:90:8c:4e:7e:83:b0:c0:0e:fb:0b:c3:9f:ac:8d:
- ee:65:fe:7d:85:2b:b3:93:62:56:50:f3:ca:68:68:76:37:9d:
- e7:85:13:45:c1:c8:9e:c6:ba:eb:ef:24:85:e8:47:31:82:53:
- 1b:c4:66:b3:c3:e6:89:5f:3e:18:9f:f5:ed:66:19:9e:57:5b:
- 3d:6a:2f:fb:c2:e3:5a:40:d0:5b:2e:ac:f6:a4:c6:5b:ee:a5:
- 76:a0:af:a8:c0:c0:e1:2f:78:6c:7b:fa:fe:a8:2d:8b:cf:2b:
- c8:87:ee:09
+ Signature Algorithm: sha256WithRSAEncryption
+ 32:97:4c:af:bf:ca:e0:10:66:b7:cc:8b:0d:05:d1:d2:ca:b8:
+ 0c:c2:78:57:1f:f6:55:9c:74:fc:bd:31:58:05:18:bc:6d:b5:
+ 79:9a:22:8c:1f:da:33:ea:ef:db:e3:cb:46:bc:36:91:8b:d8:
+ 36:8d:06:40:c2:e9:fe:79:1b:4a:c5:70:74:6d:9d:92:2c:90:
+ be:3c:a7:88:03:e4:b7:ef:f4:b0:00:34:ec:8f:d1:c3:23:2b:
+ ef:bc:ff:ab:a2:0e:bc:ba:11:a5:8e:44:80:fa:d6:f4:26:66:
+ 84:64:2c:e3:23:62:0c:e2:ba:01:ab:5f:24:d6:9d:7e:9c:7b:
+ f4:5d:0e:ba:64:35:6e:a5:fa:98:0c:57:f3:72:e8:3e:2e:ce:
+ b3:f9:e3:fa:ee:aa:79:f9:06:01:19:b2:b3:28:ff:f4:d6:bb:
+ 17:bb:a6:a0:e0:45:23:f3:61:40:31:5c:a3:ee:88:1c:00:31:
+ 54:96:f9:71:37:b5:7f:66:6a:af:04:94:09:39:99:b3:88:86:
+ 9e:bb:d6:36:24:24:f4:37:2c:a6:6c:0b:35:2e:bb:40:af:a7:
+ 64:8a:7f:f2:74:e3:94:0c:32:bd:31:3d:d9:79:68:0f:1e:4b:
+ 17:c0:4e:df:85:3c:f0:84:df:58:f1:d2:4d:2f:ad:ff:1b:d7:
+ c8:9b:fe:dc
-----BEGIN CERTIFICATE-----
-MIIDWzCCAkOgAwIBAgIJAP6TFe468vz4MA0GCSqGSIb3DQEBBQUAMEQxCzAJBgNV
-BAYTAlNFMRAwDgYDVQQIDAdVcHBzYWxhMRAwDgYDVQQHDAdVcHBzYWxhMREwDwYD
-VQQKDAhNeVNRTCBBQjAeFw0xNTAxMjkxMzMzMzZaFw0zNTAxMjQxMzMzMzZaMEQx
-CzAJBgNVBAYTAlNFMRAwDgYDVQQIDAdVcHBzYWxhMRAwDgYDVQQHDAdVcHBzYWxh
-MREwDwYDVQQKDAhNeVNRTCBBQjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBAK15O9HE8/1y6EqeVNtEhsdXqVMuAVpbBLi3FQIosuiKjQ4yKabMYwD75Hrs
-J7AJj000lcWeLpIgi+yI0wh1x8BhRmB5uw9f5AjXsiAIGnGp6vLWVUAmgpssagBm
-dFjq6Gx3dIEQO3h/IHWcrHpjrw62e+iUEwC4fTN6x0kfsoTODYlKl+5hCh2Lp4tF
-kNzM5lbcqiiyy4MJ53uafD7aTxHQspUNlsCwQWMtK0UvbUY4WrCT5gev0S8V/4Tz
-BWKlKBqkQCM9xndgLFV9/a/aSuj7FgOaZ0t2puyWukaG8vt86yxZXK/neVAmBdRx
-w9Vi1SsXNdMyTrTfMH2L/brDpl0CAwEAAaNQME4wHQYDVR0OBBYEFNAlNuTm24tu
-T4pNIEikITpYfu/EMB8GA1UdIwQYMBaAFNAlNuTm24tuT4pNIEikITpYfu/EMAwG
-A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAI2fVpNnS3fhTPA8a5yKoKU9
-Xachcl68TIgWYZU95jTaprCMbpRMaerGivosPb/5jrXRaayhRhKVvP1nIR7KD0l3
-+FQpqgZbCAuOC0+dUtoDnqExG0q738vXurEg13e8O4fkrkZZE4jNdqsVaMWQ1wH7
-exYwf/gexT2j4mHZNf5wr5pHElkmJ7H2otiZgKGko6N3rUCQjE5+g7DADvsLw5+s
-je5l/n2FK7OTYlZQ88poaHY3neeFE0XByJ7GuuvvJIXoRzGCUxvEZrPD5olfPhif
-9e1mGZ5XWz1qL/vC41pA0FsurPakxlvupXagr6jAwOEveGx7+v6oLYvPK8iH7gk=
+MIIDmTCCAoGgAwIBAgIJAOG0pVw936YTMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNV
+BAYTAlNFMRIwEAYDVQQIDAlTdG9ja2hvbG0xEjAQBgNVBAcMCVN0b2NraG9sbTEP
+MA0GA1UECgwGT3JhY2xlMQ4wDAYDVQQLDAVNeVNRTDELMAkGA1UEAwwCQ0EwHhcN
+MTQxMjA1MDQ0ODExWhcNMzAxMjAxMDQ0ODExWjBjMQswCQYDVQQGEwJTRTESMBAG
+A1UECAwJU3RvY2tob2xtMRIwEAYDVQQHDAlTdG9ja2hvbG0xDzANBgNVBAoMBk9y
+YWNsZTEOMAwGA1UECwwFTXlTUUwxCzAJBgNVBAMMAkNBMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAtJW9JJJzBiIBEygOCaOUBZZUndyPgznzZHoxcPbZ
+xBQZdYemsepS7UBUWvacE47Ydo9aZaUgGRm9UZ26Nc6aqVgK/BFuHcuo8ZJ57qr8
+4zJeqg0LIzSV6dOOP3KTkLwssAR1T6RKoDLbrImsNJvQB+OB6cpbJvD13v7VXqBU
+Jt3sWAduueWX9iBt2ErAUMyB5tI/x0dwixWJZXEuR8NCdrXuFg4ml2qjHK2QU1Cw
+sW0dsLht3zzuvTuH6NtNOnJ43dtAPckgRrhOM7t2t0+yedoDzPl1wB1MUQq5myU0
+UBGX34JGAqm8mFE+w99Xrbcovt5lzivzLCL1rzEoHO8QCQIDAQABo1AwTjAdBgNV
+HQ4EFgQUlGWho4fPv8F0u9iEl7Zr7rKQc7IwHwYDVR0jBBgwFoAUlGWho4fPv8F0
+u9iEl7Zr7rKQc7IwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAMpdM
+r7/K4BBmt8yLDQXR0sq4DMJ4Vx/2VZx0/L0xWAUYvG21eZoijB/aM+rv2+PLRrw2
+kYvYNo0GQMLp/nkbSsVwdG2dkiyQvjyniAPkt+/0sAA07I/RwyMr77z/q6IOvLoR
+pY5EgPrW9CZmhGQs4yNiDOK6AatfJNadfpx79F0OumQ1bqX6mAxX83LoPi7Os/nj
++u6qefkGARmysyj/9Na7F7umoOBFI/NhQDFco+6IHAAxVJb5cTe1f2ZqrwSUCTmZ
+s4iGnrvWNiQk9DcspmwLNS67QK+nZIp/8nTjlAwyvTE92XloDx5LF8BO34U88ITf
+WPHSTS+t/xvXyJv+3A==
-----END CERTIFICATE-----
diff --git a/mysql-test/std_data/client-cert.pem b/mysql-test/std_data/client-cert.pem
index c7ee6bc25fd..f60a0884178 100644
--- a/mysql-test/std_data/client-cert.pem
+++ b/mysql-test/std_data/client-cert.pem
@@ -1,26 +1,35 @@
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 3 (0x3)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=SE, ST=Uppsala, L=Uppsala, O=MySQL AB
+ Serial Number: 16263805969935345173 (0xe1b4a55c3ddfa615)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=SE, ST=Stockholm, L=Stockholm, O=Oracle, OU=MySQL, CN=CA
Validity
- Not Before: Jan 29 13:33:49 2015 GMT
- Not After : Jan 24 13:33:49 2035 GMT
- Subject: C=SE, ST=Uppsala, O=MySQL AB
+ Not Before: Dec 5 04:49:23 2014 GMT
+ Not After : Dec 1 04:49:23 2029 GMT
+ Subject: C=SE, ST=Stockholm, L=Stockholm, O=Oracle, OU=MySQL, CN=Client
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
- Public-Key: (1024 bit)
+ Public-Key: (2048 bit)
Modulus:
- 00:c1:f6:6e:41:de:b5:80:fe:10:6d:c5:15:98:53:
- 85:4a:88:51:06:85:30:7f:c9:92:87:51:3a:d6:8d:
- d3:9c:0e:91:c2:39:30:e9:b2:6e:53:4a:3a:aa:a3:
- 8b:ce:c0:93:94:c9:65:db:89:8e:21:2b:af:2a:ff:
- 7b:5a:0f:b9:03:99:f0:eb:20:d4:2c:39:00:0e:5a:
- b7:2b:17:e6:78:54:4f:54:23:36:81:b2:db:3e:48:
- cd:8e:14:36:b4:4f:6e:4d:a1:84:64:29:b7:68:3c:
- 45:3e:eb:9a:9b:8f:e2:d0:35:a8:0c:e6:70:4e:ac:
- 78:74:d5:45:aa:67:33:81:0d
+ 00:c8:d1:a1:fe:a4:8c:f3:1b:17:71:1b:74:35:11:
+ e0:0e:6c:40:0a:fb:c0:f7:f0:eb:bb:c9:1d:a1:c7:
+ d7:b0:8a:f6:f1:cf:fa:6b:d0:79:64:eb:bb:69:a5:
+ 0d:80:06:df:52:14:d2:85:32:cf:bf:ce:2a:47:28:
+ 5b:cd:0b:28:ab:bb:07:33:d5:8b:d3:b4:72:c4:a6:
+ b5:cc:37:b9:03:a8:78:56:25:58:1f:17:30:7c:d1:
+ 0a:bb:ec:3c:a3:03:90:97:99:92:49:ae:b3:57:96:
+ 5c:1a:e9:e8:02:23:ae:c8:c9:05:50:63:e5:77:a1:
+ 9a:73:06:74:0e:46:50:28:d8:c9:4f:c4:1c:37:b8:
+ 52:18:0b:af:19:2b:d4:e5:66:74:a4:f3:f0:da:09:
+ 30:f7:bc:0c:c9:9b:ce:57:06:04:27:e5:a1:2f:2b:
+ a0:ba:b7:99:69:9d:46:fc:21:b6:45:81:9d:b2:3d:
+ 2f:76:15:78:b5:33:62:ac:1e:6b:66:dd:27:61:0a:
+ 47:02:20:2b:57:bb:32:20:dd:06:4c:76:a4:9b:72:
+ 42:4c:9c:2c:76:72:12:1f:4b:df:1e:11:1f:a9:06:
+ 54:dc:88:12:b0:49:d5:40:83:ef:7e:48:43:86:7a:
+ 37:a6:c1:d7:9b:fe:08:34:98:e0:54:3c:30:4f:79:
+ 15:29
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
@@ -28,41 +37,46 @@ Certificate:
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
- 17:61:EA:3F:25:92:55:2B:04:1C:D8:C7:A9:F6:61:C9:D9:99:A4:C9
+ 26:0C:90:BC:97:12:9E:43:BB:5E:FE:EB:A9:66:B3:C3:EE:B2:18:CB
X509v3 Authority Key Identifier:
- keyid:D0:25:36:E4:E6:DB:8B:6E:4F:8A:4D:20:48:A4:21:3A:58:7E:EF:C4
+ keyid:94:65:A1:A3:87:CF:BF:C1:74:BB:D8:84:97:B6:6B:EE:B2:90:73:B2
- Signature Algorithm: sha1WithRSAEncryption
- 78:ea:34:4f:ac:c5:0b:17:bd:c9:f4:28:bd:b2:b1:cd:a7:58:
- 74:4f:00:82:82:c8:a5:71:fe:f4:2f:54:d0:e0:ae:b0:57:87:
- 7d:e6:2e:14:4a:49:21:43:c3:b5:39:e4:7c:0f:fe:8b:c5:5d:
- 5e:84:bc:42:2a:2a:a1:69:10:30:dc:e8:a6:ba:79:8b:a0:56:
- 09:ab:a3:ce:db:32:b2:10:7a:9f:b7:7a:46:80:4a:90:59:af:
- 81:5c:c7:92:20:46:9d:0e:27:20:e5:9a:da:b3:26:96:37:3b:
- 87:e7:13:93:ba:8d:be:d3:9d:7a:cb:6d:96:75:36:54:e1:cd:
- 7e:ff:0d:2d:3c:6a:cd:50:b3:a5:73:a8:83:a0:a7:a2:aa:fa:
- 6e:49:b9:77:fc:03:16:21:bb:c7:8a:4a:79:5f:a9:7e:b9:21:
- 6d:84:a7:5f:96:60:38:42:f7:d0:82:de:87:74:d4:05:93:b8:
- 94:ae:d1:eb:0c:26:96:60:d5:d8:6c:cc:17:40:85:2f:ac:f8:
- 31:f5:f5:76:d0:f1:3f:aa:87:81:b9:a0:93:71:28:6a:b2:f6:
- 74:36:a1:fa:f8:dc:39:a8:cd:b7:75:79:d0:40:73:6c:d6:b2:
- dc:9e:58:a5:51:e5:09:f0:3d:c2:2f:3d:16:ab:41:26:ec:3b:
- 71:04:2d:eb
+ Signature Algorithm: sha256WithRSAEncryption
+ 3e:3c:1f:6c:5b:83:d1:71:15:f5:45:52:fc:7f:67:bc:af:c5:
+ 92:f5:74:78:13:43:3c:fe:b5:61:bf:00:47:43:45:a0:b9:dd:
+ a1:10:0c:29:69:2a:6f:7d:67:3d:1e:09:b5:15:74:bf:73:11:
+ e6:e9:09:b6:6b:b5:cc:1e:06:fd:bd:3a:11:d3:44:bd:ca:7a:
+ a1:f1:09:43:fc:bf:83:89:3a:b1:18:40:f3:cf:6d:12:ef:6e:
+ 0c:b7:a4:99:03:8a:4f:0c:3c:2c:23:78:35:2a:99:ea:de:9c:
+ 1b:e8:8d:19:fb:44:80:13:89:81:c5:05:4b:a7:66:6b:c0:31:
+ 41:f0:6c:60:aa:ec:d3:4c:ff:c1:3b:d5:bb:0d:42:7d:37:5e:
+ 80:e7:9c:7e:60:90:0f:a4:4e:70:20:9c:b1:e4:1b:70:65:b0:
+ ef:bb:41:16:ed:ad:46:ce:34:d3:02:3d:dd:e2:50:fa:3c:5d:
+ f0:e2:71:f8:9a:ef:a3:32:25:c5:8e:64:f4:46:e1:f4:c0:69:
+ d2:34:56:8d:d9:c2:6e:b6:55:3b:6a:4d:b6:d2:84:ab:85:7b:
+ cb:fd:b4:73:40:ba:5d:49:e2:0d:39:77:17:01:49:bb:72:8b:
+ 3a:c9:b1:e2:cd:13:d2:9c:ce:7d:6c:a8:f0:32:c9:a4:af:56:
+ 6f:8a:e6:88
-----BEGIN CERTIFICATE-----
-MIIC6DCCAdCgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJTRTEQ
-MA4GA1UECAwHVXBwc2FsYTEQMA4GA1UEBwwHVXBwc2FsYTERMA8GA1UECgwITXlT
-UUwgQUIwHhcNMTUwMTI5MTMzMzQ5WhcNMzUwMTI0MTMzMzQ5WjAyMQswCQYDVQQG
-EwJTRTEQMA4GA1UECAwHVXBwc2FsYTERMA8GA1UECgwITXlTUUwgQUIwgZ8wDQYJ
-KoZIhvcNAQEBBQADgY0AMIGJAoGBAMH2bkHetYD+EG3FFZhThUqIUQaFMH/JkodR
-OtaN05wOkcI5MOmyblNKOqqji87Ak5TJZduJjiErryr/e1oPuQOZ8Osg1Cw5AA5a
-tysX5nhUT1QjNoGy2z5IzY4UNrRPbk2hhGQpt2g8RT7rmpuP4tA1qAzmcE6seHTV
-RapnM4ENAgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5T
-U0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBQXYeo/JZJVKwQc2Mep
-9mHJ2ZmkyTAfBgNVHSMEGDAWgBTQJTbk5tuLbk+KTSBIpCE6WH7vxDANBgkqhkiG
-9w0BAQUFAAOCAQEAeOo0T6zFCxe9yfQovbKxzadYdE8AgoLIpXH+9C9U0OCusFeH
-feYuFEpJIUPDtTnkfA/+i8VdXoS8QioqoWkQMNzoprp5i6BWCaujztsyshB6n7d6
-RoBKkFmvgVzHkiBGnQ4nIOWa2rMmljc7h+cTk7qNvtOdesttlnU2VOHNfv8NLTxq
-zVCzpXOog6Cnoqr6bkm5d/wDFiG7x4pKeV+pfrkhbYSnX5ZgOEL30ILeh3TUBZO4
-lK7R6wwmlmDV2GzMF0CFL6z4MfX1dtDxP6qHgbmgk3EoarL2dDah+vjcOajNt3V5
-0EBzbNay3J5YpVHlCfA9wi89FqtBJuw7cQQt6w==
+MIIDyDCCArCgAwIBAgIJAOG0pVw936YVMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNV
+BAYTAlNFMRIwEAYDVQQIDAlTdG9ja2hvbG0xEjAQBgNVBAcMCVN0b2NraG9sbTEP
+MA0GA1UECgwGT3JhY2xlMQ4wDAYDVQQLDAVNeVNRTDELMAkGA1UEAwwCQ0EwHhcN
+MTQxMjA1MDQ0OTIzWhcNMjkxMjAxMDQ0OTIzWjBnMQswCQYDVQQGEwJTRTESMBAG
+A1UECAwJU3RvY2tob2xtMRIwEAYDVQQHDAlTdG9ja2hvbG0xDzANBgNVBAoMBk9y
+YWNsZTEOMAwGA1UECwwFTXlTUUwxDzANBgNVBAMMBkNsaWVudDCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAMjRof6kjPMbF3EbdDUR4A5sQAr7wPfw67vJ
+HaHH17CK9vHP+mvQeWTru2mlDYAG31IU0oUyz7/OKkcoW80LKKu7BzPVi9O0csSm
+tcw3uQOoeFYlWB8XMHzRCrvsPKMDkJeZkkmus1eWXBrp6AIjrsjJBVBj5XehmnMG
+dA5GUCjYyU/EHDe4UhgLrxkr1OVmdKTz8NoJMPe8DMmbzlcGBCfloS8roLq3mWmd
+RvwhtkWBnbI9L3YVeLUzYqwea2bdJ2EKRwIgK1e7MiDdBkx2pJtyQkycLHZyEh9L
+3x4RH6kGVNyIErBJ1UCD735IQ4Z6N6bB15v+CDSY4FQ8ME95FSkCAwEAAaN7MHkw
+CQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2Vy
+dGlmaWNhdGUwHQYDVR0OBBYEFCYMkLyXEp5Du17+66lms8PushjLMB8GA1UdIwQY
+MBaAFJRloaOHz7/BdLvYhJe2a+6ykHOyMA0GCSqGSIb3DQEBCwUAA4IBAQA+PB9s
+W4PRcRX1RVL8f2e8r8WS9XR4E0M8/rVhvwBHQ0Wgud2hEAwpaSpvfWc9Hgm1FXS/
+cxHm6Qm2a7XMHgb9vToR00S9ynqh8QlD/L+DiTqxGEDzz20S724Mt6SZA4pPDDws
+I3g1Kpnq3pwb6I0Z+0SAE4mBxQVLp2ZrwDFB8GxgquzTTP/BO9W7DUJ9N16A55x+
+YJAPpE5wIJyx5BtwZbDvu0EW7a1GzjTTAj3d4lD6PF3w4nH4mu+jMiXFjmT0RuH0
+wGnSNFaN2cJutlU7ak220oSrhXvL/bRzQLpdSeINOXcXAUm7cos6ybHizRPSnM59
+bKjwMsmkr1ZviuaI
-----END CERTIFICATE-----
diff --git a/mysql-test/std_data/client-key.pem b/mysql-test/std_data/client-key.pem
index 4ca0f1e130c..e0aae4f2c4a 100644
--- a/mysql-test/std_data/client-key.pem
+++ b/mysql-test/std_data/client-key.pem
@@ -1,15 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
-MIICXQIBAAKBgQDB9m5B3rWA/hBtxRWYU4VKiFEGhTB/yZKHUTrWjdOcDpHCOTDp
-sm5TSjqqo4vOwJOUyWXbiY4hK68q/3taD7kDmfDrINQsOQAOWrcrF+Z4VE9UIzaB
-sts+SM2OFDa0T25NoYRkKbdoPEU+65qbj+LQNagM5nBOrHh01UWqZzOBDQIDAQAB
-AoGANRzgEFWF6i6oHQbs5OtqAoDVfy2VnEh8QWWy8PGhUoiCzWaPyE69+zzGV9e0
-/wao4wNLSxSdwOOPcfzHsF/Bz4plBP4GOhq1BJ4TU13RMlVpU0G2CCJNmc7Fz/g/
-iFk7NrhJ+hS22QuC5R/upQaDmKvn3USppXurh7NbayjQRhkCQQDsd2XEdHzOqr1A
-fvd3tzAbmOoiSz05OHaVNJdHwsnWRASgn//YHCxaQCw/mt3hWjvxgRfS3kuDGFcy
-KAwa/tbnAkEA0fwyfqZERZIRH1sSxXclqbmSRfF9PsDvS8DsjjUVkj/Td4KV7DKI
-OWEv9d3VZvioIVaACeoGgmc6jdD6tAGN6wJBAN5Pyj+OfKAX6WEvfRzx/qqTctvW
-/LJFIUdZcDipKvTkca1Jf1D/+7rFxlPuF1f8a4q7oVhAYaHYSnH/MJJYsFUCQQDB
-ukofvGe6Q7NWWWCtG2p89r7zloM1VSywmBHmdSUso4QGe0yz+D7jqT1lOT872+bJ
-sxM3klhlELXdxtK1JcX3AkBqnkbKafhVdIojRvxwY1NXD2HrxZGNbl+r/0usrQc9
-viRpCxVsqPeseK9sxbL+xDJ6a1ofJrLg8YJLFapOqWTh
+MIIEowIBAAKCAQEAyNGh/qSM8xsXcRt0NRHgDmxACvvA9/Dru8kdocfXsIr28c/6
+a9B5ZOu7aaUNgAbfUhTShTLPv84qRyhbzQsoq7sHM9WL07RyxKa1zDe5A6h4ViVY
+HxcwfNEKu+w8owOQl5mSSa6zV5ZcGunoAiOuyMkFUGPld6GacwZ0DkZQKNjJT8Qc
+N7hSGAuvGSvU5WZ0pPPw2gkw97wMyZvOVwYEJ+WhLyugureZaZ1G/CG2RYGdsj0v
+dhV4tTNirB5rZt0nYQpHAiArV7syIN0GTHakm3JCTJwsdnISH0vfHhEfqQZU3IgS
+sEnVQIPvfkhDhno3psHXm/4INJjgVDwwT3kVKQIDAQABAoIBAFrliE2abbIcMSAh
+LRhYXvIoTVSrX0za39i/z4nKyvY98EjDurXSRyBHEy1eaB3q/mpIwoFH3oES8FAF
+FIha5K3Wmgv8PK42nzwjuWYWUsg1GULk5F4uQOQ+On2VEF0439m+yVhQmxyqEkac
+WUeenx6C3sTkcpkTrLUj1qQfb2kM6JmeGsXfJNFLP/U36x8Q6kp2089DxBFgVcFu
+W3ge24W08umDBKuZWIF5B9GX8JFzmbAwPT2KATppGeroX0+bo4KAts4F1dBKmbrm
+3815kqYnz+VqyWbw6AHUA7aw2TY6QIT1oHrm+EdfnOQZaf8d/2CHWlIZPmxB46Lz
+6zQTVgECgYEA/L9awju31alISm0WYOPZBBndIHsOve4iKcMmy85GTKSvV+cAvgAZ
+uQwabZi4ZYHYaa4LPF0hbTb5IdV6krQzGYXpAjlwaarW0Zx4VoQIErWyji79OnFD
+QpbzIPGQiUAc0D7Gk7kJpwNmpgjyYcSkjEibF4cFEhDpTVlccbgxboUCgYEAy2c0
+tIfKiu1hwo/8UdcO4LQ6LWJdbIDdNU45HCk/IhIe4FrB0pXnk1yIBBn0ezY7Mgzy
+USYlfPTjFmnQOFF/6bHyGmeB4YTYamlTDuHlUUdH76brCZ3ywUlqpToiAPJFjx36
+nTNjo8JLF7eyjMOy4uN6eJzzS7OP9GwsHllux1UCgYBeFLCo+me8va2uHpsk58th
+TmtUatoa8uh+mSj41kiuwOKQGunYz9rDWfEAeMey6TlwZRvDlXsa10q3QGrG7xLS
+XllUvaLNgo1CKzdUJQOIS2AysuUJ+x0pTV0lFyZRIK9ZCPUMCeXA6HAuP8hRgkwp
+9+DbSiQmDGt7olbZ8dFcrQKBgQCOFzzUWH//aTD/z8H+EfQMuRpjFfIZmDPvxwNS
+TuYRkQMMy5nW2G17ngpOgyss34eewTiNw84waoow4B5bGWP4Bx0PoPs0Za8hNw6U
+uO2PR/JS0hIjF7m7mOPtJJ0YeCZrgg/OvVV/0nzOxr7uYs+WfD7T/yBe48NOhjqT
+wPoIOQKBgGRLd3G8b0AbPTv4NVwzIl3xKHCKYd1EcBbfyPWjAZ8+BagEPK8mJfOt
+MXkMrSKOq6ShEfzRsdJna7eI0te3zNXXFu/G3IHQZUdC0RtksW5T9tXvASRN3wnX
++aaoIM1q/KUgfH0TF/1pQPHFSUfFrGyLDiCDUu1sJ2ijULr5rZES
-----END RSA PRIVATE KEY-----
diff --git a/mysql-test/std_data/server-cert.pem b/mysql-test/std_data/server-cert.pem
index ce51fe0d78f..f6acc62ff5f 100644
--- a/mysql-test/std_data/server-cert.pem
+++ b/mysql-test/std_data/server-cert.pem
@@ -1,26 +1,35 @@
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 1 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=SE, ST=Uppsala, L=Uppsala, O=MySQL AB
+ Serial Number: 16263805969935345172 (0xe1b4a55c3ddfa614)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=SE, ST=Stockholm, L=Stockholm, O=Oracle, OU=MySQL, CN=CA
Validity
- Not Before: Jan 29 13:33:36 2015 GMT
- Not After : Jan 24 13:33:36 2035 GMT
- Subject: C=SE, ST=Uppsala, O=MySQL AB, CN=localhost
+ Not Before: Dec 5 04:48:40 2014 GMT
+ Not After : Dec 1 04:48:40 2029 GMT
+ Subject: C=SE, ST=Stockholm, L=Stockholm, O=Oracle, OU=MySQL, CN=localhost
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
- Public-Key: (1024 bit)
+ Public-Key: (2048 bit)
Modulus:
- 00:9c:3a:93:e6:10:8c:b3:e2:57:2f:57:5d:03:4f:
- 0a:e6:fd:44:1a:f3:49:42:70:58:3a:d5:a3:96:ef:
- f2:98:39:09:fa:8c:57:12:d5:8b:1e:a5:b8:35:c0:
- 81:18:6d:45:c8:43:17:28:47:cc:67:8d:dc:3f:9e:
- 29:0a:f8:e5:99:ec:01:ca:d1:42:62:91:47:ee:85:
- 1b:b6:65:95:49:08:99:b8:b9:b6:2a:cf:04:05:e9:
- 5f:a3:7f:d1:c3:08:a0:37:3f:d6:fe:eb:d4:dd:7c:
- 0a:37:ad:00:43:d1:5d:cf:21:56:9c:d4:6b:d2:7c:
- 56:5e:25:fa:e4:2a:ef:14:95
+ 00:e9:20:e7:05:51:07:3a:48:b9:e2:62:a2:24:45:
+ 1f:f1:54:34:22:5c:62:86:9b:01:e8:c2:45:90:00:
+ 8d:4e:e4:a2:ea:e9:d7:b5:95:25:ce:18:ac:1a:4f:
+ b3:e6:30:46:af:20:13:40:84:df:21:dc:df:09:e5:
+ a0:7f:81:12:6e:1e:84:58:5c:a1:11:db:aa:b6:04:
+ e0:fc:1e:0c:11:2e:f3:30:62:1a:f9:ee:df:fe:a3:
+ d3:d6:83:6e:ad:e8:8d:98:89:b1:69:63:b8:72:f4:
+ 5a:e6:22:5e:73:64:95:ef:56:92:92:0b:e1:93:a5:
+ d7:4c:41:47:e7:31:ed:09:68:b3:c5:6e:c1:1b:01:
+ 39:bb:f1:8f:bf:ba:f4:02:e2:e5:e5:9e:b7:d6:9a:
+ b2:94:76:9b:48:d8:27:18:0e:9f:30:98:f5:9a:3e:
+ 23:e6:3b:4a:48:ee:a5:26:e8:80:94:37:e4:4a:ba:
+ ff:9f:42:b9:32:dd:7a:9d:63:11:a8:25:99:b1:1f:
+ 86:e5:7c:b1:31:e3:12:11:0c:eb:f6:1d:02:4b:1d:
+ 34:cb:74:1d:7f:2f:40:c0:81:e2:04:d4:8e:ea:96:
+ f8:22:35:8e:ab:b6:99:33:36:ef:b5:83:11:88:6d:
+ 06:0f:76:4d:bf:db:a8:df:6c:3c:91:e2:ba:73:a0:
+ 73:45
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
@@ -28,41 +37,46 @@ Certificate:
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
- E2:04:9A:5D:CB:44:EC:98:C9:84:13:36:A4:7A:41:AC:34:3D:CD:0C
+ E4:31:D8:D5:06:EA:C6:B3:A2:F6:01:39:8F:58:08:36:2C:7B:3F:DB
X509v3 Authority Key Identifier:
- keyid:D0:25:36:E4:E6:DB:8B:6E:4F:8A:4D:20:48:A4:21:3A:58:7E:EF:C4
+ keyid:94:65:A1:A3:87:CF:BF:C1:74:BB:D8:84:97:B6:6B:EE:B2:90:73:B2
- Signature Algorithm: sha1WithRSAEncryption
- 28:f8:8b:22:d4:8e:00:29:cb:0e:b2:82:f1:a6:3b:e2:c6:76:
- 0a:79:b5:e3:6b:b2:80:c9:af:8b:df:c5:d7:f4:cb:ab:37:3c:
- b2:be:78:b7:2d:ac:77:f1:52:bd:6c:ae:a4:70:1d:98:92:e5:
- 07:71:99:6c:70:4e:f2:c5:9d:da:c4:31:29:3e:fb:df:82:90:
- 5c:76:97:0a:70:c3:dd:0c:cc:be:7d:4c:40:f7:25:9f:6f:d3:
- 37:c5:9b:1a:09:e1:fe:28:08:59:79:17:ac:64:cb:aa:e0:ac:
- 17:f3:3e:72:69:91:f2:16:8d:c6:3e:89:33:77:be:74:8f:69:
- ad:9f:4d:96:e1:51:68:ba:4c:7b:3f:26:7f:14:38:be:e9:07:
- 5d:2b:c2:fb:58:1d:40:c3:b8:21:a8:ee:0e:69:82:7a:21:67:
- 36:16:41:08:dc:71:e4:7c:d2:f1:58:3b:c8:7b:56:63:b4:1c:
- f6:7c:2a:3e:95:2b:03:9f:9c:41:b9:95:1a:bc:ab:b7:39:1b:
- 8e:68:6e:78:ac:2e:18:00:3c:bf:c6:42:c0:62:5f:ba:ec:9f:
- 81:da:0e:76:94:a7:88:68:71:22:ef:d1:4a:15:94:5e:cb:5a:
- 9c:af:59:b3:f7:1a:ad:8f:74:e8:fc:a5:b1:da:f9:4f:fc:d6:
- f8:11:4c:a9
+ Signature Algorithm: sha256WithRSAEncryption
+ 46:ef:cd:bf:c1:ef:36:a9:cb:99:b5:be:e2:a7:ba:69:0d:f5:
+ 9b:63:39:78:32:35:01:a8:b9:f1:70:0e:b5:d1:8f:94:2e:7a:
+ cb:65:d4:d0:b4:ad:52:b8:51:5f:64:2e:a8:08:a5:71:fe:c2:
+ 35:8a:0d:28:26:e5:be:ca:d7:f4:79:54:e1:27:8f:87:92:d3:
+ 04:72:1b:cc:c4:7f:8b:26:09:92:2d:c8:6f:27:da:97:31:80:
+ 0f:83:84:9c:e0:a4:88:c9:e3:8f:35:e7:de:bd:31:e2:fa:52:
+ 83:de:ee:5c:60:6e:8f:a5:8d:5e:53:41:18:42:f3:03:0b:05:
+ 0b:59:09:42:2e:1b:0b:29:b3:fe:11:3b:d5:ad:3f:4d:24:e8:
+ c0:da:4c:0d:93:94:ec:cd:18:0f:66:cd:03:d3:ee:a0:b2:7f:
+ 64:d7:39:66:19:72:9f:64:43:38:b4:b6:b3:ea:6f:39:e7:09:
+ 98:90:9f:6c:f5:e8:b3:2e:09:8d:7b:76:65:30:f4:c4:9b:8e:
+ 10:4e:9b:8c:93:63:44:9d:2b:8a:f3:f0:cf:f8:7b:65:95:38:
+ fb:b4:92:e8:6c:11:03:a2:a2:2f:ea:e0:22:b7:cd:cf:0d:a5:
+ 91:23:14:47:0c:34:8f:f1:11:cc:e8:1e:37:53:ec:a1:01:81:
+ 20:c0:2c:f5
-----BEGIN CERTIFICATE-----
-MIIC/DCCAeSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJTRTEQ
-MA4GA1UECAwHVXBwc2FsYTEQMA4GA1UEBwwHVXBwc2FsYTERMA8GA1UECgwITXlT
-UUwgQUIwHhcNMTUwMTI5MTMzMzM2WhcNMzUwMTI0MTMzMzM2WjBGMQswCQYDVQQG
-EwJTRTEQMA4GA1UECAwHVXBwc2FsYTERMA8GA1UECgwITXlTUUwgQUIxEjAQBgNV
-BAMMCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAnDqT5hCM
-s+JXL1ddA08K5v1EGvNJQnBYOtWjlu/ymDkJ+oxXEtWLHqW4NcCBGG1FyEMXKEfM
-Z43cP54pCvjlmewBytFCYpFH7oUbtmWVSQiZuLm2Ks8EBelfo3/RwwigNz/W/uvU
-3XwKN60AQ9FdzyFWnNRr0nxWXiX65CrvFJUCAwEAAaN7MHkwCQYDVR0TBAIwADAs
-BglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYD
-VR0OBBYEFOIEml3LROyYyYQTNqR6Qaw0Pc0MMB8GA1UdIwQYMBaAFNAlNuTm24tu
-T4pNIEikITpYfu/EMA0GCSqGSIb3DQEBBQUAA4IBAQAo+Isi1I4AKcsOsoLxpjvi
-xnYKebXja7KAya+L38XX9MurNzyyvni3Lax38VK9bK6kcB2YkuUHcZlscE7yxZ3a
-xDEpPvvfgpBcdpcKcMPdDMy+fUxA9yWfb9M3xZsaCeH+KAhZeResZMuq4KwX8z5y
-aZHyFo3GPokzd750j2mtn02W4VFoukx7PyZ/FDi+6QddK8L7WB1Aw7ghqO4OaYJ6
-IWc2FkEI3HHkfNLxWDvIe1ZjtBz2fCo+lSsDn5xBuZUavKu3ORuOaG54rC4YADy/
-xkLAYl+67J+B2g52lKeIaHEi79FKFZRey1qcr1mz9xqtj3To/KWx2vlP/Nb4EUyp
+MIIDyzCCArOgAwIBAgIJAOG0pVw936YUMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNV
+BAYTAlNFMRIwEAYDVQQIDAlTdG9ja2hvbG0xEjAQBgNVBAcMCVN0b2NraG9sbTEP
+MA0GA1UECgwGT3JhY2xlMQ4wDAYDVQQLDAVNeVNRTDELMAkGA1UEAwwCQ0EwHhcN
+MTQxMjA1MDQ0ODQwWhcNMjkxMjAxMDQ0ODQwWjBqMQswCQYDVQQGEwJTRTESMBAG
+A1UECAwJU3RvY2tob2xtMRIwEAYDVQQHDAlTdG9ja2hvbG0xDzANBgNVBAoMBk9y
+YWNsZTEOMAwGA1UECwwFTXlTUUwxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBAOkg5wVRBzpIueJioiRFH/FUNCJcYoab
+AejCRZAAjU7kourp17WVJc4YrBpPs+YwRq8gE0CE3yHc3wnloH+BEm4ehFhcoRHb
+qrYE4PweDBEu8zBiGvnu3/6j09aDbq3ojZiJsWljuHL0WuYiXnNkle9WkpIL4ZOl
+10xBR+cx7Qlos8VuwRsBObvxj7+69ALi5eWet9aaspR2m0jYJxgOnzCY9Zo+I+Y7
+SkjupSbogJQ35Eq6/59CuTLdep1jEaglmbEfhuV8sTHjEhEM6/YdAksdNMt0HX8v
+QMCB4gTUjuqW+CI1jqu2mTM277WDEYhtBg92Tb/bqN9sPJHiunOgc0UCAwEAAaN7
+MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQg
+Q2VydGlmaWNhdGUwHQYDVR0OBBYEFOQx2NUG6sazovYBOY9YCDYsez/bMB8GA1Ud
+IwQYMBaAFJRloaOHz7/BdLvYhJe2a+6ykHOyMA0GCSqGSIb3DQEBCwUAA4IBAQBG
+782/we82qcuZtb7ip7ppDfWbYzl4MjUBqLnxcA610Y+ULnrLZdTQtK1SuFFfZC6o
+CKVx/sI1ig0oJuW+ytf0eVThJ4+HktMEchvMxH+LJgmSLchvJ9qXMYAPg4Sc4KSI
+yeOPNefevTHi+lKD3u5cYG6PpY1eU0EYQvMDCwULWQlCLhsLKbP+ETvVrT9NJOjA
+2kwNk5TszRgPZs0D0+6gsn9k1zlmGXKfZEM4tLaz6m855wmYkJ9s9eizLgmNe3Zl
+MPTEm44QTpuMk2NEnSuK8/DP+HtllTj7tJLobBEDoqIv6uAit83PDaWRIxRHDDSP
+8RHM6B43U+yhAYEgwCz1
-----END CERTIFICATE-----
diff --git a/mysql-test/std_data/server-key.pem b/mysql-test/std_data/server-key.pem
index 4377302efb8..89aead41877 100644
--- a/mysql-test/std_data/server-key.pem
+++ b/mysql-test/std_data/server-key.pem
@@ -1,15 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
-MIICXAIBAAKBgQCcOpPmEIyz4lcvV10DTwrm/UQa80lCcFg61aOW7/KYOQn6jFcS
-1Ysepbg1wIEYbUXIQxcoR8xnjdw/nikK+OWZ7AHK0UJikUfuhRu2ZZVJCJm4ubYq
-zwQF6V+jf9HDCKA3P9b+69TdfAo3rQBD0V3PIVac1GvSfFZeJfrkKu8UlQIDAQAB
-AoGAPWQDZD+SmslRi0fgRAGWfih9z71UR2hQM2ZqL1DA2rJnSm5FdSA21+c1GOI5
-mHiwGD7M5cY4+2RSbSlgZXBjAFj+V0NReudoRMymTLCB8LsuaOSbPxMn92NffGKH
-BQmZRncj+Sj+dTvTmnbaCzjGMEw6UUFBIus6nOH/dl3+TA0CQQDKuiwhreU2gUOT
-ztmc+DggMWOWMs2Ji2jMJCpMrdxDSwxVas6jgaDesQ/9nL7F8RzPtliv6qaDCMfT
-XoXGKPuvAkEAxUhfb/FkZ6MwDs2MyKCNhZjAoEvFESdGP/xiBzLlbDZSRDEUMNRS
-sJrUYOIDUl3TIOvFJVh7tCQftygM3ciw+wJALcvy7kTPdAmtj3V6GYjFfRhLLAIc
-Bod0zDEbUSkxig4pIh63wZ4mDkinmR5Qxnyaip3h2RPEO/O+2JQQ2lwlxwJBAKPi
-TTXHB6t4SrHhWzRG+4mhrVL73oczYw5AcIaeZyuPrKNtSeKOXurKk+avmibQPlU4
-xpsReCHbaGVUZevPjgUCQAU5WDLCV2DTXEb42PDuvRn7M7yw853CaN2d7j5Kliun
-7lS42fcyaFttfLpopCvAhZ0fVRpJGgCcAvoA/zN8uco=
+MIIEpQIBAAKCAQEA6SDnBVEHOki54mKiJEUf8VQ0IlxihpsB6MJFkACNTuSi6unX
+tZUlzhisGk+z5jBGryATQITfIdzfCeWgf4ESbh6EWFyhEduqtgTg/B4MES7zMGIa
++e7f/qPT1oNureiNmImxaWO4cvRa5iJec2SV71aSkgvhk6XXTEFH5zHtCWizxW7B
+GwE5u/GPv7r0AuLl5Z631pqylHabSNgnGA6fMJj1mj4j5jtKSO6lJuiAlDfkSrr/
+n0K5Mt16nWMRqCWZsR+G5XyxMeMSEQzr9h0CSx00y3Qdfy9AwIHiBNSO6pb4IjWO
+q7aZMzbvtYMRiG0GD3ZNv9uo32w8keK6c6BzRQIDAQABAoIBAQDUbdzVJV6Wp4pq
+VUI2Fp7iwr22ycQlr71voQbODxK0XvZtZKPgnIWUZTr9xr7A9CCUl3+zfN/t9Vtv
+o0Q6qxxmJ3ylH9LNeQL3VT7FvYN1bPjAj8TRFfAaEqKHh8AkzBGqe12kEPAUH8Fs
+jsjOEUvmiVaJqjXk2mty2tFwRDggJwCrN5bXkhkzwhDcMfH2Wgc4c4XkyUrciJQU
+ua4d0L354B3UmRYtrzwPr6WHLXCGPGhyWvXYpDjjdUGMVf2YcBSQdABF+mhCEb2b
+NP4dYUqKHjKn6p4B1/qfJtf0c9Lz229nz0WTzanmpXaNxQVce0sTbktp5A3itT+m
+NlQfDNoBAoGBAPvqSK7NqCrvFYEo+Cvl6fOhq9li2zAeaYO7D+AKiWSJzG9KK/Ts
+F+28nnWkBEdzAnmgWZ7UZlUwHqF6DNIGn+RLHDJ2MVRrZug2irCR8g2mxcHk2dss
+DcmUtsatjCbjLqVCcyuuQylP2GWK60JmRbdKEOfpHLntzGStpOhn5FPBAoGBAOzo
+okk2FWZlymJTkN2HYTqvUCYINDciTDm/ms7YGC6YKdDJ8PUVq6qJ2GO/M+zGPQtV
+A+qFWqx1kk3K5uLPnZLCPLORXPIm0X1ZGreG+rHsrJTnP6uh9OxrTyLNkvt6xcm7
+yA51QOWTuRbYhPwy05IqT3Z88HkHByMKr4xafPCFAoGADff1w8ufkZHkTV8qM7Tx
+/hJu5wT2RnrJOwa6YJ/08mA5t8oTGeelhAc7eiZ4HkYgUwIzNf1tFzgt2qJb56F6
+aDxJ+fpXzeiOsj2j/xp4o40l1hSMh/yvXwgiAm5JITbjtUI0BK4LB1VoGGlVlj75
+iqpOua1RbHXlKYf/Zuur24ECgYEAqXDFSWmGKsOY2XR9QwQltUxYHat2dQxxykfR
+GCmUOhcYqT0VuqSyL/oBK25AXBN465b1gxG3xWsdpcf+FLB7OdD0i1XnTUYYRPeq
+1SKUQRdOY/11G3Ntcn5ZjkHL41NvDRbiQfz42noqQj2/94T+rybVyKAZeeZd42Es
+J0082OUCgYEAnguGJxhfSryD3a2kAQ/6s+L303rgXkRt+/luoopdm7vu2AcnaP7L
+aK4dCDusp/DZyGn8/ebDCGNIaVEMJVHAPLFbhJA9E9HCjfC33RdklCO/aGDtXsiq
+kzg3mqPHTCPCpmpr5YAtuLONczP1qgB04/vqb2S5eANC+5k6mEifu2U=
-----END RSA PRIVATE KEY-----
diff --git a/mysql-test/std_data/server8k-cert.pem b/mysql-test/std_data/server8k-cert.pem
index 5caeb95bb4b..dfae47b05d2 100644
--- a/mysql-test/std_data/server8k-cert.pem
+++ b/mysql-test/std_data/server8k-cert.pem
@@ -1,86 +1,86 @@
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 2 (0x2)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=SE, ST=Uppsala, L=Uppsala, O=MySQL AB
+ Serial Number: 10754692786786449447 (0x9540581bd8dcb827)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=SE, ST=Stockholm, L=Stockholm, O=Oracle, OU=MySQL, CN=CA
Validity
- Not Before: Jan 29 13:33:49 2015 GMT
- Not After : Jan 24 13:33:49 2035 GMT
- Subject: C=SE, ST=Uppsala, O=MySQL AB, CN=server
+ Not Before: Dec 5 04:50:48 2014 GMT
+ Not After : Dec 1 04:50:48 2029 GMT
+ Subject: C=SE, ST=Stockholm, L=Stockholm, O=Oracle, OU=MySQL, CN=Server
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (8192 bit)
Modulus:
- 00:bd:48:03:11:06:b5:8b:92:f6:9f:2b:27:e0:3d:
- 6c:8b:87:cc:7b:cf:e5:7b:e9:5f:eb:8d:4c:95:36:
- 68:a6:1d:dc:81:10:83:c0:bb:97:c9:ac:4b:d1:c2:
- a1:64:2a:09:e2:1e:5f:26:14:42:6b:b8:8c:82:ea:
- 6a:d8:df:9b:dd:46:9a:23:52:66:03:51:25:90:2f:
- 96:d4:c2:ec:1f:6c:a7:de:3a:eb:49:7c:da:81:ae:
- 42:48:30:59:82:43:d6:ab:00:a1:22:80:e5:1c:f4:
- 74:3c:59:42:e4:a2:6b:5d:13:69:1e:74:a3:f9:a2:
- 71:eb:a6:b6:7b:ba:12:49:a8:4b:47:40:ed:f0:2e:
- 94:80:23:73:5c:51:7a:2a:5c:96:bc:a1:20:7b:bb:
- 38:b6:41:11:53:92:c4:1c:95:cf:d4:b2:62:ce:65:
- bc:dd:4a:34:76:71:8f:e3:3e:fb:4c:0c:8f:dd:51:
- 69:a3:e0:4c:c5:23:fa:c2:fd:5a:24:5d:cb:b1:fe:
- f1:21:3f:c4:16:f1:d1:53:09:0c:72:bb:9b:01:b6:
- c0:13:34:8e:bf:39:30:db:c5:f0:fc:6d:38:92:c3:
- a8:8c:91:59:cb:b1:ce:4f:2e:7b:2f:6c:65:69:d9:
- 8c:35:f9:b8:ae:1b:9d:2f:ee:b0:26:23:43:9b:d8:
- ab:08:90:6a:d0:1d:cb:09:73:64:a4:55:95:f4:6f:
- 0d:17:c5:ef:53:ea:6f:a0:13:3d:c1:cb:60:d0:1c:
- aa:02:a3:22:4b:05:0a:26:86:ae:ed:73:0e:b7:6c:
- b4:3b:ee:f1:34:01:60:9d:82:3d:e3:78:b0:ca:af:
- ed:8e:f2:56:ac:de:1c:9b:f7:2c:55:cc:58:94:11:
- 92:55:a9:38:75:61:71:c4:da:95:7a:d4:7f:03:2d:
- 9d:29:76:e3:f7:c9:69:56:54:a0:b9:db:b9:ea:46:
- e0:1a:55:a2:0f:cd:80:0f:4d:cf:7a:51:9c:f2:d5:
- e4:6d:9a:59:95:e1:7e:00:2e:2e:e5:30:14:6c:8e:
- 21:52:3b:f8:01:7c:9b:c8:ba:77:fd:41:1e:d4:b9:
- a3:58:e1:4e:6d:a6:45:7e:cf:4f:3b:bb:a3:dd:a6:
- 99:e8:d6:45:e3:28:d7:5b:b1:25:34:cb:15:3c:31:
- 16:91:3b:01:76:32:b4:dd:c0:07:e9:d9:d9:87:f6:
- c9:c2:6a:30:05:47:ba:d9:1b:98:b5:2b:50:9f:71:
- ee:41:76:d6:0a:f5:30:de:0d:c6:d2:e1:ec:f7:7c:
- 3e:97:13:5b:fb:2f:cf:82:7a:28:c0:98:e3:20:96:
- 2c:f0:a7:30:19:ee:3d:66:c6:1e:f9:e8:f1:aa:11:
- aa:fa:38:7f:89:c6:74:fa:7c:22:8e:37:5c:49:20:
- 98:ae:cd:bc:21:d5:76:7b:66:f8:cf:07:3f:bc:07:
- bf:75:ec:96:90:7f:62:10:31:eb:fe:60:c5:bf:78:
- d5:51:f5:87:70:d5:ce:a9:17:4d:f5:b4:69:7e:08:
- 98:19:cf:31:dd:f4:cd:b9:17:2d:46:d2:23:08:e4:
- d1:75:c8:c5:a1:c4:5c:d8:26:bc:d8:bc:10:71:e1:
- 5d:b7:2a:a3:c8:17:1c:7e:55:3c:d5:92:72:50:99:
- a7:6c:a0:0d:5a:46:89:1c:71:e8:2c:05:b8:60:3d:
- 03:74:05:2d:f4:20:4f:11:a7:04:82:ba:32:b8:5f:
- de:ee:b6:bb:b2:7a:c2:64:ff:cc:5a:08:1c:c4:d8:
- ac:e4:37:be:d4:1d:f2:7b:4a:db:5a:0d:07:25:88:
- e2:74:91:ec:30:3a:97:b4:87:68:de:d7:53:6a:b8:
- cd:54:cd:b0:de:55:95:f6:76:41:3f:3c:37:27:0a:
- d0:bb:54:42:cf:5a:9f:3f:bc:9f:2b:45:f7:64:1e:
- d5:f8:98:75:8b:e9:b1:9d:32:00:bf:6a:f1:78:eb:
- f3:db:0b:12:16:62:4b:b3:b3:a9:c4:e2:48:72:cb:
- c4:a7:f5:26:23:27:32:63:3d:b7:40:70:d0:14:e6:
- 93:56:e4:8b:c6:21:40:35:4b:2d:59:e2:21:97:df:
- cb:14:cb:eb:a5:27:a8:56:83:9c:94:ce:76:a6:2b:
- 25:5d:51:de:0b:40:86:29:ae:2c:e6:74:a7:7d:b8:
- d7:13:1a:df:fc:d3:de:f8:38:24:d6:69:5e:69:61:
- 6f:ad:ea:d7:94:61:22:30:6c:08:4a:3f:71:6f:c9:
- c0:d1:08:ca:06:ef:e4:12:a2:75:dd:a6:15:a2:56:
- 14:82:e2:5e:b8:fe:87:09:70:c1:12:7d:84:29:5d:
- cf:b1:a4:45:7a:c6:a6:d3:91:c9:83:ec:0b:d9:95:
- 25:5c:a7:fb:c4:75:2f:f7:13:31:1d:b5:48:20:2c:
- fb:eb:95:02:80:2e:81:bb:32:92:28:da:71:5b:42:
- 97:c7:66:3d:2c:be:b3:ab:ee:30:68:b0:6b:11:f9:
- 0d:5a:82:0d:5f:d6:3a:2a:99:f3:2a:e4:b5:47:c0:
- 34:ce:94:ac:17:68:68:cd:72:52:f5:83:bd:17:f9:
- 7b:ad:76:0a:98:6e:83:6f:4b:02:b6:af:bd:c2:e7:
- 60:68:e5:e8:a5:90:1c:30:ce:c6:bc:78:e6:0f:77:
- 7d:9c:7e:62:49:8c:54:4b:a5:98:be:31:b7:05:21:
- b1:6a:9c:2a:76:7f:20:f5:f5:1f:2a:40:80:b5:05:
- 57:12:b9:d0:29
+ 00:d8:8f:9d:66:66:9c:12:ca:0a:ad:9e:9f:05:66:
+ 6c:6c:8a:db:19:9f:a2:d0:fa:38:dc:de:c5:a6:94:
+ 60:0d:4b:72:c9:85:e2:ff:27:c8:d4:ce:b1:29:66:
+ 31:e7:2b:4e:08:b3:a2:71:cf:1e:36:7c:8e:4d:08:
+ 6e:fd:7a:ea:c1:0d:5c:97:09:66:fa:ed:0b:36:64:
+ 8f:cc:39:35:a9:43:6c:a9:17:48:0f:2e:0a:4b:d3:
+ 94:bb:b0:5b:43:f1:4e:f7:e5:30:e1:ae:a2:a8:5d:
+ 3c:db:39:df:d6:4b:70:a6:c9:68:c3:f3:9d:19:d7:
+ 2f:2a:38:31:11:ab:f1:60:66:c3:38:4f:d9:6f:b5:
+ 49:df:ce:14:b5:fa:c8:95:04:50:69:90:9d:26:c2:
+ e9:07:69:7b:a2:d8:91:e7:cd:de:c4:ed:9c:e4:c8:
+ 8c:e3:a0:cd:dd:2b:37:21:8f:ee:54:38:91:2b:2b:
+ 01:86:90:f0:2e:9a:06:8a:e1:f2:a2:3f:d1:d4:21:
+ 9f:b0:81:eb:d0:e9:d3:e9:a9:28:6e:c2:06:4b:94:
+ 6e:96:70:f5:31:33:dd:97:2f:cc:5d:80:c5:74:ce:
+ c0:3d:b2:6a:81:b7:ce:65:4f:6a:49:3e:c9:5d:00:
+ 3c:06:4a:57:c9:a7:f9:bb:46:50:df:64:dc:13:1f:
+ 22:ad:21:0b:aa:4b:5d:94:60:9f:20:ff:28:aa:56:
+ 5f:f6:cd:23:34:fe:44:a2:d6:80:bd:a9:67:00:d6:
+ a1:82:82:9f:c9:e8:0c:97:26:1e:a9:b1:e2:ee:01:
+ ef:9d:c6:82:fc:72:33:02:40:35:cc:ae:51:23:f4:
+ f8:92:29:d3:2f:5c:1f:03:c6:81:7d:fb:4f:e9:de:
+ ed:68:3c:a1:be:7c:fa:11:96:2b:5a:10:c5:c5:cb:
+ 2e:7a:54:4c:7b:12:b8:07:01:d9:b5:38:0f:a6:43:
+ 70:28:81:8d:d7:95:ad:d6:e8:88:b4:19:62:05:7b:
+ 75:c0:2d:24:72:1c:4d:04:a3:f7:1d:6b:8b:fa:16:
+ a3:5a:6c:51:ba:5c:62:fa:3e:82:7f:4e:10:db:d0:
+ 52:d4:81:df:0e:5b:33:7e:20:77:1d:51:ca:4e:13:
+ ee:cd:72:36:28:b4:31:88:3d:61:0f:1a:80:19:f6:
+ 7d:71:5d:21:1f:dd:0b:d9:73:88:a9:72:4b:8d:a3:
+ d6:f1:4f:5d:01:6e:9e:c2:28:97:80:de:5b:2d:ac:
+ a3:c9:24:db:e9:0f:2b:36:ee:a7:f2:94:c1:41:7a:
+ 70:9f:fd:d0:31:a9:de:55:38:65:89:20:f4:02:f1:
+ 83:73:40:77:db:35:d2:66:ff:26:5f:f4:d2:e6:f9:
+ ba:fc:6a:66:b1:02:24:04:a3:32:4b:21:85:83:b4:
+ 6a:97:3c:25:7f:65:cc:a6:dd:cc:ac:e5:22:09:58:
+ dc:a1:0d:7d:b4:ac:98:98:81:1d:a7:83:d4:3a:e4:
+ 39:a7:04:6a:b6:b7:5d:a8:fe:0e:47:08:1d:95:61:
+ eb:a8:97:53:91:1e:ca:1f:3f:19:5a:01:73:da:33:
+ 32:d7:33:ca:39:1e:00:37:6b:f8:18:47:30:3a:2e:
+ 99:39:d0:d0:49:6d:87:c1:98:59:d0:21:ca:12:6d:
+ 89:33:0f:f2:52:6e:d6:c5:78:dd:15:b6:11:d6:5e:
+ 72:e8:c7:12:00:c3:8d:57:34:e5:d8:6d:a2:e8:47:
+ 79:83:8c:49:17:3b:75:24:0d:de:e1:3b:dd:bc:b7:
+ df:89:a6:31:e6:49:37:80:f8:8f:86:e3:42:f4:2e:
+ dc:de:58:45:c4:41:a9:2d:a6:5d:f0:7d:81:3d:54:
+ f4:8a:a3:5f:18:7c:02:c9:7f:1c:f5:9f:dd:0a:29:
+ 49:40:92:24:b3:b7:65:37:91:9a:a8:00:c4:4e:7f:
+ 7e:f7:97:de:24:2a:d7:3b:f2:a2:63:ec:38:b7:1f:
+ 9e:b5:72:99:bd:b1:c0:41:6a:57:97:e2:fb:11:32:
+ ba:a3:5d:82:48:c5:0a:cc:2c:f5:21:7a:f1:99:56:
+ 1b:54:9d:c7:64:50:62:80:94:50:5a:40:32:61:f3:
+ 2c:f8:09:dc:f0:6d:2b:60:29:c2:86:70:5a:57:12:
+ 7d:09:73:ca:41:6d:22:61:18:1a:48:cb:80:95:be:
+ 08:e8:15:99:de:36:3a:bf:09:67:35:e8:53:d9:40:
+ 1b:27:e5:14:32:09:73:e0:f6:a9:19:ee:81:90:dc:
+ b7:9d:b6:91:51:33:1e:1f:22:e0:bd:df:a8:d1:33:
+ a7:ab:9b:9c:27:7a:3c:ef:aa:9e:4d:f8:a8:97:63:
+ 24:20:c8:36:ab:05:8a:c0:80:9b:64:0c:1f:ec:4f:
+ de:ec:f0:9c:9c:54:db:02:ab:12:aa:ab:58:a3:49:
+ 25:bf:6a:0a:04:7f:2f:1d:41:11:23:4e:e2:83:51:
+ e3:f5:12:95:22:72:13:f4:be:6f:e2:00:29:4f:fe:
+ 9b:ae:b9:e2:7d:72:d3:1b:e8:12:3b:6d:b6:d2:62:
+ a4:91:31:46:e7:16:7f:9d:8d:74:5e:97:51:d1:cb:
+ 82:57:bb:bd:46:e4:9c:c5:bd:08:8b:68:20:f8:5e:
+ d6:aa:ed:6e:4d:ba:a4:29:fd:ac:5c:2f:25:14:d3:
+ 19:63:0c:01:75:6c:87:a5:0b:29:09:7f:13:7f:00:
+ d4:63:72:e2:a0:39:88:80:68:2c:3f:49:b1:9b:94:
+ 77:63:08:05:55
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
@@ -88,60 +88,120 @@ Certificate:
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
- DF:F6:30:35:E7:24:29:DF:22:90:5F:EF:7C:1F:14:E9:5B:1C:98:1D
+ 3E:96:BB:23:C2:FD:41:11:7F:EB:63:9B:39:5F:58:2D:92:A0:F0:9F
X509v3 Authority Key Identifier:
- keyid:D0:25:36:E4:E6:DB:8B:6E:4F:8A:4D:20:48:A4:21:3A:58:7E:EF:C4
+ keyid:60:57:8F:09:CF:83:86:4B:35:32:BF:73:EB:81:4C:DB:36:27:12:8F
- Signature Algorithm: sha1WithRSAEncryption
- 78:18:7b:57:42:67:41:d3:b8:3e:2f:ad:74:e6:c0:de:2e:83:
- ea:fa:07:5c:06:fe:d6:47:46:85:5a:df:67:17:86:f3:da:52:
- 83:98:9a:5f:80:a3:a5:60:ab:07:f0:f0:d8:c5:9d:c5:09:53:
- ad:79:c4:c0:31:35:af:0c:e7:41:8e:b7:aa:ca:36:ee:90:6b:
- 34:a6:19:1c:3b:1a:90:3a:91:10:47:12:a0:31:49:0c:c2:38:
- 68:0e:38:57:24:d6:12:c6:4c:bb:b2:b4:d8:ab:9e:80:93:ad:
- af:84:01:d0:e8:2b:b3:ea:f6:c0:bc:4a:fa:01:b1:ce:fa:ab:
- eb:f1:08:b3:0d:83:fc:08:57:79:02:74:4c:09:56:14:0a:52:
- e0:02:74:76:44:66:2b:12:fe:8d:d4:8c:30:90:41:3b:4a:7b:
- 3f:1c:7c:86:74:97:94:66:43:39:da:7d:20:4a:ba:3a:17:49:
- ac:c7:fa:72:ee:d8:84:09:e6:f4:84:8d:e3:2a:7b:70:36:93:
- 88:f8:60:ef:7f:b8:e8:51:61:16:6f:a0:94:b8:7d:ff:3f:ec:
- 25:fe:42:cf:0e:0d:ab:06:07:88:7a:e2:ba:d5:62:ff:19:19:
- 37:43:ff:92:53:8c:ea:31:6f:a1:14:89:3b:b4:d1:3c:45:e8:
- 9c:ef:bb:2d
+ Signature Algorithm: sha256WithRSAEncryption
+ 19:b8:4d:94:a3:41:1b:78:e8:fa:da:7c:c3:0c:f5:42:6a:2e:
+ 04:8c:f4:6e:90:e0:d1:55:28:7c:97:85:18:12:c4:ff:d3:ba:
+ 74:f1:7f:af:b0:ab:4d:64:f4:45:58:6e:b1:2e:06:cc:a7:5b:
+ cd:25:8f:60:68:14:e1:f9:56:21:40:43:e4:c4:ee:91:72:01:
+ 7d:86:41:2f:ac:6d:be:c6:1a:2a:ae:dd:13:ca:51:01:37:33:
+ 7e:b9:1a:9a:28:16:8c:bc:d1:e7:d4:46:55:87:1f:05:93:4c:
+ b5:75:ff:ed:ca:29:b2:5d:15:05:4c:02:a9:53:3c:d9:11:01:
+ 04:db:82:ad:01:ad:4e:d4:7d:9e:6a:00:5e:cc:88:83:42:98:
+ 6e:4b:cd:7c:55:c6:4c:98:39:db:d1:e3:aa:f3:27:83:6a:3c:
+ 01:ad:c5:ee:ef:01:aa:b7:4d:f7:a1:86:34:9d:61:20:7c:a0:
+ c0:75:26:24:6f:a3:68:0e:03:4d:cf:f3:bf:d9:40:4f:1a:04:
+ 4d:9c:5e:62:49:37:5b:78:ee:c5:11:78:ee:e5:87:f7:f4:f1:
+ 6d:0d:bd:a2:fb:a2:6c:27:91:d4:84:43:03:f5:9b:11:50:ab:
+ 45:ca:7c:3d:fe:5c:6b:e1:03:20:c8:c9:ac:66:ff:74:6e:0d:
+ 87:47:75:77:41:ca:5e:e9:77:5f:2b:09:bb:a5:7d:fc:cf:ed:
+ 75:dd:b0:ee:b8:da:3e:59:d0:e2:7f:38:16:fe:04:c9:99:d1:
+ 06:84:11:b1:07:8a:4d:59:d6:70:c3:9b:f7:f8:b9:ae:99:86:
+ b6:31:a4:13:de:7e:23:27:33:96:d1:9b:15:65:98:04:e5:f8:
+ 73:3c:f3:72:ef:a1:28:06:1d:7e:88:52:c1:f7:eb:2a:e1:f7:
+ 57:e5:ed:08:e9:ee:f8:95:3d:ec:4c:98:93:e7:e1:ea:a5:02:
+ 37:c1:66:18:ba:01:78:05:6d:c4:6b:2c:61:ee:bf:a9:e1:4d:
+ bf:95:31:f5:28:2a:f8:c9:ce:72:a5:c7:a3:38:2c:f6:69:34:
+ eb:cb:e9:b3:4f:78:de:87:61:8a:34:bd:5a:64:27:f0:42:1a:
+ 22:e9:2b:ac:97:f1:ed:7a:50:3b:3e:18:ae:b7:d9:20:9b:d6:
+ 12:3b:18:b1:47:71:39:0a:31:54:9f:fe:f2:90:d7:b8:27:6b:
+ 49:e5:82:cd:82:99:95:b1:ab:aa:1f:7a:e4:4e:6e:46:91:a7:
+ 16:b8:09:a3:5b:ec:6f:57:ca:b4:4f:69:e7:f5:f3:b9:03:93:
+ 08:90:9d:8d:57:82:77:bc:69:f8:e4:46:d9:4d:d1:25:ea:b8:
+ 60:b0:e2:cd:0c:ff:c2:63:65:20:f4:2c:34:36:34:a3:cf:67:
+ 6a:01:3e:51:5f:4a:49:26:9d:30:3f:03:05:70:22:b1:e3:46:
+ d1:ff:23:23:45:08:4b:0e:77:db:91:d9:a2:5c:15:48:49:ee:
+ 08:48:90:c3:25:44:b7:7b:9f:82:96:7e:8e:91:91:e5:a0:4d:
+ af:04:b8:72:df:07:a0:4b:02:79:0e:38:05:47:61:c3:9e:b4:
+ bf:01:00:10:c3:12:44:64:12:7a:bc:e1:c8:41:e5:cb:0d:7c:
+ 52:32:7f:71:c1:3f:6e:d3:81:d3:12:ec:85:4c:16:72:d2:79:
+ f8:bf:c0:fe:31:14:47:53:20:87:73:bb:34:8f:60:4a:9e:91:
+ 35:6e:20:96:da:bd:4b:7e:bd:c7:c4:f9:25:54:40:2c:9d:b0:
+ 8b:b5:fb:1e:74:59:a5:f7:b9:b7:23:56:3b:eb:2e:0a:eb:f5:
+ 10:9b:88:5b:49:8e:0f:05:61:7b:e5:a9:a0:24:f2:16:3f:cb:
+ 5b:06:d6:a5:bb:94:3a:46:2e:43:c5:02:67:b1:7d:5d:b6:c0:
+ f9:93:2a:d6:18:95:89:73:ff:3b:a1:f3:a6:bd:5b:6a:f0:e0:
+ 11:e8:95:09:83:5d:69:c3:91:e8:88:ea:b2:7c:32:73:a8:b0:
+ a4:24:d8:e5:6f:c7:97:8b:3e:c7:1e:69:6a:2a:b7:db:d1:26:
+ 7b:94:83:27:6d:d2:82:58:dd:a7:c2:74:0d:43:13:e2:c5:96:
+ 9f:3c:00:40:1a:10:b1:da:62:23:2e:b7:5c:33:61:56:3b:8b:
+ b4:b9:01:64:71:67:82:7c:18:2c:e8:d9:cf:e7:da:4b:16:7a:
+ 91:67:af:82:0e:ac:7a:c9:cc:47:9b:84:b9:49:e8:3d:33:a4:
+ 66:3f:c3:c1:20:ba:d1:0e:1e:11:80:82:78:90:25:a4:bc:80:
+ a2:25:8a:5c:de:3c:59:52:2f:b3:50:bb:0b:5a:f1:96:8d:d2:
+ eb:b9:f1:e9:72:a8:ae:f2:15:fd:5a:9c:a3:e8:ca:26:e9:67:
+ 80:13:38:1f:38:9f:85:8a:82:3c:4f:d3:04:ff:3a:13:f7:b5:
+ 13:f7:e3:50:1d:d6:e1:e6:1e:d0:b4:c8:5e:21:d7:22:cc:01:
+ de:db:d1:c4:a2:5c:0b:dc:dc:2f:08:e4:2e:12:c5:4a:bc:a1:
+ b3:92:32:1e:05:5c:7e:ca:43:6e:2e:06:3f:27:fd:1b:75:f0:
+ 01:42:8d:ff:aa:f8:f1:47:5b:56:67:74:66:1b:aa:b5:75:41:
+ 69:ba:91:66:ce:c3:3a:00:7a:93:59:1c:0c:49:c2:d2:d8:8d:
+ 7a:57:a4:7d:ba:61:26:1e:e9:aa:ab:e6:cb:2c:16:0a
-----BEGIN CERTIFICATE-----
-MIIGfTCCBWWgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJTRTEQ
-MA4GA1UECAwHVXBwc2FsYTEQMA4GA1UEBwwHVXBwc2FsYTERMA8GA1UECgwITXlT
-UUwgQUIwHhcNMTUwMTI5MTMzMzQ5WhcNMzUwMTI0MTMzMzQ5WjBDMQswCQYDVQQG
-EwJTRTEQMA4GA1UECAwHVXBwc2FsYTERMA8GA1UECgwITXlTUUwgQUIxDzANBgNV
-BAMMBnNlcnZlcjCCBCIwDQYJKoZIhvcNAQEBBQADggQPADCCBAoCggQBAL1IAxEG
-tYuS9p8rJ+A9bIuHzHvP5XvpX+uNTJU2aKYd3IEQg8C7l8msS9HCoWQqCeIeXyYU
-Qmu4jILqatjfm91GmiNSZgNRJZAvltTC7B9sp94660l82oGuQkgwWYJD1qsAoSKA
-5Rz0dDxZQuSia10TaR50o/miceumtnu6EkmoS0dA7fAulIAjc1xReipclryhIHu7
-OLZBEVOSxByVz9SyYs5lvN1KNHZxj+M++0wMj91RaaPgTMUj+sL9WiRdy7H+8SE/
-xBbx0VMJDHK7mwG2wBM0jr85MNvF8PxtOJLDqIyRWcuxzk8uey9sZWnZjDX5uK4b
-nS/usCYjQ5vYqwiQatAdywlzZKRVlfRvDRfF71Pqb6ATPcHLYNAcqgKjIksFCiaG
-ru1zDrdstDvu8TQBYJ2CPeN4sMqv7Y7yVqzeHJv3LFXMWJQRklWpOHVhccTalXrU
-fwMtnSl24/fJaVZUoLnbuepG4BpVog/NgA9Nz3pRnPLV5G2aWZXhfgAuLuUwFGyO
-IVI7+AF8m8i6d/1BHtS5o1jhTm2mRX7PTzu7o92mmejWReMo11uxJTTLFTwxFpE7
-AXYytN3AB+nZ2Yf2ycJqMAVHutkbmLUrUJ9x7kF21gr1MN4NxtLh7Pd8PpcTW/sv
-z4J6KMCY4yCWLPCnMBnuPWbGHvno8aoRqvo4f4nGdPp8Io43XEkgmK7NvCHVdntm
-+M8HP7wHv3XslpB/YhAx6/5gxb941VH1h3DVzqkXTfW0aX4ImBnPMd30zbkXLUbS
-Iwjk0XXIxaHEXNgmvNi8EHHhXbcqo8gXHH5VPNWSclCZp2ygDVpGiRxx6CwFuGA9
-A3QFLfQgTxGnBIK6Mrhf3u62u7J6wmT/zFoIHMTYrOQ3vtQd8ntK21oNByWI4nSR
-7DA6l7SHaN7XU2q4zVTNsN5VlfZ2QT88NycK0LtUQs9anz+8nytF92Qe1fiYdYvp
-sZ0yAL9q8Xjr89sLEhZiS7OzqcTiSHLLxKf1JiMnMmM9t0Bw0BTmk1bki8YhQDVL
-LVniIZffyxTL66UnqFaDnJTOdqYrJV1R3gtAhimuLOZ0p3241xMa3/zT3vg4JNZp
-Xmlhb63q15RhIjBsCEo/cW/JwNEIygbv5BKidd2mFaJWFILiXrj+hwlwwRJ9hCld
-z7GkRXrGptORyYPsC9mVJVyn+8R1L/cTMR21SCAs++uVAoAugbsykijacVtCl8dm
-PSy+s6vuMGiwaxH5DVqCDV/WOiqZ8yrktUfANM6UrBdoaM1yUvWDvRf5e612Cphu
-g29LAravvcLnYGjl6KWQHDDOxrx45g93fZx+YkmMVEulmL4xtwUhsWqcKnZ/IPX1
-HypAgLUFVxK50CkCAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYd
-T3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFN/2MDXnJCnf
-IpBf73wfFOlbHJgdMB8GA1UdIwQYMBaAFNAlNuTm24tuT4pNIEikITpYfu/EMA0G
-CSqGSIb3DQEBBQUAA4IBAQB4GHtXQmdB07g+L6105sDeLoPq+gdcBv7WR0aFWt9n
-F4bz2lKDmJpfgKOlYKsH8PDYxZ3FCVOtecTAMTWvDOdBjreqyjbukGs0phkcOxqQ
-OpEQRxKgMUkMwjhoDjhXJNYSxky7srTYq56Ak62vhAHQ6Cuz6vbAvEr6AbHO+qvr
-8QizDYP8CFd5AnRMCVYUClLgAnR2RGYrEv6N1IwwkEE7Sns/HHyGdJeUZkM52n0g
-Sro6F0msx/py7tiECeb0hI3jKntwNpOI+GDvf7joUWEWb6CUuH3/P+wl/kLPDg2r
-BgeIeuK61WL/GRk3Q/+SU4zqMW+hFIk7tNE8Reic77st
+MIIJyDCCBbCgAwIBAgIJAJVAWBvY3LgnMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNV
+BAYTAlNFMRIwEAYDVQQIDAlTdG9ja2hvbG0xEjAQBgNVBAcMCVN0b2NraG9sbTEP
+MA0GA1UECgwGT3JhY2xlMQ4wDAYDVQQLDAVNeVNRTDELMAkGA1UEAwwCQ0EwHhcN
+MTQxMjA1MDQ1MDQ4WhcNMjkxMjAxMDQ1MDQ4WjBnMQswCQYDVQQGEwJTRTESMBAG
+A1UECAwJU3RvY2tob2xtMRIwEAYDVQQHDAlTdG9ja2hvbG0xDzANBgNVBAoMBk9y
+YWNsZTEOMAwGA1UECwwFTXlTUUwxDzANBgNVBAMMBlNlcnZlcjCCBCIwDQYJKoZI
+hvcNAQEBBQADggQPADCCBAoCggQBANiPnWZmnBLKCq2enwVmbGyK2xmfotD6ONze
+xaaUYA1LcsmF4v8nyNTOsSlmMecrTgizonHPHjZ8jk0Ibv166sENXJcJZvrtCzZk
+j8w5NalDbKkXSA8uCkvTlLuwW0PxTvflMOGuoqhdPNs539ZLcKbJaMPznRnXLyo4
+MRGr8WBmwzhP2W+1Sd/OFLX6yJUEUGmQnSbC6Qdpe6LYkefN3sTtnOTIjOOgzd0r
+NyGP7lQ4kSsrAYaQ8C6aBorh8qI/0dQhn7CB69Dp0+mpKG7CBkuUbpZw9TEz3Zcv
+zF2AxXTOwD2yaoG3zmVPakk+yV0APAZKV8mn+btGUN9k3BMfIq0hC6pLXZRgnyD/
+KKpWX/bNIzT+RKLWgL2pZwDWoYKCn8noDJcmHqmx4u4B753GgvxyMwJANcyuUSP0
++JIp0y9cHwPGgX37T+ne7Wg8ob58+hGWK1oQxcXLLnpUTHsSuAcB2bU4D6ZDcCiB
+jdeVrdboiLQZYgV7dcAtJHIcTQSj9x1ri/oWo1psUbpcYvo+gn9OENvQUtSB3w5b
+M34gdx1Ryk4T7s1yNii0MYg9YQ8agBn2fXFdIR/dC9lziKlyS42j1vFPXQFunsIo
+l4DeWy2so8kk2+kPKzbup/KUwUF6cJ/90DGp3lU4ZYkg9ALxg3NAd9s10mb/Jl/0
+0ub5uvxqZrECJASjMkshhYO0apc8JX9lzKbdzKzlIglY3KENfbSsmJiBHaeD1Drk
+OacEara3Xaj+DkcIHZVh66iXU5Eeyh8/GVoBc9ozMtczyjkeADdr+BhHMDoumTnQ
+0Elth8GYWdAhyhJtiTMP8lJu1sV43RW2EdZecujHEgDDjVc05dhtouhHeYOMSRc7
+dSQN3uE73by334mmMeZJN4D4j4bjQvQu3N5YRcRBqS2mXfB9gT1U9IqjXxh8Asl/
+HPWf3QopSUCSJLO3ZTeRmqgAxE5/fveX3iQq1zvyomPsOLcfnrVymb2xwEFqV5fi
++xEyuqNdgkjFCsws9SF68ZlWG1Sdx2RQYoCUUFpAMmHzLPgJ3PBtK2ApwoZwWlcS
+fQlzykFtImEYGkjLgJW+COgVmd42Or8JZzXoU9lAGyflFDIJc+D2qRnugZDct522
+kVEzHh8i4L3fqNEzp6ubnCd6PO+qnk34qJdjJCDINqsFisCAm2QMH+xP3uzwnJxU
+2wKrEqqrWKNJJb9qCgR/Lx1BESNO4oNR4/USlSJyE/S+b+IAKU/+m6654n1y0xvo
+EjttttJipJExRucWf52NdF6XUdHLgle7vUbknMW9CItoIPhe1qrtbk26pCn9rFwv
+JRTTGWMMAXVsh6ULKQl/E38A1GNy4qA5iIBoLD9JsZuUd2MIBVUCAwEAAaN7MHkw
+CQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2Vy
+dGlmaWNhdGUwHQYDVR0OBBYEFD6WuyPC/UERf+tjmzlfWC2SoPCfMB8GA1UdIwQY
+MBaAFGBXjwnPg4ZLNTK/c+uBTNs2JxKPMA0GCSqGSIb3DQEBCwUAA4IEAQAZuE2U
+o0EbeOj62nzDDPVCai4EjPRukODRVSh8l4UYEsT/07p08X+vsKtNZPRFWG6xLgbM
+p1vNJY9gaBTh+VYhQEPkxO6RcgF9hkEvrG2+xhoqrt0TylEBNzN+uRqaKBaMvNHn
+1EZVhx8Fk0y1df/tyimyXRUFTAKpUzzZEQEE24KtAa1O1H2eagBezIiDQphuS818
+VcZMmDnb0eOq8yeDajwBrcXu7wGqt033oYY0nWEgfKDAdSYkb6NoDgNNz/O/2UBP
+GgRNnF5iSTdbeO7FEXju5Yf39PFtDb2i+6JsJ5HUhEMD9ZsRUKtFynw9/lxr4QMg
+yMmsZv90bg2HR3V3Qcpe6XdfKwm7pX38z+113bDuuNo+WdDifzgW/gTJmdEGhBGx
+B4pNWdZww5v3+LmumYa2MaQT3n4jJzOW0ZsVZZgE5fhzPPNy76EoBh1+iFLB9+sq
+4fdX5e0I6e74lT3sTJiT5+HqpQI3wWYYugF4BW3Eayxh7r+p4U2/lTH1KCr4yc5y
+pcejOCz2aTTry+mzT3jeh2GKNL1aZCfwQhoi6Susl/HtelA7Phiut9kgm9YSOxix
+R3E5CjFUn/7ykNe4J2tJ5YLNgpmVsauqH3rkTm5GkacWuAmjW+xvV8q0T2nn9fO5
+A5MIkJ2NV4J3vGn45EbZTdEl6rhgsOLNDP/CY2Ug9Cw0NjSjz2dqAT5RX0pJJp0w
+PwMFcCKx40bR/yMjRQhLDnfbkdmiXBVISe4ISJDDJUS3e5+Cln6OkZHloE2vBLhy
+3wegSwJ5DjgFR2HDnrS/AQAQwxJEZBJ6vOHIQeXLDXxSMn9xwT9u04HTEuyFTBZy
+0nn4v8D+MRRHUyCHc7s0j2BKnpE1biCW2r1Lfr3HxPklVEAsnbCLtfsedFml97m3
+I1Y76y4K6/UQm4hbSY4PBWF75amgJPIWP8tbBtalu5Q6Ri5DxQJnsX1dtsD5kyrW
+GJWJc/87ofOmvVtq8OAR6JUJg11pw5HoiOqyfDJzqLCkJNjlb8eXiz7HHmlqKrfb
+0SZ7lIMnbdKCWN2nwnQNQxPixZafPABAGhCx2mIjLrdcM2FWO4u0uQFkcWeCfBgs
+6NnP59pLFnqRZ6+CDqx6ycxHm4S5Seg9M6RmP8PBILrRDh4RgIJ4kCWkvICiJYpc
+3jxZUi+zULsLWvGWjdLrufHpcqiu8hX9Wpyj6Mom6WeAEzgfOJ+FioI8T9ME/zoT
+97UT9+NQHdbh5h7QtMheIdcizAHe29HEolwL3NwvCOQuEsVKvKGzkjIeBVx+ykNu
+LgY/J/0bdfABQo3/qvjxR1tWZ3RmG6q1dUFpupFmzsM6AHqTWRwMScLS2I16V6R9
+umEmHumqq+bLLBYK
-----END CERTIFICATE-----
diff --git a/mysql-test/std_data/server8k-key.pem b/mysql-test/std_data/server8k-key.pem
index 9d61d3e5dcd..9b3f7ed2aa3 100644
--- a/mysql-test/std_data/server8k-key.pem
+++ b/mysql-test/std_data/server8k-key.pem
@@ -1,99 +1,99 @@
-----BEGIN RSA PRIVATE KEY-----
-MIISJwIBAAKCBAEAvUgDEQa1i5L2nysn4D1si4fMe8/le+lf641MlTZoph3cgRCD
-wLuXyaxL0cKhZCoJ4h5fJhRCa7iMgupq2N+b3UaaI1JmA1ElkC+W1MLsH2yn3jrr
-SXzaga5CSDBZgkPWqwChIoDlHPR0PFlC5KJrXRNpHnSj+aJx66a2e7oSSahLR0Dt
-8C6UgCNzXFF6KlyWvKEge7s4tkERU5LEHJXP1LJizmW83Uo0dnGP4z77TAyP3VFp
-o+BMxSP6wv1aJF3Lsf7xIT/EFvHRUwkMcrubAbbAEzSOvzkw28Xw/G04ksOojJFZ
-y7HOTy57L2xladmMNfm4rhudL+6wJiNDm9irCJBq0B3LCXNkpFWV9G8NF8XvU+pv
-oBM9wctg0ByqAqMiSwUKJoau7XMOt2y0O+7xNAFgnYI943iwyq/tjvJWrN4cm/cs
-VcxYlBGSVak4dWFxxNqVetR/Ay2dKXbj98lpVlSgudu56kbgGlWiD82AD03PelGc
-8tXkbZpZleF+AC4u5TAUbI4hUjv4AXybyLp3/UEe1LmjWOFObaZFfs9PO7uj3aaZ
-6NZF4yjXW7ElNMsVPDEWkTsBdjK03cAH6dnZh/bJwmowBUe62RuYtStQn3HuQXbW
-CvUw3g3G0uHs93w+lxNb+y/PgnoowJjjIJYs8KcwGe49ZsYe+ejxqhGq+jh/icZ0
-+nwijjdcSSCYrs28IdV2e2b4zwc/vAe/deyWkH9iEDHr/mDFv3jVUfWHcNXOqRdN
-9bRpfgiYGc8x3fTNuRctRtIjCOTRdcjFocRc2Ca82LwQceFdtyqjyBccflU81ZJy
-UJmnbKANWkaJHHHoLAW4YD0DdAUt9CBPEacEgroyuF/e7ra7snrCZP/MWggcxNis
-5De+1B3ye0rbWg0HJYjidJHsMDqXtIdo3tdTarjNVM2w3lWV9nZBPzw3JwrQu1RC
-z1qfP7yfK0X3ZB7V+Jh1i+mxnTIAv2rxeOvz2wsSFmJLs7OpxOJIcsvEp/UmIycy
-Yz23QHDQFOaTVuSLxiFANUstWeIhl9/LFMvrpSeoVoOclM52pislXVHeC0CGKa4s
-5nSnfbjXExrf/NPe+Dgk1mleaWFvrerXlGEiMGwISj9xb8nA0QjKBu/kEqJ13aYV
-olYUguJeuP6HCXDBEn2EKV3PsaRFesam05HJg+wL2ZUlXKf7xHUv9xMxHbVIICz7
-65UCgC6BuzKSKNpxW0KXx2Y9LL6zq+4waLBrEfkNWoINX9Y6KpnzKuS1R8A0zpSs
-F2hozXJS9YO9F/l7rXYKmG6Db0sCtq+9wudgaOXopZAcMM7GvHjmD3d9nH5iSYxU
-S6WYvjG3BSGxapwqdn8g9fUfKkCAtQVXErnQKQIDAQABAoIEAErwZt5n1JrE/cV4
-1ZnPV9lKU6g1YDsV47cjw01UNEyIiBPFURSOcQMUpxQORc2dYzpWIf+2h7GUaHUw
-kEr7BP+vgzk211K63u9eGA52efvbDf9LPnpi5zPupSllkxqi9yvO3P0HIS68jgSS
-poxUzcMU+0pmjcE5EndlEtybh8AH1H4Kc+ni10KARp0nWQHKlJdsB6tVLZfi3RRE
-iEZ0/crNMZdb6lGGnozCW2ByQBYU5ySNphCOrnZiz1ZB7l11kT8Qm7E5SM54wRJq
-A7atFiqwiw1PgrCs2O46STX3nC1nL6UvquidpfvtgDH/bYth6UQ5cWflYO9oRe9j
-iNH8D4MdglyRXyCHwjHZ/LvA9+MQp7eGmtk6pPnEJrlej+TpZ5tiDGnCayFxq0Lt
-09HiwTaA0RqrRQt5bi1hR+GPisd4TMVnL/NsKym8Zz5o+ARpJxz0Gbh+xyaf+ZhA
-DPO+l2jpqpTLLKlXlER44Of2yZvFh75673OpQX4vXQadN0ClCEYPKhbskr63JXKZ
-PihTw0vOa4F3WffHhECfUuZo94rDuJX57vejVhogwlr4IK3tNaQWH0Qyo1qDqt4c
-uEVazegpyimh1w9QHeb1KRmZY5stBVJ/1TCTcNyJgc1eS26Uj0dLD+C8RiD3cokG
-Pu5Y5sQEvWOW0lKNYBg7pOpbgmD8LHIvQQeM/Jut5B3hT8kmBbvbjts5tsrgSlM3
-0LB1tUHRqGlFYOC3l4/vQPt+OnNeajh0iF8MiCMyWLWssZbKJYR5T2zWQZFd0cNw
-I1Dssspmx98dF//tA9cgv9joVeWM2mDZIFsYuo3BnMAzFMlXgMogE4vhGbxuAq9T
-iqar7zueu0sEkbgzJUFLzQEkh6cXM5jixtG0ryxzogk6sSkFqEnowYxBMzGh44yy
-ownBTwULKfs1UCRrW7O5DnoUNQ5kK1v8Nm+mEanadKe5qiqrBu6q7lYwPeSG2t/6
-LSlQ5KRVPxWrf30zzwqzLJy08/P42wPM1zZFOyqFtdamV1k2nhvSefiq/b+aIXK4
-fN0gtBcO6fStqNvRBeMHO0DjHz49/HZGjqa1ZWjCA8oGuTMXfrmlgrf+RBlWJgLA
-ST3RAFQ7Nyw2D5ABuSk/2m1yGcuyEgwsqOqr8qDY11nNgmiAxuVF9Atf3zmoB6Mp
-+4GE3EQuATyBhcZ/ZJiMn02roQ/lkrDOkdE1DrRnF7Jjw6y9XpBbhH6dwlWIMmmZ
-EZAhhKo9vtP9SKAGy43IE8JMHFnMVpr1nEMT54WsyU3cNKORUKL6diOl2trGjsSr
-T4tE1jWqry/sfLg8OxqWxGoca6UUjngLfBcnUSbcaDhlGPqCl+kahmummozNcziS
-mogK5N0CggIBAPA1BMon7N+1Q/1saE/SsPsgbUcWzjb5M2mwHURUamQRQ2OnltSr
-/qjKoe++TzF19QnAGCJMsKhTUIdWW988xEUUnwSlPGZ6h+vx779Nc9870r1B8WgA
-ejwx7oH14EVNg6WECXZEYvVSvQn1LsXEWfpujlxeDYoaOMHZSq7MFzyrzJxKgUIB
-e35mCPzXPvh3XUz6MR9RtfRZk/XaSIV1LRR56H4xDTXOp8nejmvTALLbX9RaSV1K
-64KbEPdWe4FZ7WK+qLBglO/JR0OE5f7y86MqUztjNfnUKubABfo9lBS574u26rbW
-Y+kFHux9WjkVPIkQsO5kGjs+dWWkyeUKoNEyE5otxJ7p8nXaUU9ZSd7c1VvK8Cof
-+uIsFpwCpyAJdo+zfgCNf0WzFwAM5UIB8PsbmMQnbTdDr+VYhxaEh9e0oLCApjCz
-+RUm5I6ElXKpzejkMn5FGlknQ3aEghmOfTo1WmZ2B31ZnJrRLuYRKRZXqieIvHm8
-NGiyJx4oi6jQzf4QxKjbH0brW2lSkxArE8sgKrJImSLI7TxPVlQ8JmuLR4MU2xHp
-48PC0AxnBB/0l+2EWG37yPmPVCNQ5oEKjzqp8fgnCzuLKe2wG2QE2IkLUEJUtZjD
-fHkCArilVmZDvAUDpYDu9AbgDhsRlyV6fKAo+S05EiuwjbKExhn4Iry3AoICAQDJ
-udlnRSVxoHEPFfg2IQzAg2v3e6OAWNc/c+Unc88eEZJXUHIGt0fqWN2OrVvx3HEg
-ZrwhiByThLHPqmfqLjr/s9KuxYBSoC/5YhYb9KGYHEcwdSrxFo3bvCULmIjDGqbU
-1m3AbHVPe6Zj0dw13hgf7HDcW/ZK/mtvjgBMQiRjI5RWlkh9kGkxKKOiAZFsGx0T
-dB+ocXhC5SVbISARkCesMKmuYQfo285JNSudaJ4JWJkLOj1+Ovfczj3KxWo4nLV2
-HYJlWugL6RBVETu2iDlrcO1RlxcH6942N4DbN3SVNYMWQ2vjbro8tC2RBU2L60/u
-v5tDlMag8IotVSVQWInda/Dwk9WKpxHyHjUHreqj22wrECmizmTD2CTfTtLgfGoa
-4qXZUfuMGLgxBiAdxQyRJsjzVKtY6CAlzBuF9kNfIaGJGtDAumG2f3/YC17rfyYq
-vlNtJKbRPkif5g97de1x/H5gNzXlKx2+lJ7wWW2lH3fRF14tji/1xjHGSZeO0Rrs
-bPJvqLAQHu9AsBmA5qsyydFkwks21NxUXjnr98iIVYusNvNPvsQQzAOLcHWTxtel
-uhjPh6Wa2w68WW2f+u0Wp6t8ksFt/QmYVWZ67UOpGQFU36k+qXJvSQpRwNNlkkcP
-aZQbA7SstkspiMFmPitqQptbUnBr5iYA8z7h6di6HwKCAgATPgwOLbiaCylRKdgJ
-XPV0iJp4cWk/miL2Ond9u81yCrf9SbWZf9W8q87hJ7usWKiyiULlrIMSWOpAjTh6
-36FRb191vc7i3rn4ur7b8lZv8ZjmNFwkWrVwEQfsPUgkBRugrL0dTkknIeOm4o9G
-pH4Yw7Z/y8EF6SfWz5NeAVdzMsgHVSiZowjDjWT27D9NJDLDMd+xhJgw5OQnc78P
-gd2EoGdxhHhscQub7ko2dQa/TTeWCU2LPa80HTv0tGbca9nKaT+WMYZ81wDwdbr+
-+3NtBLz6Ku5t/wMYzRUtgLVWG7cG2DZhQzdpuVFK3JfXrs3UpROnZTl8uXoqFFNg
-F8PePka3uSbhHBiiPET7OEnkoogs/ErU9Q7iA2okQUomFNv8kwJrBOrHKJuVE3Ni
-IEmvs/w+6nGjVbbHhpn7wc4oB34/5W5qxGAVw7HXgON/9f5aw70PxHVh4vVSjzbk
-2TdK7G87egULk5wqAsvg/kruUUN+O0Pt9Je2M19S2Sim82MtESbP6A3PXpdKDqVd
-TDYftYn2Ej7CPJpUlH5z7QWe499srsUF4Fiwm/CSrcX00WFCU7HJzbvB0iuJULfG
-apQivO53VJlfwbwwIEVxc7ns8I0TYznQ7QgRoYmaRRRwyMhNFoexlnLSAizfGj+j
-bvaA1gdwCfxcp54SSPSdq/UMbQKCAgBTyZrwVvsfgAmVv4VSTlXynGO67qLRy5TU
-KTo0MdkEXz4OgD5sZbI8N18HRSBcjDh8wc9Aij18VHBaligFT+B3luRabXRIXXqv
-tbsDL4/zE0PKb9A/RSP08efdMiUUDLzgyJPbifEL64sICQHTagVRNS8HiDb7nUNY
-mX2sLwjYGM4jTNadON9IaN3Wi5owce6YxvHjUAYomu7yNAcS5HJmBexknq7fXHUJ
-WUldXzfNH/ypei5SgQG0uAFYeLkO/KAuiEFCAglB8TM0ci0AOwLGiqg37G7HfoPU
-tycRZq5Iz2o8VBK666H1Vs1aX/5+sGWKABHodyItdNufyq7t+WiCDLSN6ImYxp4g
-l8VlBCrilmAOXu88TUfzRJLEIgRa87JKqntCkdfOr/HJgwbR9qeqnpZ242MsUXYQ
-3P9NnCUNnXVv8jBk7MVrPPgH72kknbJnrJgQTFnxrVITAEbL/AZ9Augm5KfBITCA
-mVCO+kYdgL2Onosilt160zCXcLe/vUDWlMX59PH0MDUmBD8DmEvhk4wissT06GL/
-tAeQ6GFlp0qVZFmZdN4RL/wE7dgYYk3t6yclA+2YLYaoWui6u0nA0DHdU0N+gMx8
-dnRTeLtSwC0aaK/udAkxCgB8RoBHvwM+9pZqxhZEao87mC7kXcxAnZvTyaEiX/zH
-BkHHKg839wKCAgAAvo9BfWg3gf0rRnbXsGbYGeiodCMGiskI/QmboM1uJ27oMrcn
-pHeIuNP7Ag9L88DYewznq6IqHk2PHLU4Gzt+AAiiiEE5SFIJP1J5NR28u//MQC9v
-K+cPDjGjPXJHhE084VFqz3nV+R/M8MdwD/Wm2JWevDnMKBpZxLJuQNzv1UBLVSMb
-kdkYWvS8Be8p4sv2zcrgygawCHJRVlwrm6EZcpSDr0ohNd2KuAHQpi1DGBDDWEBv
-0WylbTmqiNf8LCE+1a5n6CvrdUmEe43FKpLPnvN+lqyCmSxR7pUrjoIzlVCGkAQ8
-y1nAmhStjC/TM4S3M7ip6036AAFqHe9y8Rwt2D8YaTQXxr6seyMmWLYPWMZeF/mm
-fYV2pNmjwLCN5TOnjn2EJABzsxA9Ex814BDcZhb6vam29K1mkEo32khrqP22YXB7
-XT7BNE8vczQ1lnUclfZIeuOgdFLwmrT7R95BX2xfR6yGZUpqqZOePoLvBKIC28Hf
-sp88Jm8QTZfjQiLAu8kuu2+bPkooIdyXZqYO8qrRCza2QjJwM1xuyxABqoz4a6OW
-YfT+WHRUQLJTkSvD95B2B4fKWnK+C8QeTP42SZbDNwzrbUyQgqlNbH2MFEIYE/b4
-ipfcemR7T7zP7DEL8VkqGR33q/qFOtHvijb6H3W0IO06MmDOaenbMpkmyA==
+MIISKQIBAAKCBAEA2I+dZmacEsoKrZ6fBWZsbIrbGZ+i0Po43N7FppRgDUtyyYXi
+/yfI1M6xKWYx5ytOCLOicc8eNnyOTQhu/XrqwQ1clwlm+u0LNmSPzDk1qUNsqRdI
+Dy4KS9OUu7BbQ/FO9+Uw4a6iqF082znf1ktwpslow/OdGdcvKjgxEavxYGbDOE/Z
+b7VJ384UtfrIlQRQaZCdJsLpB2l7otiR583exO2c5MiM46DN3Ss3IY/uVDiRKysB
+hpDwLpoGiuHyoj/R1CGfsIHr0OnT6akobsIGS5RulnD1MTPdly/MXYDFdM7APbJq
+gbfOZU9qST7JXQA8BkpXyaf5u0ZQ32TcEx8irSELqktdlGCfIP8oqlZf9s0jNP5E
+otaAvalnANahgoKfyegMlyYeqbHi7gHvncaC/HIzAkA1zK5RI/T4kinTL1wfA8aB
+fftP6d7taDyhvnz6EZYrWhDFxcsuelRMexK4BwHZtTgPpkNwKIGN15Wt1uiItBli
+BXt1wC0kchxNBKP3HWuL+hajWmxRulxi+j6Cf04Q29BS1IHfDlszfiB3HVHKThPu
+zXI2KLQxiD1hDxqAGfZ9cV0hH90L2XOIqXJLjaPW8U9dAW6ewiiXgN5bLayjySTb
+6Q8rNu6n8pTBQXpwn/3QManeVThliSD0AvGDc0B32zXSZv8mX/TS5vm6/GpmsQIk
+BKMySyGFg7Rqlzwlf2XMpt3MrOUiCVjcoQ19tKyYmIEdp4PUOuQ5pwRqtrddqP4O
+RwgdlWHrqJdTkR7KHz8ZWgFz2jMy1zPKOR4AN2v4GEcwOi6ZOdDQSW2HwZhZ0CHK
+Em2JMw/yUm7WxXjdFbYR1l5y6McSAMONVzTl2G2i6Ed5g4xJFzt1JA3e4TvdvLff
+iaYx5kk3gPiPhuNC9C7c3lhFxEGpLaZd8H2BPVT0iqNfGHwCyX8c9Z/dCilJQJIk
+s7dlN5GaqADETn9+95feJCrXO/KiY+w4tx+etXKZvbHAQWpXl+L7ETK6o12CSMUK
+zCz1IXrxmVYbVJ3HZFBigJRQWkAyYfMs+Anc8G0rYCnChnBaVxJ9CXPKQW0iYRga
+SMuAlb4I6BWZ3jY6vwlnNehT2UAbJ+UUMglz4PapGe6BkNy3nbaRUTMeHyLgvd+o
+0TOnq5ucJ3o876qeTfiol2MkIMg2qwWKwICbZAwf7E/e7PCcnFTbAqsSqqtYo0kl
+v2oKBH8vHUERI07ig1Hj9RKVInIT9L5v4gApT/6brrnifXLTG+gSO2220mKkkTFG
+5xZ/nY10XpdR0cuCV7u9RuScxb0Ii2gg+F7Wqu1uTbqkKf2sXC8lFNMZYwwBdWyH
+pQspCX8TfwDUY3LioDmIgGgsP0mxm5R3YwgFVQIDAQABAoIEAAYjvDClBBO8SqU1
+dAixKK3DGgcV8YW/MlGAt1XLqxV1aCGyfAcD17vAyGEGFrAZGDNC9H4Jgy/ERDyG
+2q6xB2rFuDRH/fVrNwApxbHihVTxJml80Xwsr/oKW5MeotfARZ7djo83ZkEjs4/7
+ig8HQIBaAXBcvb13zkyCH1IC7+rtvucfzGhQWXHQ4+Fs5Lbk0mrLwMjSicy9/tVV
+En3h5kjq+6G41dW2P1/f08ZN0FHu8J6qr3ZjMYwAreLOGRTkfkxnT6GvbUIU/v8G
+3rCVK5yE7sWxGiJ09/lLT53vAqoXGnglUMOwtFdG8xp0fzz1vr3m6ao76uaWTcCn
+mV2palBCOZRwYozMWHaVBVAe9sWGd1MPSl7befbmkJcDfry2e1U8EO9QE1p4QpjA
+0UxFznzdt/h+XYgaAQ7l6Q4rxWL4V6DBxfYOY+ubeFuWLHe8D1LkUQJSq2i6I+0v
+6qMqmrEIKmXq2va5vrpHQgA0rCMFoKqKda72GxaBsSDTEJPrGhxpaiSC88qie4av
+C9dQYl69ldjFhTOlIu/DQih3PylDolqoUgLdFA//W9Ai/VdyRuN1i4TlQQUoPSfD
+EMLNDLtNQ9C/kUFzI2kZwYHTy/31gQc41ks7NNxv068a7IewsvS2O2rNCBKecLJ8
+jq5urm1cDInYcsicvzfFNx15QwXY6QqJ7qIIsvx2yBdhmEgMBX+eImyic9o30kMr
+aYd0bKilOlV/Vi0nYq9ArT3Iwd2RsQHad2ujOTMZyxfHVFIyEgShpQM5XXTN9w8g
+QwVI/0ydYdLWktJdjexvJmtJBFeUiCTz5JqCCGz/7mUfJW9XnljVLEd4J53f1PtY
+fIgEGkiG1ekUejbPA+Zm1eq2oeOsTkBqqEI3e5hL+R8PL7GKWgaJEY1Io6kcbboX
+RPwZeRZo6EjIJPQET3ER5x3Fey0kupercmpKaJ2aN1aZuq2TNUNRFC6n6lPknclJ
+VwZsjKoazHdj6usiVNLxC5aI8MJRCuaLDgq+eLz2Au4A7a4MTtXiRG5CxtcYEOwe
++xp4Sov7+aLtn5ECdBvtQigl0E1Qew/xvQIjULSjRNnyPthX/m5FdVfD0Ni3IcT+
+nPnmDK2NYAY5PLGA7ykEMcqlAnjpRWwvsVMiC6zHCVPLhi6dYTyuK7MAvHqfEphJ
+OMzF5C9SmsMmZXp5/8lCF6/dIH5vjWphxo7M1Y+5S0cL/3qPqIetVWNJBgGgMec6
+SmNg6tpmeFdTbLDpixOWclGLIb5XUPsEGBy6mrM8rPnGHfCq2hWJTlUBPXGakZAd
+gQOURFJSWHa34B2PHaeJSIRWHJBy4aa2mQI8OkBsTLWh/i51gKQlWjeKNiHphsH3
+rGQMYoECggIBAOz+cYvL2uyJIZXQzzUgZAlCSbaQ/DEEiyji7L1hFGLSwy5wEO0S
+rC1oCkRbo2/Ios3QDK49JYCk+QvWzIqyFnasQnTj9XCktFSBcKYRPGJnvutkf1X/
+ysO0hHbACIClfUN+mwbDfgVHHswbjSwgHPOuNxljg1TAcRnxQG8lqj3njku0RwUU
+fFfTTDmMJawhAAxd7dUxgcb0zI7ge6430/TuTnc8J96Gg7ZsRoGMrFAYTVbtvkj/
+mryLK2aMz2P/cxejMOcSVMQVd5tOBLhsRhETtkjgMar1pT9z8I0E/4iEs6gqcIqr
+ll+L6lghBdL+1SwW7MEFekypllMwypzlRD5uws838akoY4Ko03jm0YbA9Zf1Zn2S
+gT/q+uhvhZ7IWy9OuMeBIVGhv4EltC7SWuAfHWf7SUyKcEA2yfktPlDSqeywvts6
+CxKCz9xL8P8XSsKz8jMkC7FS5Zs0rn8G3d2sPFjEY9uWABPw8jcMq/w0regwmwt8
+gkGbKnKWKmUMgGBWoQM2gjTAB0Ss1MsOJ1m260d5Wd8pNLzXjcCrHqNh6xQx8DoN
+nOTCPRQu9cke/wjzW23ez9Ks9fRa4s9zJMtzc+tq2JH7WHmnehuyPYUPa6ALAcsB
+5B5QMXKbTSv/hTGydeYfSBiP1yCG3DyN0miuPS1VREfzaJr6V2Fv/3DFAoICAQDp
+7a1eFQ0F8SdD/9I9x9GPMvbhEi2Yz0BHjLOsOEN98EG8c7aA+pYW5AZBj/6m1nFZ
+EpvGQkmPHb24v4vxK09kcACMpJC9vkFvrt0GLn4OkiGNouqe2ip6CN7VNJkpMpTs
+x3aQ0x6CIEALVukHuDpV6i4TpB9O7bdmrO7hf/2GgsSM8zDGpo6a0Xk/POUVf7l8
+ZY2ZPf/LJVpLEW1YQLljZRJDI62nwgA+dtWnkX92DVT0LuKkisozlyY3+E0sWULE
+tizfJdGOqzfnilZBcG5/dDrvaW/OVVQLUjRk6Hhkoudff+mJfNrdJD0t4X9lZxvf
+NShlos28HJPkrOeThNhy4za6neTpn7AK6M9YYTelPBI4WyhVZkpvy4ZYnCORRs81
++byb0l4C3oDxaKu2McTtMFVQ5z2reLNnvPip92zQcPHbmuO+NhP29Gk2sjPp24N5
+DM4c1KYPTz5k3S85V+m1DLyI+uTmh4lqL8Rdn556pKZncJfOFUp+7isauHJMrd5i
+ICBtaL+M/hTZlSxFLcxykblo3gqmumIOKzegYSNZ7v8JB/r7VeZ3bQXxGThfB9dw
+Tpmef8XKK+ye0Nm//P33C36s5BjukRLUg5xMOHNza74L1zR2ToJgw6nrBJjRNDSt
+7EONSp7l8tQotry7C2fVezfUBMcSTHo11qOL7fdrUQKCAgEA5fttWMo04wGYc/g0
+fEu4iDupqN89vJu6J60/K/A/hj8dZb0ez9ElANNL01ZSXjIHu05AX/26nQJ7JAAI
+cjesEPHNc/2buvo6fR83oBBt1tjyrx/RajVWIWDWgx6Lobv2uT7tVjzz2E9SFaRO
+9Rkcv2S614p4chBmMVSqwLF+aaCBt/l0Sfu9RsUn3VihXk6P63BjUlY+qEH7GFPD
+8ib/K1rvDkp0Lj+/JZIhQaqvtPJAazE/TTuuf3VWYqgWweWtXKzi0fo6BCcI8M9f
+SVDZFc1ZQZM+37aN6+uo7lCBYYvVhEXa/NbSkFoIygkRy9W8LJL6ob2dFzQjSwu4
+M1VRSnzV051oiE1HdA49WcA0aF5sdlCQax93Cf4QCuvecV3hDyGHsyMeoEckvkFG
+f4Fm6sOHF9cFJJ/bmpUQnxxGsswcVjKWo8vJ3ubOq+uOLR3/UL6rNPGv3x6g7mLL
+Sz3wpCN2VHYQqZEA9lkF1GIZrB+6++3fJ+BlzyCyqowLDBB7rAGlMqb86A/Jfd1y
+irJrgWY/IBclHaixIujTCLuGeeqV4/0qMEvxixTrjOCdZ9UKjTcL7K0iZEGwVLa2
+D7afaEfboAMJs3CERVo+5w2rIar7OE42KTjmlHwh4CPRWfcW3ElgnDaTEjLUAx6c
+Lq86FpevioSKRIBzbKGvlkDHVDkCggIAbNL9C/+PB2ygb6nbDJKgkpWK9DmYrLX9
+mUuDamLiQvw6GIlcJbRtjkiWAHoUZVjtchqODTVZMxMK5590YsVbMcZI+ySzkRGp
+L2ORvwZx7iVdJp7btvqXOB5YS6ckeV3mmiBQsB8G2lJWeO/9iHHT8ZP3y3tWdUlx
+QHrCxnTcZG8BMPERh9iEDtHULe8OQ2ofyBcWQGvvS3oc/z8kNyIlHHAwhrtaVeiS
+ZHyz+Dhfq3OYSeBl31YRqt5uESuZ+z+rKAf35/eX/V75quVYKyk6vmA76pSKRtq7
+NmkPpsHfADIooOzIoAVNbAMn0uhMc8f712LLYDzUqOZChudI8/+hEhFRrI83ptd6
+9hhIHT1cvamscDs4EEJ97nQoE6DPiw3954Y+j97VjVAlfCjNePy+N/l8Nx7cOaD1
+FRV8ONW58V4ZpafwutQ9hW0+ZQuRywErsGyclhz3A7hBtnqPNYYIWwmJy8+sHPKA
+or2GBGf1OejO4OAoPt74wQPbWZrk0XcxNUTs0Pkh411wJaiX57benY3dS0PAgL/E
+TgMc5adK4tOkIXds8u+LP5OgaADrkIn9V2m5XVrjkKHOejN+mSoAm6TlUVjroFAt
+CmAPngXE77T3vFppNYBgdtOPgJ2q2egHecGny1sjgKXuvOIF+p3buBySZDe0xHZ/
+g/xOKRKTP4ECggIBAJkMUEiE8iiHdfbB46mGob8sFTFIJitpGLzTXL0BmFBJauI7
+lcz+qKcAd2htF45c3M/IEyFEID4Qywze4qgimFi7pA5Ns9v1gDOZw2lui3vm58o8
+BgStk+MQBYK6/JloxU9FE6UfdZRh0mXf/BY+dAvIbs3ehpgxq7VxULjv7/P+5sOZ
+ObMGlE0widtniFv+Nx/L1xX6BSYnpjA4BZjLZzxhvBqQEPotSf0dj/7NGfRuj/r9
+HX5tpekG9vi3WBpWdiCBC+4MRbpXhIb9nhWJch4gjgOFQ15ySzUeBkbAdKhNWNLv
+RcF1GyaM2zEHE9XpbAoYBXyik5dsEQM1JVYJP09yXQ4VAB3qwHdWI9z/yrUu48qh
+JR+6PqBwVFpy9l7XJlbjPDo2mwiN4v35ngjhxyrYcJAvNe20gilAbTDCrDfFYAV6
+FS4oSDiRASVUcl+zeTcdNKrjVAtBE/qxkx3u9gJ/qowP6dvG+i42Bb4Cndv9sLEn
+EX/23kIIt+SIJizrwGpjHpVeWrCkFBB+1IdvbTl1C3DHRXf78XGUeS90EoL4XupP
+6fv45eHDMCccUoTj3r/eqFTxXrHl4LJ7Dj+H+kX6AJhr2eL78RiJIud0xOifPIOy
+/g2eOU1OXnlz7Y0X7Vw74ECqKGtB1Pg7kh7KbCGDHscC+fD8zhc/Pa3mxRh0
-----END RSA PRIVATE KEY-----
diff --git a/mysql-test/suite/binlog/r/binlog_database.result b/mysql-test/suite/binlog/r/binlog_database.result
index 4f7d2dc7b94..504b3daa206 100644
--- a/mysql-test/suite/binlog/r/binlog_database.result
+++ b/mysql-test/suite/binlog/r/binlog_database.result
@@ -50,10 +50,31 @@ master-bin.000001 # Query # # use `test`; DROP TEMPORARY TABLE `tt1` /* generate
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */
FLUSH STATUS;
+
+# 'DROP TABLE IF EXISTS <deleted tables>' is binlogged
+# when 'DROP DATABASE' fails and at least one table is deleted
+# from the database.
+RESET MASTER;
+CREATE DATABASE testing_1;
+USE testing_1;
+CREATE TABLE t1(c1 INT);
+CREATE TABLE t2(c1 INT);
+# Create a file in the database directory
+SELECT 'hello' INTO OUTFILE 'fake_file.FAKE_FILE';
+
+# 'DROP DATABASE' will fail if there is any other file in the the
+# database directory
+DROP DATABASE testing_1;
+ERROR HY000: Error dropping database (can't rmdir './testing_1', errno: 39 "Directory not empty")
+
+# Remove the fake file.
+# Now we can drop the database.
+DROP DATABASE testing_1;
#
# Bug#11765416 58381: FAILED DROP DATABASE CAN BREAK STATEMENT
# BASED REPLICATION
#
+USE test;
DROP DATABASE IF EXISTS db1;
DROP TABLE IF EXISTS t3;
CREATE DATABASE db1;
@@ -70,7 +91,7 @@ t2
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # GTID #-#-#
-master-bin.000001 # Query # # use `db1`; DROP TABLE `t1`
+master-bin.000001 # Query # # use `db1`; DROP TABLE IF EXISTS `t1`
DROP TABLE t3;
DROP DATABASE db1;
set binlog_format=mixed;
@@ -125,10 +146,31 @@ master-bin.000001 # Query # # use `test`; DROP TEMPORARY TABLE `tt1` /* generate
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */
FLUSH STATUS;
+
+# 'DROP TABLE IF EXISTS <deleted tables>' is binlogged
+# when 'DROP DATABASE' fails and at least one table is deleted
+# from the database.
+RESET MASTER;
+CREATE DATABASE testing_1;
+USE testing_1;
+CREATE TABLE t1(c1 INT);
+CREATE TABLE t2(c1 INT);
+# Create a file in the database directory
+SELECT 'hello' INTO OUTFILE 'fake_file.FAKE_FILE';
+
+# 'DROP DATABASE' will fail if there is any other file in the the
+# database directory
+DROP DATABASE testing_1;
+ERROR HY000: Error dropping database (can't rmdir './testing_1', errno: 39 "Directory not empty")
+
+# Remove the fake file.
+# Now we can drop the database.
+DROP DATABASE testing_1;
#
# Bug#11765416 58381: FAILED DROP DATABASE CAN BREAK STATEMENT
# BASED REPLICATION
#
+USE test;
DROP DATABASE IF EXISTS db1;
DROP TABLE IF EXISTS t3;
CREATE DATABASE db1;
@@ -145,7 +187,7 @@ t2
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # GTID #-#-#
-master-bin.000001 # Query # # use `db1`; DROP TABLE `t1`
+master-bin.000001 # Query # # use `db1`; DROP TABLE IF EXISTS `t1`
DROP TABLE t3;
DROP DATABASE db1;
set binlog_format=row;
@@ -200,10 +242,31 @@ master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt1` /* gen
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */
FLUSH STATUS;
+
+# 'DROP TABLE IF EXISTS <deleted tables>' is binlogged
+# when 'DROP DATABASE' fails and at least one table is deleted
+# from the database.
+RESET MASTER;
+CREATE DATABASE testing_1;
+USE testing_1;
+CREATE TABLE t1(c1 INT);
+CREATE TABLE t2(c1 INT);
+# Create a file in the database directory
+SELECT 'hello' INTO OUTFILE 'fake_file.FAKE_FILE';
+
+# 'DROP DATABASE' will fail if there is any other file in the the
+# database directory
+DROP DATABASE testing_1;
+ERROR HY000: Error dropping database (can't rmdir './testing_1', errno: 39 "Directory not empty")
+
+# Remove the fake file.
+# Now we can drop the database.
+DROP DATABASE testing_1;
#
# Bug#11765416 58381: FAILED DROP DATABASE CAN BREAK STATEMENT
# BASED REPLICATION
#
+USE test;
DROP DATABASE IF EXISTS db1;
DROP TABLE IF EXISTS t3;
CREATE DATABASE db1;
@@ -220,7 +283,7 @@ t2
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # GTID #-#-#
-master-bin.000001 # Query # # use `db1`; DROP TABLE `t1`
+master-bin.000001 # Query # # use `db1`; DROP TABLE IF EXISTS `t1`
DROP TABLE t3;
DROP DATABASE db1;
show databases;
diff --git a/mysql-test/suite/innodb/r/binlog_consistent.result b/mysql-test/suite/innodb/r/binlog_consistent.result
index edfa5947eb8..47f9900c449 100644
--- a/mysql-test/suite/innodb/r/binlog_consistent.result
+++ b/mysql-test/suite/innodb/r/binlog_consistent.result
@@ -104,4 +104,13 @@ master-bin.000001 1757 Gtid 1 1795 BEGIN GTID 0-1-9
master-bin.000001 1795 Query 1 1887 use `test`; INSERT INTO t1 VALUES (3, "")
master-bin.000001 1887 Xid 1 1914 COMMIT /* XID */
master-bin.000001 1914 Rotate 1 1958 master-bin.000002;pos=4
-DROP TABLE t1,t2;
+*** MDEV-7310: last_commit_pos_offset set to wrong value after binlog rotate in group commit ***
+SET @old_size= @@GLOBAL.max_binlog_size;
+SET GLOBAL max_binlog_size=4096;
+CREATE TABLE t3 (a INT PRIMARY KEY, b VARBINARY(8192)) ENGINE=MyISAM;
+INSERT INTO t3 VALUES (10, '');
+INSERT INTO t3 VALUES (11, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
+test_result
+OK
+SET GLOBAL max_binlog_size=@old_size;
+DROP TABLE t1,t2, t3;
diff --git a/mysql-test/suite/innodb/r/innodb-alter-table-disk-full.result b/mysql-test/suite/innodb/r/innodb-alter-table-disk-full.result
index ffeacae7951..a357fe27f37 100644
--- a/mysql-test/suite/innodb/r/innodb-alter-table-disk-full.result
+++ b/mysql-test/suite/innodb/r/innodb-alter-table-disk-full.result
@@ -1,4 +1,5 @@
-create table t1(a int not null primary key, b int) engine=innodb;
+call mtr.add_suppression("InnoDB: Error: row_merge_drop_indexes_dict failed with error code*");
+create table t1(a int, b int) engine=innodb;
create procedure innodb_insert_proc (repeat_count int)
begin
declare current_num int;
@@ -10,41 +11,53 @@ end while;
end//
commit;
set autocommit=0;
-call innodb_insert_proc(10000);
+call innodb_insert_proc(20000);
commit;
set autocommit=1;
+create table t2(a int) engine=innodb;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
set DEBUG_DBUG='+d,ib_os_aio_func_io_failure_28';
alter table t1 add testcol int;
ERROR HY000: The table 't1' is full
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` int(11) NOT NULL,
- `b` int(11) DEFAULT NULL,
- PRIMARY KEY (`a`)
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
-set DEBUG_DBUG='+d,ib_os_aio_func_io_failure_28_2';
+alter table t2 add testcol int;
+ERROR HY000: The table 't2' is full
+alter table t1 add testcol int;
+ERROR HY000: The table 't1' is full
alter table t1 add testcol int;
ERROR HY000: The table 't1' is full
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `a` int(11) NOT NULL,
- `b` int(11) DEFAULT NULL,
- PRIMARY KEY (`a`)
-) ENGINE=InnoDB DEFAULT CHARSET=latin1
-set DEBUG_DBUG=NULL;
alter table t1 add testcol2 int;
+ERROR HY000: The table 't1' is full
+alter table t1 add testcol3 int;
+ERROR HY000: The table 't1' is full
+alter table t1 add testcol int;
+ERROR HY000: The table 't1' is full
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` int(11) NOT NULL,
- `b` int(11) DEFAULT NULL,
- `testcol2` int(11) DEFAULT NULL,
- PRIMARY KEY (`a`)
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
-select count(1) from t1;
-count(1)
-10000
+drop table t2;
+alter table t1 add testcol2 int;
+ERROR HY000: The table 't1' is full
+alter table t1 add testcol3 int;
+ERROR HY000: The table 't1' is full
+call innodb_insert_proc(20000);
+set autocommit=0;
+call innodb_insert_proc(20000);
+commit;
+set autocommit=1;
+set DEBUG_DBUG='';
drop procedure innodb_insert_proc;
drop table t1;
+drop table if exists t2;
diff --git a/mysql-test/suite/innodb/r/innodb-fk.result b/mysql-test/suite/innodb/r/innodb-fk.result
index cf883d83874..82ac412e339 100644
--- a/mysql-test/suite/innodb/r/innodb-fk.result
+++ b/mysql-test/suite/innodb/r/innodb-fk.result
@@ -33,3 +33,37 @@ select * from fk_29;
f1
29
drop table t1;
+CREATE TABLE t1 (
+id int(11) NOT NULL AUTO_INCREMENT,
+f1 int(11) DEFAULT NULL,
+PRIMARY KEY (id),
+CONSTRAINT fk1 FOREIGN KEY (f1) REFERENCES t1 (id) ON DELETE CASCADE
+) ENGINE=InnoDB;
+CREATE TABLE t2 (
+id int(11) NOT NULL AUTO_INCREMENT,
+f2 int(11) NOT NULL,
+f3 int(11) NOT NULL,
+PRIMARY KEY (`id`),
+CONSTRAINT fk2 FOREIGN KEY (f2) REFERENCES t1 (`id`) ON DELETE CASCADE,
+CONSTRAINT fk3 FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE
+) ENGINE=InnoDB;
+ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed")
+show warnings;
+Level Code Message
+Error 1005 Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed")
+Warning 1215 Cannot add foreign key constraint
+CREATE TABLE t2 (
+id int(11) NOT NULL AUTO_INCREMENT,
+f2 int(11) NOT NULL,
+f3 int(11) NOT NULL,
+PRIMARY KEY (`id`),
+CONSTRAINT fk2 FOREIGN KEY (f2) REFERENCES t1 (`id`) ON DELETE CASCADE
+) ENGINE=InnoDB;
+ALTER TABLE t2 ADD CONSTRAINT fk3 FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE;
+ERROR HY000: Can't create table `test`.`#sql-temporary` (errno: 150 "Foreign key constraint is incorrectly formed")
+show warnings;
+Level Code Message
+Error 1005 Can't create table `test`.`#sql-temporary` (errno: 150 "Foreign key constraint is incorrectly formed")
+Warning 1215 Cannot add foreign key constraint
+drop table t2;
+drop table t1;
diff --git a/mysql-test/suite/innodb/r/innodb-mdev-7055.result b/mysql-test/suite/innodb/r/innodb-mdev-7055.result
new file mode 100644
index 00000000000..d00491fd7e5
--- /dev/null
+++ b/mysql-test/suite/innodb/r/innodb-mdev-7055.result
@@ -0,0 +1 @@
+1
diff --git a/mysql-test/suite/innodb/r/innodb-mdev-7408.result b/mysql-test/suite/innodb/r/innodb-mdev-7408.result
new file mode 100644
index 00000000000..8f6ad139192
--- /dev/null
+++ b/mysql-test/suite/innodb/r/innodb-mdev-7408.result
@@ -0,0 +1,12 @@
+select @@global.innodb_ft_server_stopword_table;
+@@global.innodb_ft_server_stopword_table
+NULL
+CREATE TABLE `stop_it-IT` ENGINE = InnoDB SELECT * FROM information_schema.INNODB_FT_DEFAULT_STOPWORD;
+SET @@global.innodb_ft_server_stopword_table = 'test/stop_it-IT';
+ERROR 42000: Variable 'innodb_ft_server_stopword_table' can't be set to the value of 'test/stop_it-IT'
+SET @@global.innodb_ft_server_stopword_table = 'test/stop_it@002dIT';
+drop table `stop_it-IT`;
+CREATE TABLE stop_it ENGINE = InnoDB SELECT * FROM information_schema.INNODB_FT_DEFAULT_STOPWORD;
+SET @@global.innodb_ft_server_stopword_table = 'test/stop_it';
+SET @@global.innodb_ft_server_stopword_table = NULL;
+drop table stop_it;
diff --git a/mysql-test/suite/innodb/r/innodb-mdev-7513.result b/mysql-test/suite/innodb/r/innodb-mdev-7513.result
new file mode 100644
index 00000000000..bb3531e3f90
--- /dev/null
+++ b/mysql-test/suite/innodb/r/innodb-mdev-7513.result
@@ -0,0 +1,204 @@
+call mtr.add_suppression("Row size too large (> 8126)*");
+CREATE TABLE t1 ( text1 TEXT,
+text2 TEXT,
+text3 TEXT,
+text4 TEXT,
+text5 TEXT,
+text6 TEXT,
+text7 TEXT,
+text8 TEXT,
+text9 TEXT,
+text10 TEXT,
+text11 TEXT,
+text12 TEXT,
+text13 TEXT,
+text14 TEXT,
+text15 TEXT,
+text16 TEXT,
+text17 TEXT,
+text18 TEXT,
+text19 TEXT,
+text20 TEXT,
+text21 TEXT,
+text22 TEXT,
+text23 TEXT,
+text24 TEXT,
+text25 TEXT,
+text26 TEXT,
+text27 TEXT,
+text28 TEXT,
+text29 TEXT,
+text30 TEXT,
+text31 TEXT,
+text32 TEXT,
+text33 TEXT,
+text34 TEXT,
+text35 TEXT,
+text36 TEXT,
+text37 TEXT,
+text38 TEXT,
+text39 TEXT,
+text40 TEXT,
+text41 TEXT,
+text42 TEXT,
+text43 TEXT,
+text44 TEXT,
+text45 TEXT,
+text46 TEXT,
+text47 TEXT,
+text48 TEXT,
+text49 TEXT,
+text50 TEXT,
+text51 TEXT,
+text52 TEXT,
+text53 TEXT,
+text54 TEXT,
+text55 TEXT,
+text56 TEXT,
+text57 TEXT,
+text58 TEXT,
+text59 TEXT,
+text60 TEXT,
+text61 TEXT,
+text62 TEXT,
+text63 TEXT,
+text64 TEXT,
+text65 TEXT,
+text66 TEXT,
+text67 TEXT,
+text68 TEXT,
+text69 TEXT,
+text70 TEXT,
+text71 TEXT,
+text72 TEXT,
+text73 TEXT,
+text74 TEXT,
+text75 TEXT,
+text76 TEXT,
+text77 TEXT,
+text78 TEXT,
+text79 TEXT,
+text80 TEXT,
+text81 TEXT,
+text82 TEXT,
+text83 TEXT,
+text84 TEXT,
+text85 TEXT,
+text86 TEXT,
+text87 TEXT,
+text88 TEXT,
+text89 TEXT,
+text90 TEXT,
+text91 TEXT,
+text92 TEXT,
+text93 TEXT,
+text94 TEXT,
+text95 TEXT,
+text96 TEXT,
+text97 TEXT,
+text98 TEXT,
+text99 TEXT,
+text100 TEXT,
+text101 TEXT,
+text102 TEXT,
+text103 TEXT,
+text104 TEXT,
+text105 TEXT,
+text106 TEXT,
+text107 TEXT,
+text108 TEXT,
+text109 TEXT,
+text110 TEXT,
+text111 TEXT,
+text112 TEXT,
+text113 TEXT,
+text114 TEXT,
+text115 TEXT,
+text116 TEXT,
+text117 TEXT,
+text118 TEXT,
+text119 TEXT,
+text120 TEXT,
+text121 TEXT,
+text122 TEXT,
+text123 TEXT,
+text124 TEXT,
+text125 TEXT,
+text126 TEXT,
+text127 TEXT,
+text128 TEXT,
+text129 TEXT,
+text130 TEXT,
+text131 TEXT,
+text132 TEXT,
+text133 TEXT,
+text134 TEXT,
+text135 TEXT,
+text136 TEXT,
+text137 TEXT,
+text138 TEXT,
+text139 TEXT,
+text140 TEXT,
+text141 TEXT,
+text142 TEXT,
+text143 TEXT,
+text144 TEXT,
+text145 TEXT,
+text146 TEXT,
+text147 TEXT,
+text148 TEXT,
+text149 TEXT,
+text150 TEXT,
+text151 TEXT,
+text152 TEXT,
+text153 TEXT,
+text154 TEXT,
+text155 TEXT,
+text156 TEXT,
+text157 TEXT,
+text158 TEXT,
+text159 TEXT,
+text160 TEXT,
+text161 TEXT,
+text162 TEXT,
+text163 TEXT,
+text164 TEXT,
+text165 TEXT,
+text166 TEXT,
+text167 TEXT,
+text168 TEXT,
+text169 TEXT,
+text170 TEXT,
+text171 TEXT,
+text172 TEXT,
+text173 TEXT,
+text174 TEXT,
+text175 TEXT,
+text176 TEXT,
+text177 TEXT,
+text178 TEXT,
+text179 TEXT,
+text180 TEXT,
+text181 TEXT,
+text182 TEXT,
+text183 TEXT,
+text184 TEXT,
+text185 TEXT,
+text186 TEXT,
+text187 TEXT,
+text188 TEXT,
+text189 TEXT,
+text190 TEXT,
+text191 TEXT,
+text192 TEXT,
+text193 TEXT,
+text194 TEXT,
+text195 TEXT,
+text196 TEXT,
+text197 TEXT
+) ENGINE = InnoDB;
+INSERT INTO t1 VALUES ('abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef');
+DELETE FROM t1 WHERE text1 = 'abcdef';
+SELECT * from t1;
+text1 text2 text3 text4 text5 text6 text7 text8 text9 text10 text11 text12 text13 text14 text15 text16 text17 text18 text19 text20 text21 text22 text23 text24 text25 text26 text27 text28 text29 text30 text31 text32 text33 text34 text35 text36 text37 text38 text39 text40 text41 text42 text43 text44 text45 text46 text47 text48 text49 text50 text51 text52 text53 text54 text55 text56 text57 text58 text59 text60 text61 text62 text63 text64 text65 text66 text67 text68 text69 text70 text71 text72 text73 text74 text75 text76 text77 text78 text79 text80 text81 text82 text83 text84 text85 text86 text87 text88 text89 text90 text91 text92 text93 text94 text95 text96 text97 text98 text99 text100 text101 text102 text103 text104 text105 text106 text107 text108 text109 text110 text111 text112 text113 text114 text115 text116 text117 text118 text119 text120 text121 text122 text123 text124 text125 text126 text127 text128 text129 text130 text131 text132 text133 text134 text135 text136 text137 text138 text139 text140 text141 text142 text143 text144 text145 text146 text147 text148 text149 text150 text151 text152 text153 text154 text155 text156 text157 text158 text159 text160 text161 text162 text163 text164 text165 text166 text167 text168 text169 text170 text171 text172 text173 text174 text175 text176 text177 text178 text179 text180 text181 text182 text183 text184 text185 text186 text187 text188 text189 text190 text191 text192 text193 text194 text195 text196 text197
+DROP TABLE t1;
diff --git a/mysql-test/suite/innodb/r/innodb_bug34300.result b/mysql-test/suite/innodb/r/innodb_bug34300.result
index bf07febca73..09fc0b44579 100644
--- a/mysql-test/suite/innodb/r/innodb_bug34300.result
+++ b/mysql-test/suite/innodb/r/innodb_bug34300.result
@@ -1,3 +1,3 @@
-ERROR 42000: Row size too large (> ####). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.
+ERROR 42000: The size of BLOB/TEXT data inserted in one transaction is greater than 10% of redo log size. Increase the redo log size using innodb_log_file_size.
f4 f8
f4 f8
diff --git a/mysql-test/suite/innodb/t/binlog_consistent.test b/mysql-test/suite/innodb/t/binlog_consistent.test
index 20023871093..c248c39bbce 100644
--- a/mysql-test/suite/innodb/t/binlog_consistent.test
+++ b/mysql-test/suite/innodb/t/binlog_consistent.test
@@ -86,4 +86,35 @@ SHOW MASTER STATUS;
--replace_regex /\/\* xid=.* \*\//\/* XID *\// /Server ver: .*, Binlog ver: .*/Server ver: #, Binlog ver: #/ /table_id: [0-9]+/table_id: #/
SHOW BINLOG EVENTS;
-DROP TABLE t1,t2;
+
+--echo *** MDEV-7310: last_commit_pos_offset set to wrong value after binlog rotate in group commit ***
+
+SET @old_size= @@GLOBAL.max_binlog_size;
+SET GLOBAL max_binlog_size=4096;
+
+CREATE TABLE t3 (a INT PRIMARY KEY, b VARBINARY(8192)) ENGINE=MyISAM;
+INSERT INTO t3 VALUES (10, '');
+--let $bigdata= `SELECT REPEAT('a', 5000)`
+eval INSERT INTO t3 VALUES (11, '$bigdata');
+
+# The bug was that binlog_snapshot_file pointed to the new file after binlog
+# rotation, but binlog_snapshot_position was the offset in the old file before
+# binlog rotation. So the position was invalid.
+# So here, we check that the values are consistent with SHOW MASTER STATUS,
+# which uses a different code path and did not have the bug.
+
+--let $snap_file= query_get_value(SHOW STATUS LIKE 'binlog_snapshot_file', Value, 1)
+--let $snap_pos= query_get_value(SHOW STATUS LIKE 'binlog_snapshot_position', Value, 1)
+
+--let $master_file= query_get_value(SHOW MASTER STATUS, File, 1)
+--let $master_pos= query_get_value(SHOW MASTER STATUS, Position, 1)
+
+--disable_query_log
+eval SET @errmsg= 'ERROR: ($snap_file, $snap_pos) != ($master_file, $master_pos)';
+eval SELECT IF('$snap_file' = '$master_file' AND $snap_pos = $master_pos, 'OK', @errmsg) AS test_result;
+--enable_query_log
+
+SET GLOBAL max_binlog_size=@old_size;
+
+
+DROP TABLE t1,t2, t3;
diff --git a/mysql-test/suite/innodb/t/innodb-alter-table-disk-full.test b/mysql-test/suite/innodb/t/innodb-alter-table-disk-full.test
index adeb2ef9fd2..8fd8e3914c4 100644
--- a/mysql-test/suite/innodb/t/innodb-alter-table-disk-full.test
+++ b/mysql-test/suite/innodb/t/innodb-alter-table-disk-full.test
@@ -7,7 +7,9 @@
# DEBUG_SYNC must be compiled in.
--source include/have_debug_sync.inc
-create table t1(a int not null primary key, b int) engine=innodb;
+call mtr.add_suppression("InnoDB: Error: row_merge_drop_indexes_dict failed with error code*");
+
+create table t1(a int, b int) engine=innodb;
delimiter //;
create procedure innodb_insert_proc (repeat_count int)
@@ -23,28 +25,51 @@ delimiter ;//
commit;
set autocommit=0;
-call innodb_insert_proc(10000);
+call innodb_insert_proc(20000);
commit;
set autocommit=1;
+create table t2(a int) engine=innodb;
+show create table t2;
+
# This caused crash earlier
set DEBUG_DBUG='+d,ib_os_aio_func_io_failure_28';
--error 1114
alter table t1 add testcol int;
show create table t1;
-
-# This caused crash earlier
-set DEBUG_DBUG='+d,ib_os_aio_func_io_failure_28_2';
+--error 1114
+alter table t2 add testcol int;
--error 1114
alter table t1 add testcol int;
-show create table t1;
-
-set DEBUG_DBUG=NULL;
+--error 1114
+alter table t1 add testcol int;
+--error 1114
alter table t1 add testcol2 int;
+--error 1114
+alter table t1 add testcol3 int;
+--error 1114
+alter table t1 add testcol int;
show create table t1;
+--error 0,1051
+drop table t2;
+--error 1114
+alter table t1 add testcol2 int;
+--error 1114
+alter table t1 add testcol3 int;
+--error 0,1114
+call innodb_insert_proc(20000);
+set autocommit=0;
+--error 0,1114
+call innodb_insert_proc(20000);
+commit;
+set autocommit=1;
-select count(1) from t1;
+set DEBUG_DBUG='';
drop procedure innodb_insert_proc;
drop table t1;
+--disable_warnings
+drop table if exists t2;
+--enable_warnings
+
diff --git a/mysql-test/suite/innodb/t/innodb-fk.test b/mysql-test/suite/innodb/t/innodb-fk.test
index 9839cd2d084..2c2a8c76cf8 100644
--- a/mysql-test/suite/innodb/t/innodb-fk.test
+++ b/mysql-test/suite/innodb/t/innodb-fk.test
@@ -84,3 +84,43 @@ while ($i)
drop table t1;
+#
+# MDEV-7672: Crash creating an InnoDB table with foreign keys
+#
+
+CREATE TABLE t1 (
+ id int(11) NOT NULL AUTO_INCREMENT,
+ f1 int(11) DEFAULT NULL,
+ PRIMARY KEY (id),
+ CONSTRAINT fk1 FOREIGN KEY (f1) REFERENCES t1 (id) ON DELETE CASCADE
+) ENGINE=InnoDB;
+
+--error 1005
+CREATE TABLE t2 (
+ id int(11) NOT NULL AUTO_INCREMENT,
+ f2 int(11) NOT NULL,
+ f3 int(11) NOT NULL,
+ PRIMARY KEY (`id`),
+ CONSTRAINT fk2 FOREIGN KEY (f2) REFERENCES t1 (`id`) ON DELETE CASCADE,
+ CONSTRAINT fk3 FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE
+) ENGINE=InnoDB;
+
+show warnings;
+
+CREATE TABLE t2 (
+ id int(11) NOT NULL AUTO_INCREMENT,
+ f2 int(11) NOT NULL,
+ f3 int(11) NOT NULL,
+ PRIMARY KEY (`id`),
+ CONSTRAINT fk2 FOREIGN KEY (f2) REFERENCES t1 (`id`) ON DELETE CASCADE
+) ENGINE=InnoDB;
+
+--replace_regex /#sql-[0-9_a-f-]*/#sql-temporary/
+--error 1005
+ALTER TABLE t2 ADD CONSTRAINT fk3 FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE;
+
+--replace_regex /#sql-[0-9_a-f-]*/#sql-temporary/
+show warnings;
+
+drop table t2;
+drop table t1;
diff --git a/mysql-test/suite/innodb/t/innodb-mdev-7055.test b/mysql-test/suite/innodb/t/innodb-mdev-7055.test
new file mode 100644
index 00000000000..8f4d647e35d
--- /dev/null
+++ b/mysql-test/suite/innodb/t/innodb-mdev-7055.test
@@ -0,0 +1,23 @@
+-- source include/have_innodb.inc
+
+# MDEV-7055: MySQL#74664 - InnoDB: Failing assertion: len <= col->len
+# || col->mtype == 5 || (col->len == 0 && col->mtype == 1) in
+# file rem0rec.cc line 845
+--disable_query_log
+--disable_warnings
+--disable_result_log
+set @old_character_set=@@character_set_connection;
+set character_set_connection=ucs2;
+create TABLE t1 engine=innodb select if(0=0,'Y','N');
+insert INTO t1 values(date_format('2001-01-01','%W'));
+select * from t1;
+drop table t1;
+set @@character_set_connection=@old_character_set;
+--enable_result_log
+--enable_warnings
+--enable_query_log
+
+#produce something
+--echo 1
+
+
diff --git a/mysql-test/suite/innodb/t/innodb-mdev-7408.opt b/mysql-test/suite/innodb/t/innodb-mdev-7408.opt
new file mode 100644
index 00000000000..1c256483e10
--- /dev/null
+++ b/mysql-test/suite/innodb/t/innodb-mdev-7408.opt
@@ -0,0 +1,2 @@
+--innodb_ft_default_stopword
+
diff --git a/mysql-test/suite/innodb/t/innodb-mdev-7408.test b/mysql-test/suite/innodb/t/innodb-mdev-7408.test
new file mode 100644
index 00000000000..d1cd1879bb1
--- /dev/null
+++ b/mysql-test/suite/innodb/t/innodb-mdev-7408.test
@@ -0,0 +1,16 @@
+--source include/have_innodb.inc
+
+select @@global.innodb_ft_server_stopword_table;
+CREATE TABLE `stop_it-IT` ENGINE = InnoDB SELECT * FROM information_schema.INNODB_FT_DEFAULT_STOPWORD;
+--error 1231
+SET @@global.innodb_ft_server_stopword_table = 'test/stop_it-IT';
+--error 0,1231
+SET @@global.innodb_ft_server_stopword_table = 'test/stop_it@002dIT';
+drop table `stop_it-IT`;
+
+CREATE TABLE stop_it ENGINE = InnoDB SELECT * FROM information_schema.INNODB_FT_DEFAULT_STOPWORD;
+SET @@global.innodb_ft_server_stopword_table = 'test/stop_it';
+
+SET @@global.innodb_ft_server_stopword_table = NULL;
+
+drop table stop_it;
diff --git a/mysql-test/suite/innodb/t/innodb-mdev-7513.test b/mysql-test/suite/innodb/t/innodb-mdev-7513.test
new file mode 100644
index 00000000000..b929ea14781
--- /dev/null
+++ b/mysql-test/suite/innodb/t/innodb-mdev-7513.test
@@ -0,0 +1,220 @@
+-- source include/have_innodb.inc
+-- source include/not_embedded.inc
+
+# MDEV-7513: ib_warn_row_too_big dereferences null thd
+
+call mtr.add_suppression("Row size too large (> 8126)*");
+
+--disable_warnings
+CREATE TABLE t1 ( text1 TEXT,
+text2 TEXT,
+text3 TEXT,
+text4 TEXT,
+text5 TEXT,
+text6 TEXT,
+text7 TEXT,
+text8 TEXT,
+text9 TEXT,
+text10 TEXT,
+text11 TEXT,
+text12 TEXT,
+text13 TEXT,
+text14 TEXT,
+text15 TEXT,
+text16 TEXT,
+text17 TEXT,
+text18 TEXT,
+text19 TEXT,
+text20 TEXT,
+text21 TEXT,
+text22 TEXT,
+text23 TEXT,
+text24 TEXT,
+text25 TEXT,
+text26 TEXT,
+text27 TEXT,
+text28 TEXT,
+text29 TEXT,
+text30 TEXT,
+text31 TEXT,
+text32 TEXT,
+text33 TEXT,
+text34 TEXT,
+text35 TEXT,
+text36 TEXT,
+text37 TEXT,
+text38 TEXT,
+text39 TEXT,
+text40 TEXT,
+text41 TEXT,
+text42 TEXT,
+text43 TEXT,
+text44 TEXT,
+text45 TEXT,
+text46 TEXT,
+text47 TEXT,
+text48 TEXT,
+text49 TEXT,
+text50 TEXT,
+text51 TEXT,
+text52 TEXT,
+text53 TEXT,
+text54 TEXT,
+text55 TEXT,
+text56 TEXT,
+text57 TEXT,
+text58 TEXT,
+text59 TEXT,
+text60 TEXT,
+text61 TEXT,
+text62 TEXT,
+text63 TEXT,
+text64 TEXT,
+text65 TEXT,
+text66 TEXT,
+text67 TEXT,
+text68 TEXT,
+text69 TEXT,
+text70 TEXT,
+text71 TEXT,
+text72 TEXT,
+text73 TEXT,
+text74 TEXT,
+text75 TEXT,
+text76 TEXT,
+text77 TEXT,
+text78 TEXT,
+text79 TEXT,
+text80 TEXT,
+text81 TEXT,
+text82 TEXT,
+text83 TEXT,
+text84 TEXT,
+text85 TEXT,
+text86 TEXT,
+text87 TEXT,
+text88 TEXT,
+text89 TEXT,
+text90 TEXT,
+text91 TEXT,
+text92 TEXT,
+text93 TEXT,
+text94 TEXT,
+text95 TEXT,
+text96 TEXT,
+text97 TEXT,
+text98 TEXT,
+text99 TEXT,
+text100 TEXT,
+text101 TEXT,
+text102 TEXT,
+text103 TEXT,
+text104 TEXT,
+text105 TEXT,
+text106 TEXT,
+text107 TEXT,
+text108 TEXT,
+text109 TEXT,
+text110 TEXT,
+text111 TEXT,
+text112 TEXT,
+text113 TEXT,
+text114 TEXT,
+text115 TEXT,
+text116 TEXT,
+text117 TEXT,
+text118 TEXT,
+text119 TEXT,
+text120 TEXT,
+text121 TEXT,
+text122 TEXT,
+text123 TEXT,
+text124 TEXT,
+text125 TEXT,
+text126 TEXT,
+text127 TEXT,
+text128 TEXT,
+text129 TEXT,
+text130 TEXT,
+text131 TEXT,
+text132 TEXT,
+text133 TEXT,
+text134 TEXT,
+text135 TEXT,
+text136 TEXT,
+text137 TEXT,
+text138 TEXT,
+text139 TEXT,
+text140 TEXT,
+text141 TEXT,
+text142 TEXT,
+text143 TEXT,
+text144 TEXT,
+text145 TEXT,
+text146 TEXT,
+text147 TEXT,
+text148 TEXT,
+text149 TEXT,
+text150 TEXT,
+text151 TEXT,
+text152 TEXT,
+text153 TEXT,
+text154 TEXT,
+text155 TEXT,
+text156 TEXT,
+text157 TEXT,
+text158 TEXT,
+text159 TEXT,
+text160 TEXT,
+text161 TEXT,
+text162 TEXT,
+text163 TEXT,
+text164 TEXT,
+text165 TEXT,
+text166 TEXT,
+text167 TEXT,
+text168 TEXT,
+text169 TEXT,
+text170 TEXT,
+text171 TEXT,
+text172 TEXT,
+text173 TEXT,
+text174 TEXT,
+text175 TEXT,
+text176 TEXT,
+text177 TEXT,
+text178 TEXT,
+text179 TEXT,
+text180 TEXT,
+text181 TEXT,
+text182 TEXT,
+text183 TEXT,
+text184 TEXT,
+text185 TEXT,
+text186 TEXT,
+text187 TEXT,
+text188 TEXT,
+text189 TEXT,
+text190 TEXT,
+text191 TEXT,
+text192 TEXT,
+text193 TEXT,
+text194 TEXT,
+text195 TEXT,
+text196 TEXT,
+text197 TEXT
+) ENGINE = InnoDB;
+
+INSERT INTO t1 VALUES ('abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef');
+--enable_warnings
+
+DELETE FROM t1 WHERE text1 = 'abcdef';
+
+--source include/restart_mysqld.inc
+
+--disable_warnings
+SELECT * from t1;
+--enable_warnings
+
+DROP TABLE t1;
+
diff --git a/mysql-test/suite/innodb/t/innodb-mdev7046.test b/mysql-test/suite/innodb/t/innodb-mdev7046.test
index 4033f284e65..b4085228e02 100644
--- a/mysql-test/suite/innodb/t/innodb-mdev7046.test
+++ b/mysql-test/suite/innodb/t/innodb-mdev7046.test
@@ -1,5 +1,7 @@
--source include/have_innodb.inc
--source include/have_partition.inc
+# Test causes OS error printout
+--source include/not_windows.inc
--disable_query_log
--disable_result_log
diff --git a/mysql-test/suite/innodb/t/innodb_bug34300.test b/mysql-test/suite/innodb/t/innodb_bug34300.test
index 800f326707d..13c708b48d6 100644
--- a/mysql-test/suite/innodb/t/innodb_bug34300.test
+++ b/mysql-test/suite/innodb/t/innodb_bug34300.test
@@ -5,6 +5,11 @@
-- source include/have_innodb.inc
+if (`select plugin_auth_version <= "5.6.22-MariaDB-72.0" from information_schema.plugins where plugin_name='innodb'`)
+{
+ --skip Not fixed in XtraDB as of 5.6.22-MariaDB-72.0 or earlier
+}
+
-- disable_query_log
-- disable_result_log
diff --git a/mysql-test/suite/innodb/t/innodb_corrupt_bit.test b/mysql-test/suite/innodb/t/innodb_corrupt_bit.test
index 12c560934ef..d6d77076b83 100644
--- a/mysql-test/suite/innodb/t/innodb_corrupt_bit.test
+++ b/mysql-test/suite/innodb/t/innodb_corrupt_bit.test
@@ -4,11 +4,6 @@
-- source include/have_innodb.inc
-- source include/have_innodb_16k.inc
-if (`select plugin_auth_version <= "5.5.40-MariaDB-36.1" from information_schema.plugins where plugin_name='innodb'`)
-{
- --skip Not fixed in XtraDB as of 5.5.40-MariaDB-36.1 or earlier
-}
-
# Issues with innodb_change_buffering_debug on Windows, so the test scenario
# cannot be created on windows
--source include/not_windows.inc
@@ -30,10 +25,10 @@ SET GLOBAL innodb_change_buffering_debug = 1;
SET UNIQUE_CHECKS=0;
CREATE DATABASE pad;
-let $i=345;
+let $i=338;
while ($i)
{
- --eval CREATE TABLE pad.t$i (a INT PRIMARY KEY) ENGINE=InnoDB;
+--eval CREATE TABLE pad.t$i(a INT PRIMARY KEY)ENGINE=InnoDB;
dec $i;
}
diff --git a/mysql-test/suite/plugins/r/server_audit.result b/mysql-test/suite/plugins/r/server_audit.result
index cc474ceb970..e9f4eb82fbe 100644
--- a/mysql-test/suite/plugins/r/server_audit.result
+++ b/mysql-test/suite/plugins/r/server_audit.result
@@ -85,6 +85,66 @@ create table sa_t1(id int);
insert into sa_t1 values (1), (2);
drop table sa_t1;
drop database sa_db;
+create database sa_db;
+use sa_db;
+CREATE USER u1 IDENTIFIED BY 'pwd-123';
+GRANT ALL ON sa_db TO u2 IDENTIFIED BY "pwd-321";
+SET PASSWORD FOR u1 = PASSWORD('pwd 098');
+CREATE USER u3 IDENTIFIED BY '';
+drop user u1, u2, u3;
+set global server_audit_events='query_ddl';
+create table t1(id int);
+insert into t1 values (1), (2);
+select * from t1;
+id
+1
+2
+select 2;
+2
+2
+(select 2);
+2
+2
+/*! select 2*/;
+2
+2
+/*comment*/ select 2;
+2
+2
+drop table t1;
+set global server_audit_events='query_ddl,query_dml';
+create table t1(id int);
+insert into t1 values (1), (2);
+select * from t1;
+id
+1
+2
+select 2;
+2
+2
+drop table t1;
+set global server_audit_events='query_dml';
+create table t1(id int);
+insert into t1 values (1), (2);
+select * from t1;
+id
+1
+2
+select 2;
+2
+2
+(select 2);
+2
+2
+/*! select 2*/;
+2
+2
+/*comment*/ select 2;
+2
+2
+drop table t1;
+set global server_audit_events='';
+drop database sa_db;
set global server_audit_file_path='.';
show status like 'server_audit_current_log';
Variable_name Value
@@ -184,19 +244,68 @@ TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proc,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,event,
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop database sa_db',0
TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,sa_db,,0
-TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_file_path=\'.\'',0
-TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_file_path=\'.\'',0
-TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'show status like \'server_audit_current_log\'',0
-TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_file_path=\'\'',0
-TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_file_path=\'\'',0
-TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'show status like \'server_audit_current_log\'',0
-TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_file_path=\' \'',0
-TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_file_path=\' \'',0
-TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'show status like \'server_audit_current_log\'',0
-TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_file_path=\'nonexisting_dir/\'',0
-TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_file_path=\'nonexisting_dir/\'',0
-TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'SHOW WARNINGS',0
-TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'show status like \'server_audit_current_log\'',0
-TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'show variables like \'server_audit%\'',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create database sa_db',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'use sa_db',0
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user,
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db,
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv,
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv,
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_priv,
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv,
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping,
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u1 IDENTIFIED BY *****',0
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user,
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv,
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'GRANT ALL ON sa_db TO u2 IDENTIFIED BY *****',0
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user,
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'SET PASSWORD FOR u1 = PASSWORD(*****)',0
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user,
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db,
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv,
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv,
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_priv,
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv,
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping,
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u3 IDENTIFIED BY *****',0
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user,
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db,
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv,
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv,
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_priv,
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv,
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping,
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop user u1, u2, u3',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'create table t1(id int)',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop table t1',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'create table t1(id int)',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'insert into t1 values (1), (2)',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'select * from t1',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'select 2',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop table t1',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'insert into t1 values (1), (2)',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'select * from t1',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'select 2',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'(select 2)',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'/*! select 2*/',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'/*comment*/ select 2',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_events=\'\'',0
+TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,proc,
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proc,
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,event,
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop database sa_db',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_file_path=\'.\'',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_file_path=\'.\'',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'show status like \'server_audit_current_log\'',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_file_path=\'\'',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_file_path=\'\'',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'show status like \'server_audit_current_log\'',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_file_path=\' \'',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_file_path=\' \'',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'show status like \'server_audit_current_log\'',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_file_path=\'nonexisting_dir/\'',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_file_path=\'nonexisting_dir/\'',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'SHOW WARNINGS',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'show status like \'server_audit_current_log\'',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'show variables like \'server_audit%\'',0
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,plugin,
-TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'uninstall plugin server_audit',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'uninstall plugin server_audit',0
diff --git a/mysql-test/suite/plugins/t/server_audit.test b/mysql-test/suite/plugins/t/server_audit.test
index 869fd944d51..eb1727fefc2 100644
--- a/mysql-test/suite/plugins/t/server_audit.test
+++ b/mysql-test/suite/plugins/t/server_audit.test
@@ -15,6 +15,7 @@ connect (con1,localhost,root,,mysql);
connection default;
disconnect con1;
--sleep 2
+--sleep 2
--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT
--error ER_ACCESS_DENIED_ERROR
connect (con1,localhost,no_such_user,,mysql);
@@ -46,6 +47,8 @@ create database sa_db;
--sleep 2
connect (con1,localhost,root,,test);
connection con1;
+--sleep 2
+--sleep 2
create table t1 (id2 int);
insert into t1 values (1), (2);
select * from t1;
@@ -57,8 +60,43 @@ drop table sa_t1;
drop database sa_db;
connection default;
disconnect con1;
-
--sleep 2
+--sleep 2
+create database sa_db;
+use sa_db;
+CREATE USER u1 IDENTIFIED BY 'pwd-123';
+GRANT ALL ON sa_db TO u2 IDENTIFIED BY "pwd-321";
+SET PASSWORD FOR u1 = PASSWORD('pwd 098');
+CREATE USER u3 IDENTIFIED BY '';
+drop user u1, u2, u3;
+
+set global server_audit_events='query_ddl';
+create table t1(id int);
+insert into t1 values (1), (2);
+select * from t1;
+select 2;
+(select 2);
+/*! select 2*/;
+/*comment*/ select 2;
+drop table t1;
+set global server_audit_events='query_ddl,query_dml';
+create table t1(id int);
+insert into t1 values (1), (2);
+select * from t1;
+select 2;
+drop table t1;
+set global server_audit_events='query_dml';
+create table t1(id int);
+insert into t1 values (1), (2);
+select * from t1;
+select 2;
+(select 2);
+/*! select 2*/;
+/*comment*/ select 2;
+drop table t1;
+set global server_audit_events='';
+drop database sa_db;
+
set global server_audit_file_path='.';
--replace_regex /\.[\\\/]/HOME_DIR\//
show status like 'server_audit_current_log';
diff --git a/mysql-test/suite/rpl/r/rpl_drop_db_fail.result b/mysql-test/suite/rpl/r/rpl_drop_db_fail.result
new file mode 100644
index 00000000000..1be90338493
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_drop_db_fail.result
@@ -0,0 +1,16 @@
+include/master-slave.inc
+[connection master]
+CREATE DATABASE IF NOT EXISTS db1;
+CREATE DATABASE IF NOT EXISTS db2;
+use db1;
+CREATE TABLE a(id INT);
+CREATE VIEW v AS SELECT * FROM a;
+CREATE TABLE table_father(id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(20)) ENGINE=INNODB;
+use db2;
+CREATE TABLE table_child(id INT PRIMARY KEY, info VARCHAR(20), father_id INT) ENGINE=INNODB;
+ALTER TABLE table_child ADD CONSTRAINT aaa FOREIGN KEY (father_id) REFERENCES db1.table_father(id);
+DROP DATABASE db1;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
+DROP DATABASE db2;
+DROP DATABASE db1;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_gtid_basic.result b/mysql-test/suite/rpl/r/rpl_gtid_basic.result
index 465cc875af0..f3b52d89eb4 100644
--- a/mysql-test/suite/rpl/r/rpl_gtid_basic.result
+++ b/mysql-test/suite/rpl/r/rpl_gtid_basic.result
@@ -310,7 +310,7 @@ master_gtid_wait('2-1-10')
0
master_gtid_wait('2-1-10')
0
-*** Test sql_gtid_slave_pos when used with GTID ***
+*** Test gtid_slave_pos when used with GTID ***
include/stop_slave.inc
SET gtid_domain_id=2;
SET gtid_seq_no=1000;
@@ -413,5 +413,26 @@ SELECT IF(LOCATE("2-1-1040", @@GLOBAL.gtid_slave_pos)>0, "Ok", CONCAT("ERROR! ex
status
Ok
SET GLOBAL slave_ddl_exec_mode= @saved_mode;
+*** Test GTID-connecting to a master with out-of-order sequence numbers in the binlog. ***
+SET gtid_domain_id= @@GLOBAL.gtid_domain_id;
+INSERT INTO t1 VALUES (31);
+SET gtid_domain_id= @@GLOBAL.gtid_domain_id;
+INSERT INTO t1 VALUES (32);
+INSERT INTO t1 VALUES (33);
+include/stop_slave.inc
+INSERT INTO t1 VALUES (34);
+include/start_slave.inc
+SELECT * FROM t1 WHERE a >= 30 ORDER BY a;
+a
+31
+32
+33
+34
+SELECT * FROM t1 WHERE a >= 30 ORDER BY a;
+a
+31
+32
+33
+34
DROP TABLE t1;
include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_gtid_crash.result b/mysql-test/suite/rpl/r/rpl_gtid_crash.result
index 75bd9d0cbb1..0c2249f2dce 100644
--- a/mysql-test/suite/rpl/r/rpl_gtid_crash.result
+++ b/mysql-test/suite/rpl/r/rpl_gtid_crash.result
@@ -267,5 +267,55 @@ a
24
26
27
+*** MDEV-6391: GTID binlog state not recovered if mariadb-bin.state is removed ***
+include/stop_slave.inc
+INSERT INTO t1 VALUES (30);
+SET @old_server_id= @@server_id;
+SET @old_domain_id= @@gtid_domain_id;
+SET SESSION server_id= 10;
+INSERT INTO t1 VALUES (31);
+INSERT INTO t1 VALUES (32);
+SET SESSION gtid_domain_id= 1;
+SET SESSION server_id=11;
+INSERT INTO t1 VALUES (33);
+SET SESSION gtid_domain_id= 2;
+INSERT INTO t1 VALUES (34);
+SET SESSION server_id= 10;
+INSERT INTO t1 VALUES (35);
+INSERT INTO t1 VALUES (36);
+SET SESSION gtid_domain_id= 0;
+SET SESSION server_id= 12;
+INSERT INTO t1 VALUES (37);
+SET SESSION gtid_domain_id= @old_domain_id;
+SET SESSION server_id= @old_server_id;
+INSERT INTO t1 VALUES (38);
+INSERT INTO t1 VALUES (39);
+SELECT * FROM t1 WHERE a >= 30 ORDER BY a;
+a
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+include/save_master_gtid.inc
+include/start_slave.inc
+include/sync_with_master_gtid.inc
+SELECT * FROM t1 WHERE a >= 30 ORDER BY a;
+a
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
DROP TABLE t1;
include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_parallel.result b/mysql-test/suite/rpl/r/rpl_parallel.result
index 34eaa489c59..9b7c5bd89d2 100644
--- a/mysql-test/suite/rpl/r/rpl_parallel.result
+++ b/mysql-test/suite/rpl/r/rpl_parallel.result
@@ -1137,6 +1137,80 @@ SET GLOBAL debug_dbug=@old_dbug;
SET GLOBAL slave_parallel_threads=0;
SET GLOBAL slave_parallel_threads=10;
include/start_slave.inc
+*** MDEV-7335: Potential parallel slave deadlock with specific binlog corruption ***
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=1;
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,slave_discard_xid_for_gtid_0_x_1000";
+INSERT INTO t2 VALUES (101);
+INSERT INTO t2 VALUES (102);
+INSERT INTO t2 VALUES (103);
+INSERT INTO t2 VALUES (104);
+INSERT INTO t2 VALUES (105);
+SET gtid_seq_no=1000;
+INSERT INTO t2 VALUES (106);
+INSERT INTO t2 VALUES (107);
+INSERT INTO t2 VALUES (108);
+INSERT INTO t2 VALUES (109);
+INSERT INTO t2 VALUES (110);
+INSERT INTO t2 VALUES (111);
+INSERT INTO t2 VALUES (112);
+INSERT INTO t2 VALUES (113);
+INSERT INTO t2 VALUES (114);
+INSERT INTO t2 VALUES (115);
+INSERT INTO t2 VALUES (116);
+INSERT INTO t2 VALUES (117);
+INSERT INTO t2 VALUES (118);
+INSERT INTO t2 VALUES (119);
+INSERT INTO t2 VALUES (120);
+INSERT INTO t2 VALUES (121);
+INSERT INTO t2 VALUES (122);
+INSERT INTO t2 VALUES (123);
+INSERT INTO t2 VALUES (124);
+INSERT INTO t2 VALUES (125);
+INSERT INTO t2 VALUES (126);
+INSERT INTO t2 VALUES (127);
+INSERT INTO t2 VALUES (128);
+INSERT INTO t2 VALUES (129);
+INSERT INTO t2 VALUES (130);
+include/save_master_gtid.inc
+include/start_slave.inc
+include/sync_with_master_gtid.inc
+SELECT * FROM t2 WHERE a >= 100 ORDER BY a;
+a
+101
+102
+103
+104
+105
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_threads=10;
+include/start_slave.inc
*** MDEV-6676 - test syntax of @@slave_parallel_mode ***
Parallel_Mode = 'conservative'
include/stop_slave.inc
diff --git a/mysql-test/suite/rpl/r/rpl_trigger.result b/mysql-test/suite/rpl/r/rpl_trigger.result
index ac6d9155f4b..c0e35274594 100644
--- a/mysql-test/suite/rpl/r/rpl_trigger.result
+++ b/mysql-test/suite/rpl/r/rpl_trigger.result
@@ -986,4 +986,15 @@ Warning 1196 Some non-transactional changed tables couldn't be rolled back
include/diff_tables.inc [master:t1, slave:t1]
include/diff_tables.inc [master:log, slave:log]
drop table t1, log;
+drop trigger if exists notexistent;
+Warnings:
+Note 1360 Trigger does not exist
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; drop trigger if exists notexistent
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+slave-bin.000001 # Gtid # # GTID #-#-#
+slave-bin.000001 # Query # # use `test`; drop trigger if exists notexistent
include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/semisync_future-7591.result b/mysql-test/suite/rpl/r/semisync_future-7591.result
new file mode 100644
index 00000000000..732ae09daaf
--- /dev/null
+++ b/mysql-test/suite/rpl/r/semisync_future-7591.result
@@ -0,0 +1,19 @@
+include/master-slave.inc
+[connection master]
+call mtr.add_suppression("Timeout waiting for reply of binlog*");
+create table t1 (i int);
+set global rpl_semi_sync_master_enabled = ON;
+include/stop_slave.inc
+set global rpl_semi_sync_slave_enabled = ON;
+change master to master_log_file='master-bin.000002', master_log_pos = 320;
+start slave;
+include/wait_for_slave_io_error.inc [errno=1236]
+insert into t1 values (1);
+reset master;
+include/stop_slave.inc
+reset slave;
+include/start_slave.inc
+set global rpl_semi_sync_slave_enabled = OFF;
+drop table t1;
+set global rpl_semi_sync_master_enabled = OFF;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_drop_db_fail.test b/mysql-test/suite/rpl/t/rpl_drop_db_fail.test
new file mode 100644
index 00000000000..77e6cb957f7
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_drop_db_fail.test
@@ -0,0 +1,32 @@
+###############################################################################
+# Bug#20041860: SLAVE ERROR WHEN DROP DATABASE
+#
+# Test:
+# =====
+# Create two databases such that one database has a dependency over the other
+# database and try to drop the database which has a dependency. This should
+# not cause slave to break.
+###############################################################################
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+connection master;
+CREATE DATABASE IF NOT EXISTS db1;
+CREATE DATABASE IF NOT EXISTS db2;
+
+use db1;
+CREATE TABLE a(id INT);
+CREATE VIEW v AS SELECT * FROM a;
+CREATE TABLE table_father(id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(20)) ENGINE=INNODB;
+
+use db2;
+CREATE TABLE table_child(id INT PRIMARY KEY, info VARCHAR(20), father_id INT) ENGINE=INNODB;
+ALTER TABLE table_child ADD CONSTRAINT aaa FOREIGN KEY (father_id) REFERENCES db1.table_father(id);
+
+--error ER_ROW_IS_REFERENCED
+DROP DATABASE db1;
+DROP DATABASE db2;
+--sync_slave_with_master
+--connection master
+DROP DATABASE db1;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_basic.test b/mysql-test/suite/rpl/t/rpl_gtid_basic.test
index 19f90fce197..778cf427d99 100644
--- a/mysql-test/suite/rpl/t/rpl_gtid_basic.test
+++ b/mysql-test/suite/rpl/t/rpl_gtid_basic.test
@@ -367,7 +367,7 @@ reap;
reap;
---echo *** Test sql_gtid_slave_pos when used with GTID ***
+--echo *** Test gtid_slave_pos when used with GTID ***
--connection server_2
--source include/stop_slave.inc
@@ -481,6 +481,55 @@ SELECT IF(LOCATE("2-1-1040", @@GLOBAL.gtid_slave_pos)>0, "Ok", CONCAT("ERROR! ex
SET GLOBAL slave_ddl_exec_mode= @saved_mode;
+
+--echo *** Test GTID-connecting to a master with out-of-order sequence numbers in the binlog. ***
+
+# Create an out-of-order binlog on server 2.
+# Let server 3 replicate to an out-of-order point, stop it, restart it,
+# and check that it replicates correctly despite the out-of-order.
+
+--connection server_1
+SET gtid_domain_id= @@GLOBAL.gtid_domain_id;
+INSERT INTO t1 VALUES (31);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SET gtid_domain_id= @@GLOBAL.gtid_domain_id;
+INSERT INTO t1 VALUES (32);
+
+--connection server_1
+INSERT INTO t1 VALUES (33);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--save_master_pos
+
+--connection server_3
+--sync_with_master
+--source include/stop_slave.inc
+
+--connection server_1
+INSERT INTO t1 VALUES (34);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--save_master_pos
+
+--connection server_3
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 WHERE a >= 30 ORDER BY a;
+--save_master_pos
+
+--connection server_4
+SELECT * FROM t1 WHERE a >= 30 ORDER BY a;
+--sync_with_master
+
+
+# Clean up.
--connection server_1
DROP TABLE t1;
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_crash.test b/mysql-test/suite/rpl/t/rpl_gtid_crash.test
index 90b4e454a74..df3ba9a3420 100644
--- a/mysql-test/suite/rpl/t/rpl_gtid_crash.test
+++ b/mysql-test/suite/rpl/t/rpl_gtid_crash.test
@@ -587,6 +587,77 @@ eval SELECT IF(INSTR(@@gtid_current_pos, '$saved_gtid'), "Current pos ok", CONCA
SELECT * from t1 WHERE a > 10 ORDER BY a;
+--echo *** MDEV-6391: GTID binlog state not recovered if mariadb-bin.state is removed ***
+
+--connection server_2
+--source include/stop_slave.inc
+
+# Do some misc. transactions, stop the master, drop the master-bin.state file.
+# Start the master back up, check that binlog state is correct.
+
+--connection server_1
+
+INSERT INTO t1 VALUES (30);
+SET @old_server_id= @@server_id;
+SET @old_domain_id= @@gtid_domain_id;
+
+SET SESSION server_id= 10;
+INSERT INTO t1 VALUES (31);
+INSERT INTO t1 VALUES (32);
+SET SESSION gtid_domain_id= 1;
+SET SESSION server_id=11;
+INSERT INTO t1 VALUES (33);
+SET SESSION gtid_domain_id= 2;
+INSERT INTO t1 VALUES (34);
+SET SESSION server_id= 10;
+INSERT INTO t1 VALUES (35);
+INSERT INTO t1 VALUES (36);
+SET SESSION gtid_domain_id= 0;
+SET SESSION server_id= 12;
+INSERT INTO t1 VALUES (37);
+SET SESSION gtid_domain_id= @old_domain_id;
+SET SESSION server_id= @old_server_id;
+INSERT INTO t1 VALUES (38);
+INSERT INTO t1 VALUES (39);
+SELECT * FROM t1 WHERE a >= 30 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--let OLD_STATE= `SELECT @@gtid_binlog_state`
+
+--let $datadir= `SELECT @@datadir`
+
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait
+EOF
+shutdown_server 10;
+--source include/wait_until_disconnected.inc
+
+--remove_file $datadir/master-bin.state
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart
+EOF
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--let NEW_STATE= `SELECT @@gtid_binlog_state`
+
+--perl
+my $old= $ENV{'OLD_STATE'};
+my $new= $ENV{'NEW_STATE'};
+# Make them order-independent, for easy comparison.
+$old= join(",", sort(split(",", $old)));
+$new= join(",", sort(split(",", $new)));
+die "ERROR: new binlog state '$new' differs from old '$old'\n"
+ unless $old eq $new;
+EOF
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 WHERE a >= 30 ORDER BY a;
+
+
--connection server_1
DROP TABLE t1;
diff --git a/mysql-test/suite/rpl/t/rpl_parallel.test b/mysql-test/suite/rpl/t/rpl_parallel.test
index 3711e8327d8..81670e64f7e 100644
--- a/mysql-test/suite/rpl/t/rpl_parallel.test
+++ b/mysql-test/suite/rpl/t/rpl_parallel.test
@@ -1841,6 +1841,61 @@ SET GLOBAL slave_parallel_threads=0;
SET GLOBAL slave_parallel_threads=10;
--source include/start_slave.inc
+--echo *** MDEV-7335: Potential parallel slave deadlock with specific binlog corruption ***
+
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=1;
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,slave_discard_xid_for_gtid_0_x_1000";
+
+--connection server_1
+INSERT INTO t2 VALUES (101);
+INSERT INTO t2 VALUES (102);
+INSERT INTO t2 VALUES (103);
+INSERT INTO t2 VALUES (104);
+INSERT INTO t2 VALUES (105);
+# Inject a partial event group (missing XID at the end). The bug was that such
+# partial group was not handled appropriately, leading to server deadlock.
+SET gtid_seq_no=1000;
+INSERT INTO t2 VALUES (106);
+INSERT INTO t2 VALUES (107);
+INSERT INTO t2 VALUES (108);
+INSERT INTO t2 VALUES (109);
+INSERT INTO t2 VALUES (110);
+INSERT INTO t2 VALUES (111);
+INSERT INTO t2 VALUES (112);
+INSERT INTO t2 VALUES (113);
+INSERT INTO t2 VALUES (114);
+INSERT INTO t2 VALUES (115);
+INSERT INTO t2 VALUES (116);
+INSERT INTO t2 VALUES (117);
+INSERT INTO t2 VALUES (118);
+INSERT INTO t2 VALUES (119);
+INSERT INTO t2 VALUES (120);
+INSERT INTO t2 VALUES (121);
+INSERT INTO t2 VALUES (122);
+INSERT INTO t2 VALUES (123);
+INSERT INTO t2 VALUES (124);
+INSERT INTO t2 VALUES (125);
+INSERT INTO t2 VALUES (126);
+INSERT INTO t2 VALUES (127);
+INSERT INTO t2 VALUES (128);
+INSERT INTO t2 VALUES (129);
+INSERT INTO t2 VALUES (130);
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+# The partial event group (a=106) should be rolled back and thus missing.
+SELECT * FROM t2 WHERE a >= 100 ORDER BY a;
+
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_threads=10;
+--source include/start_slave.inc
+
--echo *** MDEV-6676 - test syntax of @@slave_parallel_mode ***
--connection server_2
diff --git a/mysql-test/suite/rpl/t/rpl_trigger.test b/mysql-test/suite/rpl/t/rpl_trigger.test
index 723fa3e44e2..e062e821a25 100644
--- a/mysql-test/suite/rpl/t/rpl_trigger.test
+++ b/mysql-test/suite/rpl/t/rpl_trigger.test
@@ -533,6 +533,19 @@ drop table t1, log;
sync_slave_with_master;
#
+# MDEV-6769 DROP TRIGGER IF NOT EXIST binlogged on master but not on slave
+#
+let $slave_pos= query_get_value(SHOW MASTER STATUS, Position, 1);
+connection master;
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+drop trigger if exists notexistent;
+source include/show_binlog_events.inc;
+sync_slave_with_master;
+let $binlog_start= $slave_pos;
+source include/show_binlog_events.inc;
+connection master;
+
+#
# End of tests
#
--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/semisync_future-7591.test b/mysql-test/suite/rpl/t/semisync_future-7591.test
new file mode 100644
index 00000000000..772a36b5632
--- /dev/null
+++ b/mysql-test/suite/rpl/t/semisync_future-7591.test
@@ -0,0 +1,31 @@
+--source include/have_semisync.inc
+--source include/master-slave.inc
+
+call mtr.add_suppression("Timeout waiting for reply of binlog*");
+create table t1 (i int);
+
+set global rpl_semi_sync_master_enabled = ON;
+
+--connection slave
+--source include/stop_slave.inc
+set global rpl_semi_sync_slave_enabled = ON;
+change master to master_log_file='master-bin.000002', master_log_pos = 320;
+
+start slave;
+--let $slave_io_errno=1236
+--source include/wait_for_slave_io_error.inc
+
+--connection master
+insert into t1 values (1);
+reset master;
+
+--connection slave
+--source include/stop_slave.inc
+reset slave;
+--source include/start_slave.inc
+
+set global rpl_semi_sync_slave_enabled = OFF;
+--connection master
+drop table t1;
+set global rpl_semi_sync_master_enabled = OFF;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff b/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff
index f553cd4f586..2ce01384d0f 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff
+++ b/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff
@@ -1,5 +1,5 @@
---- suite/sys_vars/r/sysvars_innodb.result 2015-02-12 15:19:56.000000000 +0100
-+++ suite/sys_vars/r/sysvars_innodb,xtradb.reject 2015-02-13 00:46:02.000000000 +0100
+--- suite/sys_vars/r/sysvars_innodb.result
++++ suite/sys_vars/r/sysvars_innodb,xtradb.reject
@@ -47,6 +47,20 @@
ENUM_VALUE_LIST NULL
READ_ONLY NO
@@ -177,7 +177,7 @@
VARIABLE_NAME INNODB_DATA_FILE_PATH
SESSION_VALUE NULL
GLOBAL_VALUE ibdata1:12M:autoextend
-@@ -705,6 +845,20 @@
+@@ -719,6 +859,20 @@
ENUM_VALUE_LIST NULL
READ_ONLY YES
COMMAND_LINE_ARGUMENT OPTIONAL
@@ -198,7 +198,7 @@
VARIABLE_NAME INNODB_ENCRYPTION_ROTATE_KEY_AGE
SESSION_VALUE NULL
GLOBAL_VALUE 1
-@@ -775,6 +929,20 @@
+@@ -789,6 +943,20 @@
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
@@ -219,7 +219,7 @@
VARIABLE_NAME INNODB_FAST_SHUTDOWN
SESSION_VALUE NULL
GLOBAL_VALUE 1
-@@ -902,11 +1070,11 @@
+@@ -916,11 +1084,11 @@
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME INNODB_FLUSH_LOG_AT_TRX_COMMIT
@@ -233,7 +233,7 @@
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Controls the durability/speed trade-off for commits. Set to 0 (write and flush redo log to disk only once per second), 1 (flush to disk at each commit), 2 (write to log at commit but flush to disk only once per second) or 3 (flush to disk at prepare and at commit, slower and usually redundant). 1 and 3 guarantees that after a crash, committed transactions will not be lost and will be consistent with the binlog and other transactional engines. 2 can get inconsistent and lose transactions if there is a power failure or kernel crash but not if mysqld crashes. 0 has no guarantees in case of crash. 0 and 2 can be faster than 1 or 3.
NUMERIC_MIN_VALUE 0
-@@ -999,6 +1167,20 @@
+@@ -1013,6 +1181,20 @@
ENUM_VALUE_LIST NULL
READ_ONLY YES
COMMAND_LINE_ARGUMENT REQUIRED
@@ -254,7 +254,7 @@
VARIABLE_NAME INNODB_FT_AUX_TABLE
SESSION_VALUE NULL
GLOBAL_VALUE
-@@ -1223,6 +1405,20 @@
+@@ -1251,6 +1433,20 @@
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
@@ -275,7 +275,7 @@
VARIABLE_NAME INNODB_LARGE_PREFIX
SESSION_VALUE NULL
GLOBAL_VALUE OFF
-@@ -1251,6 +1447,20 @@
+@@ -1279,6 +1475,20 @@
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
@@ -296,7 +296,7 @@
VARIABLE_NAME INNODB_LOCKS_UNSAFE_FOR_BINLOG
SESSION_VALUE NULL
GLOBAL_VALUE OFF
-@@ -1279,6 +1489,62 @@
+@@ -1307,6 +1517,62 @@
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
@@ -359,7 +359,7 @@
VARIABLE_NAME INNODB_LOG_BUFFER_SIZE
SESSION_VALUE NULL
GLOBAL_VALUE 1048576
-@@ -1307,6 +1573,20 @@
+@@ -1335,6 +1601,20 @@
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
@@ -380,7 +380,7 @@
VARIABLE_NAME INNODB_LOG_COMPRESSED_PAGES
SESSION_VALUE NULL
GLOBAL_VALUE OFF
-@@ -1377,6 +1657,34 @@
+@@ -1405,6 +1685,34 @@
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
@@ -415,7 +415,7 @@
VARIABLE_NAME INNODB_MAX_DIRTY_PAGES_PCT
SESSION_VALUE NULL
GLOBAL_VALUE 75.000000
-@@ -1643,6 +1951,62 @@
+@@ -1671,6 +1979,62 @@
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
@@ -478,7 +478,7 @@
VARIABLE_NAME INNODB_PURGE_BATCH_SIZE
SESSION_VALUE NULL
GLOBAL_VALUE 300
-@@ -1811,6 +2175,48 @@
+@@ -1839,6 +2203,48 @@
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
@@ -527,7 +527,7 @@
VARIABLE_NAME INNODB_SCRUB_FORCE_TESTING
SESSION_VALUE NULL
GLOBAL_VALUE OFF
-@@ -1853,6 +2259,34 @@
+@@ -1881,6 +2287,34 @@
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
@@ -562,7 +562,7 @@
VARIABLE_NAME INNODB_SIMULATE_COMP_FAILURES
SESSION_VALUE NULL
GLOBAL_VALUE 0
-@@ -1916,7 +2350,7 @@
+@@ -1944,7 +2378,7 @@
DEFAULT_VALUE nulls_equal
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE ENUM
@@ -571,7 +571,7 @@
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
-@@ -2147,6 +2581,34 @@
+@@ -2175,6 +2609,34 @@
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
@@ -606,7 +606,7 @@
VARIABLE_NAME INNODB_TRX_PURGE_VIEW_UPDATE_ONLY_DEBUG
SESSION_VALUE NULL
GLOBAL_VALUE OFF
-@@ -2224,7 +2686,7 @@
+@@ -2252,7 +2714,7 @@
DEFAULT_VALUE OFF
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BOOLEAN
@@ -615,7 +615,7 @@
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
-@@ -2245,6 +2707,20 @@
+@@ -2273,6 +2735,20 @@
ENUM_VALUE_LIST NULL
READ_ONLY YES
COMMAND_LINE_ARGUMENT NONE
@@ -636,7 +636,7 @@
VARIABLE_NAME INNODB_USE_MTFLUSH
SESSION_VALUE NULL
GLOBAL_VALUE OFF
-@@ -2259,6 +2735,20 @@
+@@ -2287,6 +2763,20 @@
ENUM_VALUE_LIST NULL
READ_ONLY YES
COMMAND_LINE_ARGUMENT NONE
@@ -657,12 +657,12 @@
VARIABLE_NAME INNODB_USE_SYS_MALLOC
SESSION_VALUE NULL
GLOBAL_VALUE ON
-@@ -2289,12 +2779,12 @@
+@@ -2317,12 +2807,12 @@
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME INNODB_VERSION
SESSION_VALUE NULL
--GLOBAL_VALUE 5.6.22
-+GLOBAL_VALUE 5.6.22-71.0
+-GLOBAL_VALUE 5.6.23
++GLOBAL_VALUE 5.6.22-72.0
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE NULL
VARIABLE_SCOPE GLOBAL
diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result
index 030b8cd367c..867fe02d454 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result
@@ -2317,7 +2317,7 @@ READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME INNODB_VERSION
SESSION_VALUE NULL
-GLOBAL_VALUE 5.6.22
+GLOBAL_VALUE 5.6.23
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE NULL
VARIABLE_SCOPE GLOBAL
diff --git a/mysql-test/t/ctype_binary.test b/mysql-test/t/ctype_binary.test
index 4a2646d1db5..3d3f90b444b 100644
--- a/mysql-test/t/ctype_binary.test
+++ b/mysql-test/t/ctype_binary.test
@@ -20,5 +20,10 @@ SET NAMES binary;
--source include/ctype_like_cond_propagation.inc
--echo #
+--echo # MDEV-7629 Regression: Bit and hex string literals changed column names in 10.0.14
+--echo #
+SELECT _binary 0x7E, _binary X'7E', _binary B'01111110';
+
+--echo #
--echo # End of 10.0 tests
--echo #
diff --git a/mysql-test/t/ctype_latin1.test b/mysql-test/t/ctype_latin1.test
index 336d8ca761d..aeaad2cc026 100644
--- a/mysql-test/t/ctype_latin1.test
+++ b/mysql-test/t/ctype_latin1.test
@@ -241,5 +241,10 @@ SELECT HEX(a),a FROM t1;
DROP TABLE t1;
--echo #
+--echo # MDEV-7629 Regression: Bit and hex string literals changed column names in 10.0.14
+--echo #
+SELECT _latin1 0x7E, _latin1 X'7E', _latin1 B'01111110';
+
+--echo #
--echo # End of 10.0 tests
--echo #
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index 1e9047cca8e..af5f4b8ccf8 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -1744,6 +1744,11 @@ EXECUTE stmt USING @b,@b;
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
+--echo #
+--echo # MDEV-7629 Regression: Bit and hex string literals changed column names in 10.0.14
+--echo #
+SELECT _utf8 0x7E, _utf8 X'7E', _utf8 B'01111110';
+
let $ctype_unescape_combinations=selected;
--source include/ctype_unescape.inc
diff --git a/mysql-test/t/error_simulation-master.opt b/mysql-test/t/error_simulation-master.opt
new file mode 100644
index 00000000000..c9f8d7bd0c0
--- /dev/null
+++ b/mysql-test/t/error_simulation-master.opt
@@ -0,0 +1 @@
+--tmpdir=$MYSQLTEST_VARDIR/tmp
diff --git a/mysql-test/t/error_simulation.test b/mysql-test/t/error_simulation.test
index 58ead1e3ced..7c343ed6566 100644
--- a/mysql-test/t/error_simulation.test
+++ b/mysql-test/t/error_simulation.test
@@ -1,4 +1,5 @@
-- source include/have_debug.inc
+--source include/not_embedded.inc
#
# Bug #28499: crash for grouping query when tmp_table_size is too small
@@ -112,3 +113,38 @@ DROP TABLE t1,t2;
--echo #
--echo # End of 5.1 tests
--echo #
+
+
+--echo #
+--echo # BUG#11747548:DETECT ORPHAN TEMP-POOL FILES, AND HANDLE GRACEFULLY.
+--echo #
+
+--echo #Set up.
+CREATE TABLE pid_table(pid_no INT);
+CREATE TABLE t1 (a BLOB);
+INSERT INTO t1 VALUES (1), (2);
+
+--echo #Create MYD and MYI files for intrinsic temp table.
+--let $pid_file=`SELECT @@pid_file`
+--replace_result $pid_file pid_file
+--eval LOAD DATA LOCAL INFILE '$pid_file' INTO TABLE pid_table
+--let $temp_file= `SELECT CONCAT('#sql_', LCASE(HEX(pid_no)), '_0') FROM pid_table`
+--write_file $MYSQLTEST_VARDIR/tmp/$temp_file.MYD
+EOF
+--write_file $MYSQLTEST_VARDIR/tmp/$temp_file.MYI
+EOF
+--write_file $MYSQLTEST_VARDIR/tmp/$temp_file.MAD
+EOF
+--write_file $MYSQLTEST_VARDIR/tmp/$temp_file.MAI
+EOF
+
+--echo #Reports an error since the temp file already exists.
+--replace_regex /.*Can't create\/write *.*/Can't create or write to file/
+#--error 1
+SELECT a FROM t1 ORDER BY rand(1);
+
+--echo #With patch, the query executes successfully.
+SELECT a FROM t1 ORDER BY rand(1);
+
+--echo #cleanup
+DROP TABLE t1, pid_table;
diff --git a/mysql-test/t/file_contents.test b/mysql-test/t/file_contents.test
index 7592cb9420d..4734a0294f0 100644
--- a/mysql-test/t/file_contents.test
+++ b/mysql-test/t/file_contents.test
@@ -36,7 +36,7 @@ if ($dir_bin eq '/usr/') {
# Slackware
$dir_docs = glob "$dir_bin/doc/mariadb-[0-9]*" unless -d $dir_docs;
} else {
- # tar.gz package, Windows, or developer work (in BZR)
+ # tar.gz package, Windows, or developer work (in git)
$dir_docs = $dir_bin;
if(-d "$dir_docs/docs") {
$dir_docs = "$dir_docs/docs"; # package
@@ -49,8 +49,7 @@ $found_revision = "No line 'revision-id: .....' in $dir_docs/INFO_SRC";
open(I_SRC,"<","$dir_docs/INFO_SRC") or print "Cannot open 'INFO_SRC' in '$dir_docs' (starting from bindir '$dir_bin')\n";
while(defined ($line = <I_SRC>)) {
if ($line =~ m|^MariaDB source \d+\.\d\.\d+|) {$found_version = "Found MariaDB version number";}
- if ($line =~ m|^revision-id: .*@.*-2\d{13}-\w+$|) {$found_revision = "Found revision id";}
- if ($line =~ m|^commit: \w{40}$|) {$found_revision = "Found revision id";}
+ if ($line =~ m|^commit: \w{40}$|) {$found_revision = "Found GIT revision id";}
}
close I_SRC;
print "INFO_SRC: $found_version / $found_revision\n";
diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test
index 2679874ddff..69f93a6af22 100644
--- a/mysql-test/t/gis.test
+++ b/mysql-test/t/gis.test
@@ -1443,6 +1443,11 @@ create table t1 (pt point);
insert into t1 values(Geomfromtext('POLYGON((1 1, 2 2, 2 1, 1 1))'));
drop table t1;
+#
+# MDEV-7516 Assertion `!cur_p->event' failed in Gcalc_scan_iterator::arrange_event(int, int)
+#
+SELECT st_astext(ST_Buffer(ST_PolygonFromText('POLYGON((3 5, 2 4, 2 5, 3 5))'), -100));
+
--echo End of 5.5 tests
SHOW CREATE TABLE information_schema.geometry_columns;
diff --git a/mysql-test/t/group_by_innodb.test b/mysql-test/t/group_by_innodb.test
index 75ee3d0802a..e072a94fada 100644
--- a/mysql-test/t/group_by_innodb.test
+++ b/mysql-test/t/group_by_innodb.test
@@ -85,4 +85,44 @@ a.oid=b.oid WHERE a.oidGroup=1 GROUP BY a.oid;
DROP TABLE t1, t2;
+--echo #
+--echo # MDEV-7193: Incorrect Query Result (MySQL Bug 68897) in MariaDB 10.0.14
+--echo # (fixed by MDEV-5719)
+--echo #
+
+CREATE TABLE `t1` (
+ `param` int(11) NOT NULL,
+ `idx` int(11) NOT NULL,
+ `text` varchar(255) default NULL,
+ PRIMARY KEY (`param`,`idx`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+INSERT INTO `t1` (`param`, `idx`, `text`) VALUES
+(1, 0, 'select'),
+(1, 1, 'Kabel mit Stecker 5-polig'),
+(1, 2, 'Kabel ohne Stecker'),
+(2, 0, 'number'),
+(2, 1, '22'),
+(2, 2, '25');
+CREATE TABLE `t2` (
+ `id` int PRIMARY KEY
+);
+
+INSERT INTO t2 VALUES (1),(2),(3),(4);
+SELECT t2.id AS id, T.text AS xtext,GROUP_CONCAT(T3.text) AS optionen
+FROM t2
+LEFT JOIN t1 AS T ON(T.param=t2.id AND T.idx=0 )
+LEFT JOIN t1 AS T3 ON(T3.param=t2.id AND T3.idx>0 )
+GROUP BY t2.id
+ORDER BY id ASC;
+
+SELECT t2.id AS id, T.text AS xtext,GROUP_CONCAT(T3.text) AS optionen
+FROM t2
+LEFT JOIN t1 AS T ON(T.param=t2.id AND T.idx=0 )
+LEFT JOIN t1 AS T3 ON(T3.param=t2.id AND T3.idx>0 )
+GROUP BY t2.id
+ORDER BY id DESC;
+
+DROP TABLE t1, t2;
+
--echo # End of tests
diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test
index 1f3d2c551e6..cd98bf3aa5c 100644
--- a/mysql-test/t/information_schema.test
+++ b/mysql-test/t/information_schema.test
@@ -1827,6 +1827,23 @@ drop view v1;
--echo # Clean-up.
drop database mysqltest;
+--echo #
+--echo # Test for bug #16869534 - "QUERYING SUBSET OF COLUMNS DOESN'T USE TABLE
+--echo # CACHE; OPENED_TABLES INCREASES"
+--echo #
+--disable_result_log
+SELECT * FROM INFORMATION_SCHEMA.TABLES;
+--enable_result_log
+SELECT VARIABLE_VALUE INTO @val1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE
+ VARIABLE_NAME LIKE 'Opened_tables';
+--disable_result_log
+SELECT ENGINE FROM INFORMATION_SCHEMA.TABLES;
+--enable_result_log
+--echo # The below SELECT query should give same output as above SELECT query.
+SELECT VARIABLE_VALUE INTO @val2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE
+ VARIABLE_NAME LIKE 'Opened_tables';
+--echo # The below select should return '1'
+SELECT @val1 = @val2;
--echo #
--echo # End of 5.5 tests
diff --git a/mysql-test/t/join_cache.test b/mysql-test/t/join_cache.test
index 0e4610b9f54..7d873c555f6 100644
--- a/mysql-test/t/join_cache.test
+++ b/mysql-test/t/join_cache.test
@@ -3848,6 +3848,18 @@ set join_buffer_space_limit=default;
drop table t1;
+--echo #
+--echo # MDEV-6687: Assertion `0' failed in Protocol::end_statement on query
+--echo #
+SET join_cache_level = 3;
+--echo # The following should have
+--echo # - table order PROFILING,user,
+--echo # - table user accessed with hash_ALL:
+explain
+SELECT * FROM INFORMATION_SCHEMA.PROFILING, mysql.user WHERE password_expired = PAGE_FAULTS_MINOR;
+
+set join_cache_level=default;
+
# The following command must be the last one the file
# this must be the last command in the file
set @@optimizer_switch=@save_optimizer_switch;
diff --git a/mysql-test/t/openssl_1.test b/mysql-test/t/openssl_1.test
index bee0e2cc720..3594b8c86eb 100644
--- a/mysql-test/t/openssl_1.test
+++ b/mysql-test/t/openssl_1.test
@@ -15,8 +15,8 @@ insert into t1 values (5);
grant select on test.* to ssl_user1@localhost require SSL;
grant select on test.* to ssl_user2@localhost require cipher "DHE-RSA-AES256-SHA";
-grant select on test.* to ssl_user3@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/ST=Uppsala/O=MySQL AB";
-grant select on test.* to ssl_user4@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/ST=Uppsala/O=MySQL AB" ISSUER "/C=SE/ST=Uppsala/L=Uppsala/O=MySQL AB";
+grant select on test.* to ssl_user3@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/ST=Stockholm/L=Stockholm/O=Oracle/OU=MySQL/CN=Client";
+grant select on test.* to ssl_user4@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/ST=Stockholm/L=Stockholm/O=Oracle/OU=MySQL/CN=Client" ISSUER "/C=SE/ST=Stockholm/L=Stockholm/O=Oracle/OU=MySQL/CN=CA";
grant select on test.* to ssl_user5@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "xxx";
flush privileges;
diff --git a/mysql-test/t/partition_innodb_plugin.test b/mysql-test/t/partition_innodb_plugin.test
index 8044ae9ec5c..fd6e60c27fb 100644
--- a/mysql-test/t/partition_innodb_plugin.test
+++ b/mysql-test/t/partition_innodb_plugin.test
@@ -149,11 +149,11 @@ UPDATE `t``\""e` SET a = 4 WHERE a = 22;
# NOTE: replace_regex is very slow on match copy/past '(.*)' regex's
# on big texts, removing a lot of text before + after makes it much faster.
#/.*in (.*) trx.*/\1/
---replace_regex /.*RECORD LOCKS space id [0-9]* page no [0-9]* n bits [0-9]* // / trx id .*// /.*index .* in //
+--replace_regex /.*RECORD LOCKS space id [0-9]* page no [0-9]* n bits [0-9]* // / trx id .*// /.*index .* in // /trx table locks [0-9]* // /total table locks [0-9]* //
SHOW ENGINE InnoDB STATUS;
set @old_sql_mode = @@sql_mode;
set sql_mode = 'ANSI_QUOTES';
---replace_regex /.*RECORD LOCKS space id [0-9]* page no [0-9]* n bits [0-9]* // / trx id .*// /.*index .* in //
+--replace_regex /.*RECORD LOCKS space id [0-9]* page no [0-9]* n bits [0-9]* // / trx id .*// /.*index .* in // /trx table locks [0-9]* // /total table locks [0-9]* //
SHOW ENGINE InnoDB STATUS;
set @@sql_mode = @old_sql_mode;
--echo # con1
diff --git a/mysql-test/t/selectivity.test b/mysql-test/t/selectivity.test
index 77ee5f49bef..c46ff69295f 100644
--- a/mysql-test/t/selectivity.test
+++ b/mysql-test/t/selectivity.test
@@ -942,5 +942,34 @@ set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivit
drop table t0,t1,t2;
+--echo #
+--echo # Bug mdev-7316: a conjunct in WHERE with selectivity == 0
+--echo #
+
+CREATE TABLE t1 (a varchar(16), b int, PRIMARY KEY(a), KEY(b)) ENGINE=INNODB;
+INSERT INTO t1 VALUES
+ ('USAChinese',10), ('USAEnglish',20), ('USAFrench',30);
+
+CREATE TABLE t2 (i int) ENGINE=INNODB;
+INSERT INTO t2 VALUES
+ (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(1),(2),(3),(4);
+
+ANALYZE TABLE t1, t2;
+
+set use_stat_tables='preferably';
+set optimizer_use_condition_selectivity=3;
+
+EXPLAIN EXTENDED
+SELECT * FROM t1, t2
+ WHERE a <> 'USARussian' AND b IS NULL;
+
+SELECT * FROM t1, t2
+ WHERE a <> 'USARussian' AND b IS NULL;
+
+set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
+
+DROP TABLE t1,t2;
+
+
set use_stat_tables=@save_use_stat_tables;
diff --git a/mysql-test/t/selectivity_innodb.test b/mysql-test/t/selectivity_innodb.test
index 5674cb5c006..d6a77eac600 100644
--- a/mysql-test/t/selectivity_innodb.test
+++ b/mysql-test/t/selectivity_innodb.test
@@ -80,6 +80,36 @@ select * from t1 where col2 != true;
drop table t1;
--echo #
+--echo # MDEV-7413: optimizer_use_condition_selectivity > 2 crashes 10.0.15+maria-1~wheezy
+--echo #
+
+CREATE TABLE t1 (
+ parent_id int,
+ child_group_id int,
+ child_user_id int,
+ KEY (parent_id,child_group_id,child_user_id)
+) ENGINE=InnoDB;
+
+CREATE TABLE t2 (
+ id int,
+ lower_group_name varchar(255),
+ directory_id int(20),
+ UNIQUE KEY (directory_id)
+) ENGINE=InnoDB;
+
+CREATE TABLE t3 (id int) ENGINE=InnoDB;
+
+insert into t1 values (1,1,1),(2,2,2);
+insert into t2 values (10,'foo',10),(20,'bar',20);
+insert into t3 values (101),(102);
+set use_stat_tables = PREFERABLY, optimizer_use_condition_selectivity = 3;
+
+select * from t1, t2, t3
+where t1.child_user_id=t3.id and t1.child_group_id is null and t2.lower_group_name='foo' and t1.parent_id=t2.id and t2.directory_id=10;
+
+drop table t1,t2,t3;
+
+--echo #
--echo # End of 10.0 tests
--echo #
diff --git a/mysql-test/t/sp_notembedded.test b/mysql-test/t/sp_notembedded.test
index 42a3dd193c4..2a24ab3d005 100644
--- a/mysql-test/t/sp_notembedded.test
+++ b/mysql-test/t/sp_notembedded.test
@@ -462,6 +462,26 @@ DROP EVENT teste_bug11763507;
--echo # ------------------------------------------------------------------
#
+# A case of SHOW GRANTS
+# (creating a new procedure changes the password)
+#
+grant create routine on test.* to foo1@localhost identified by 'foo';
+update mysql.user set password = replace(password, '*', '-') where user='foo1';
+--connect (foo,localhost,foo1,foo)
+show grants;
+--connection default
+flush privileges;
+--connection foo
+show grants;
+create procedure spfoo() select 1;
+show grants;
+
+--connection default
+--disconnect foo
+drop procedure spfoo;
+drop user foo1@localhost;
+
+#
# Restore global concurrent_insert value. Keep in the end of the test file.
#
diff --git a/mysql-test/t/subselect_sj_mat.test b/mysql-test/t/subselect_sj_mat.test
index 912e9d5befd..c34c805f90c 100644
--- a/mysql-test/t/subselect_sj_mat.test
+++ b/mysql-test/t/subselect_sj_mat.test
@@ -1843,3 +1843,45 @@ drop database mysqltest4;
--echo # End of 5.5 tests
+--echo #
+--echo # MDEV-7220: Materialization strategy is not used for REPLACE ... SELECT
+--echo #
+create table t0(a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+
+create table t1 (a int, b int, c int);
+insert into t1
+select A.a+B.a*10+C.a*100, A.a+B.a*10+C.a*100, A.a+B.a*10+C.a*100
+from t0 A, t0 B, t0 C;
+
+create table t2 (a int, b int, c int);
+insert into t2 select A.a, A.a, A.a from t1 A;
+insert into t2 select * from t2;
+insert into t2 select * from t2;
+
+create table t3 as select * from t2 limit 1;
+
+--echo # The testcase only makes sense if the following uses Materialization:
+explain
+select * from t1 where (a,b) in (select max(a),b from t2 group by b);
+
+flush status;
+replace into t3
+select * from t1 where (a,b) in (select max(a),b from t2 group by b);
+--echo # Sequential reads:
+--echo # 1K is read from t1
+--echo # 4K is read from t2
+--echo # 1K groups is read from the tmp. table
+--echo #
+--echo # Lookups:
+--echo # 4K lookups in group by table
+--echo # 1K lookups in temp.table
+--echo #
+--echo # Writes:
+--echo # 2x 1K writes to temporary tables (grouping table and subquery materialization table
+--echo #
+--echo # The point is that neither counter should be in the millions (this
+--echo # will happen if Materialization is not used
+show status where Variable_name like 'Handler_read%' or Variable_name like 'Handler_%write%';
+
+drop table t0,t1,t2,t3;
diff --git a/mysql-test/t/table_keyinfo-6838.test b/mysql-test/t/table_keyinfo-6838.test
new file mode 100644
index 00000000000..5f4c9f44f86
--- /dev/null
+++ b/mysql-test/t/table_keyinfo-6838.test
@@ -0,0 +1,18 @@
+# Test case for MDEV-6838.
+# Due to incorrect key_length computation, this usecase failed with the error
+# Using too big key for internal temp table.
+
+CREATE TABLE t1 (i INT, state VARCHAR(997)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (2,'Louisiana'),(9,'Maine');
+
+CREATE TABLE t2 (state VARCHAR(997), j INT) ENGINE=MyISAM;
+INSERT INTO t2 VALUES ('Louisiana',9),('Alaska',5);
+INSERT INTO t2 SELECT t2.* FROM t2 JOIN t2 AS t3 JOIN t2 AS t4 JOIN t2 AS t5 JOIN t2 AS t6;
+
+SET @@max_heap_table_size= 16384;
+set @@optimizer_switch='derived_merge=OFF';
+set @@optimizer_switch='extended_keys=ON';
+
+SELECT * FROM t1 AS t1_1 LEFT JOIN ( t1 AS t1_2 INNER JOIN (SELECT * FROM t2) v2 ON t1_2.i = j ) ON t1_1.state = v2.state LIMIT 1;
+
+DROP TABLE t1, t2;
diff --git a/mysql-test/t/tmp_table_count-7586.test b/mysql-test/t/tmp_table_count-7586.test
new file mode 100644
index 00000000000..e7bac127815
--- /dev/null
+++ b/mysql-test/t/tmp_table_count-7586.test
@@ -0,0 +1,56 @@
+# MDEV-7586 regression test.
+# Test if created_tmp_tables status variable is correctly incremented.
+--source include/have_perfschema.inc
+--source include/not_embedded.inc
+
+create table t2 (a int);
+insert into t2 values (1),(2),(3);
+create view v2 as select a from t2;
+
+flush status;
+select * from v2;
+show status like '%Created_tmp%';
+
+explain select * from v2;
+
+select * from (select * from t2) T1;
+show status like '%Created_tmp%';
+
+explain select * from (select * from t2) T1;
+
+
+drop view v2;
+drop table t2;
+
+
+--disable_ps_protocol
+
+CREATE TABLE t1(a int);
+INSERT INTO t1 values(1),(2);
+CREATE TABLE t2(a int);
+INSERT INTO t2 values(1),(2);
+
+EXPLAIN SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a HAVING a > 1);
+truncate table performance_schema.events_statements_history_long;
+flush status;
+CREATE TABLE t3 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a HAVING a > 1);
+--echo # Performance schema should be the same as "Created_tmp_tables" variable below
+select sum(created_tmp_tables) from performance_schema.events_statements_history_long;
+show status like '%Created_tmp%';
+drop table t3;
+
+EXPLAIN SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a);
+truncate table performance_schema.events_statements_history_long;
+flush status;
+CREATE TABLE t3 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a);
+--echo # Performance schema should be the same as "Created_tmp_tables" variable below
+select sum(created_tmp_tables) from performance_schema.events_statements_history_long;
+show status like '%Created_tmp%';
+
+drop table t1,t2,t3;
+
+truncate table performance_schema.events_statements_history_long;
+flush status;
+--echo # Performance schema should be the same as "Created_tmp_tables" variable below
+select sum(created_tmp_tables) from performance_schema.events_statements_history_long;
+show status like '%Created_tmp%';
diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test
index ae78d5504cf..84d7da548b2 100644
--- a/mysql-test/t/view.test
+++ b/mysql-test/t/view.test
@@ -5345,6 +5345,28 @@ create view v1 as select 1;
drop view v1;
+--echo #
+--echo # MDEV-7260: Crash in get_best_combination when executing multi-table
+--echo # UPDATE with nested views
+--echo #
+
+CREATE TABLE `t1` (`id` bigint(20));
+
+INSERT INTO `t1` VALUES (1),(2);
+
+CREATE TABLE `t2` (`id` bigint(20));
+
+CREATE TABLE `t3` (`id` bigint(20), `flag` tinyint(4));
+
+create view v1 as select id from t1;
+
+create view v2 as select t2.* from (t2 left join v1 using (id));
+
+update t3 left join v2 using (id) set flag=flag+1;
+
+drop view v2, v1;
+drop table t1, t2, t3;
+
--echo # -----------------------------------------------------------------
--echo # -- End of 5.5 tests.
--echo # -----------------------------------------------------------------
diff --git a/mysql-test/t/view_alias.test b/mysql-test/t/view_alias.test
index b155ba6c2a9..09d707296bb 100644
--- a/mysql-test/t/view_alias.test
+++ b/mysql-test/t/view_alias.test
@@ -90,3 +90,12 @@ eval CREATE VIEW v1 AS $query;
DROP VIEW v1;
DROP TABLE t1, t2;
+
+#
+# MDEV-7482 VIEW containing INTERVAL(...)
+#
+create view v1 as select interval(55,10) as my_col;
+show create view v1;
+select * from v1;
+drop view v1;
+
diff --git a/mysys/my_default.c b/mysys/my_default.c
index e40e24fd5bc..0ce01960630 100644
--- a/mysys/my_default.c
+++ b/mysys/my_default.c
@@ -842,7 +842,7 @@ static int search_default_file_with_ext(Process_option_func opt_handler,
ptr, name, line)))
goto err;
- if (!(search_dir= my_dir(ptr, MYF(MY_WME))))
+ if (!(search_dir= my_dir(ptr, MYF(MY_WME | MY_WANT_SORT))))
goto err;
for (i= 0; i < (uint) search_dir->number_of_files; i++)
diff --git a/packaging/WiX/custom_ui.wxs b/packaging/WiX/custom_ui.wxs
index d49e4210b12..a28c3c9b8a1 100644
--- a/packaging/WiX/custom_ui.wxs
+++ b/packaging/WiX/custom_ui.wxs
@@ -2,7 +2,7 @@
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<!--
- Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -30,7 +30,7 @@
<Control Id="Back" Type="PushButton" X="156" Y="243" Width="56" Height="17" Text="!(loc.WixUIBack)" Disabled="yes" />
<Control Id="Description" Type="Text" X="135" Y="80" Width="220" Height="60" Transparent="yes" NoPrefix="yes" Text="!(loc.WelcomeDlgDescription)" />
<Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes" Text="!(loc.WelcomeDlgTitle)" />
- <Control Id="CopyrightText" Type="Text" X="135" Y="200" Width="220" Height="40" Transparent="yes" Text="Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved." />
+ <Control Id="CopyrightText" Type="Text" X="135" Y="200" Width="220" Height="40" Transparent="yes" Text="Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved." />
<Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="!(loc.WelcomeDlgBitmap)" />
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
</Dialog>
diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c
index 3ab14d94b1f..96b1f6a09e9 100644
--- a/plugin/server_audit/server_audit.c
+++ b/plugin/server_audit/server_audit.c
@@ -14,11 +14,10 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#define PLUGIN_VERSION 0x101
-#define PLUGIN_STR_VERSION "1.1.7"
+#define PLUGIN_VERSION 0x102
+#define PLUGIN_STR_VERSION "1.2.0"
#include <my_config.h>
-
#include <stdio.h>
#include <time.h>
#include <string.h>
@@ -152,6 +151,10 @@ static int my_strnncoll_binary(CHARSET_INFO * cs __attribute__((unused)),
#define flogger_mutex_lock(A) pthread_mutex_lock(mysql_mutex_real_mutex(A))
#define flogger_mutex_unlock(A) pthread_mutex_unlock(mysql_mutex_real_mutex(A))
+static char **int_mysql_data_home;
+static char *default_home= (char *)".";
+#define mysql_data_home (*int_mysql_data_home)
+
#include "../../mysys/file_logger.c"
#endif /*!MARIADB_ONLY*/
@@ -175,6 +178,7 @@ static int my_strnncoll_binary(CHARSET_INFO * cs __attribute__((unused)),
extern char server_version[];
static const char *serv_ver= NULL;
static int started_mysql= 0;
+static int started_mariadb= 0;
static int maria_above_5= 0;
static char *incl_users, *excl_users,
*file_path, *syslog_info;
@@ -232,11 +236,15 @@ static MYSQL_SYSVAR_STR(excl_users, excl_users, PLUGIN_VAR_RQCMDARG,
NULL, update_excl_users, NULL);
/* bits in the event filter. */
#define EVENT_CONNECT 1
-#define EVENT_QUERY 2
+#define EVENT_QUERY_ALL 2
+#define EVENT_QUERY 26
#define EVENT_TABLE 4
+#define EVENT_QUERY_DDL 8
+#define EVENT_QUERY_DML 16
+
static const char *event_names[]=
{
- "CONNECT", "QUERY", "TABLE",
+ "CONNECT", "QUERY", "TABLE", "QUERY_DDL", "QUERY_DML",
NULL
};
static TYPELIB events_typelib=
@@ -244,7 +252,7 @@ static TYPELIB events_typelib=
array_elements(event_names) - 1, "", event_names, NULL
};
static MYSQL_SYSVAR_SET(events, events, PLUGIN_VAR_RQCMDARG,
- "Specifies the set of events to monitor",
+ "Specifies the set of events to monitor. Can be CONNECT, QUERY, TABLE, QUERY_DDL, QUERY_DML.",
NULL, NULL, 0, &events_typelib);
#define OUTPUT_SYSLOG 0
#define OUTPUT_FILE 1
@@ -536,6 +544,103 @@ static int user_hash_fill(HASH *h, char *users,
}
+enum sa_keywords
+{
+ SQLCOM_NOTHING=0,
+ SQLCOM_DDL,
+ SQLCOM_DML,
+ SQLCOM_GRANT,
+ SQLCOM_CREATE_USER,
+ SQLCOM_CHANGE_MASTER,
+ SQLCOM_CREATE_SERVER,
+ SQLCOM_SET_OPTION,
+ SQLCOM_ALTER_SERVER,
+ SQLCOM_TRUNCATE,
+ SQLCOM_QUERY_ADMIN,
+ SQLCOM_DCL,
+};
+
+struct sa_keyword
+{
+ int length;
+ const char *wd;
+ struct sa_keyword *next;
+ enum sa_keywords type;
+};
+
+
+struct sa_keyword xml_word= {3, "XML", 0, SQLCOM_NOTHING};
+struct sa_keyword user_word= {4, "USER", 0, SQLCOM_NOTHING};
+struct sa_keyword data_word= {4, "DATA", 0, SQLCOM_NOTHING};
+struct sa_keyword server_word= {6, "SERVER", 0, SQLCOM_NOTHING};
+struct sa_keyword master_word= {6, "MASTER", 0, SQLCOM_NOTHING};
+struct sa_keyword password_word= {8, "PASSWORD", 0, SQLCOM_NOTHING};
+struct sa_keyword function_word= {8, "FUNCTION", 0, SQLCOM_NOTHING};
+struct sa_keyword statement_word= {9, "STATEMENT", 0, SQLCOM_NOTHING};
+struct sa_keyword procedure_word= {9, "PROCEDURE", 0, SQLCOM_NOTHING};
+
+
+struct sa_keyword keywords_to_skip[]=
+{
+ {3, "SET", &statement_word, SQLCOM_QUERY_ADMIN},
+ {0, NULL, 0, SQLCOM_DDL}
+};
+
+
+struct sa_keyword not_ddl_keywords[]=
+{
+ {4, "DROP", &function_word, SQLCOM_QUERY_ADMIN},
+ {4, "DROP", &procedure_word, SQLCOM_QUERY_ADMIN},
+ {4, "DROP", &user_word, SQLCOM_DCL},
+ {6, "CREATE", &user_word, SQLCOM_DCL},
+ {6, "CREATE", &function_word, SQLCOM_QUERY_ADMIN},
+ {6, "CREATE", &procedure_word, SQLCOM_QUERY_ADMIN},
+ {6, "RENAME", &user_word, SQLCOM_DCL},
+ {0, NULL, 0, SQLCOM_DDL}
+};
+
+
+struct sa_keyword ddl_keywords[]=
+{
+ {4, "DROP", 0, SQLCOM_DDL},
+ {5, "ALTER", 0, SQLCOM_DDL},
+ {6, "CREATE", 0, SQLCOM_DDL},
+ {6, "RENAME", 0, SQLCOM_DDL},
+ {8, "TRUNCATE", 0, SQLCOM_DDL},
+ {0, NULL, 0, SQLCOM_DDL}
+};
+
+
+struct sa_keyword dml_keywords[]=
+{
+ {2, "DO", 0, SQLCOM_DML},
+ {4, "CALL", 0, SQLCOM_DML},
+ {4, "LOAD", &data_word, SQLCOM_DML},
+ {4, "LOAD", &xml_word, SQLCOM_DML},
+ {6, "DELETE", 0, SQLCOM_DML},
+ {6, "INSERT", 0, SQLCOM_DML},
+ {6, "SELECT", 0, SQLCOM_DML},
+ {6, "UPDATE", 0, SQLCOM_DML},
+ {7, "HANDLER", 0, SQLCOM_DML},
+ {7, "REPLACE", 0, SQLCOM_DML},
+ {0, NULL, 0, SQLCOM_DML}
+};
+
+
+struct sa_keyword passwd_keywords[]=
+{
+ {3, "SET", &password_word, SQLCOM_SET_OPTION},
+ {5, "ALTER", &server_word, SQLCOM_ALTER_SERVER},
+ {5, "GRANT", 0, SQLCOM_GRANT},
+ {6, "CREATE", &user_word, SQLCOM_CREATE_USER},
+ {6, "CREATE", &server_word, SQLCOM_CREATE_SERVER},
+ {6, "CHANGE", &master_word, SQLCOM_CHANGE_MASTER},
+ {0, NULL, 0, SQLCOM_NOTHING}
+};
+
+#define MAX_KEYWORD 9
+
+
static void error_header()
{
struct tm tm_time;
@@ -573,6 +678,7 @@ struct connection_info
int log_always;
};
+
static HASH connection_hash;
@@ -783,6 +889,21 @@ static struct connection_info *
#define SAFE_STRLEN(s) (s ? strlen(s) : 0)
+static int is_space(char c)
+{
+ return c == ' ' || c == '\r' || c == '\n' || c == '\t';
+}
+
+
+#define SKIP_SPACES(str) \
+do { \
+ while (is_space(*str)) \
+ ++str; \
+} while(0)
+
+
+
+
static struct connection_info *
add_connection_initdb(const struct mysql_event_general *event)
{
@@ -990,6 +1111,98 @@ static size_t escape_string(const char *str, unsigned int len,
}
+static size_t escape_string_hide_passwords(const char *str, unsigned int len,
+ char *result, size_t result_len,
+ const char *word1, size_t word1_len,
+ const char *word2, size_t word2_len,
+ int next_text_string)
+{
+ const char *res_start= result;
+ const char *res_end= result + result_len - 2;
+ size_t d_len;
+ char b_char;
+
+ while (len)
+ {
+ if (len > word1_len + 1 && strncasecmp(str, word1, word1_len) == 0)
+ {
+ const char *next_s= str + word1_len;
+ size_t c;
+
+ if (next_text_string)
+ {
+ while (*next_s && *next_s != '\'' && *next_s != '"')
+ ++next_s;
+ }
+ else
+ {
+ if (word2)
+ {
+ SKIP_SPACES(next_s);
+ if (len < (next_s - str) + word2_len + 1 ||
+ strncasecmp(next_s, word2, word2_len) != 0)
+ goto no_password;
+ next_s+= word2_len;
+ }
+
+ while (*next_s && *next_s != '\'' && *next_s != '"')
+ ++next_s;
+ }
+
+ d_len= next_s - str;
+ if (result + d_len + 5 > res_end)
+ break;
+
+ for (c=0; c<d_len; c++)
+ result[c]= is_space(str[c]) ? ' ' : str[c];
+
+ memmove(result + d_len, "*****", 5);
+ result+= d_len + 5;
+ b_char= *(next_s++);
+ while (*next_s)
+ {
+ if (*next_s == b_char)
+ {
+ ++next_s;
+ break;
+ }
+ if (*next_s == '\\')
+ {
+ if (next_s[1])
+ next_s++;
+ }
+ next_s++;
+ }
+ len-= next_s - str;
+ str= next_s;
+ continue;
+ }
+no_password:
+ if (result >= res_end)
+ break;
+ if (*str == '\'')
+ {
+ *(result++)= '\\';
+ *(result++)= '\'';
+ }
+ else if (*str == '\\')
+ {
+ *(result++)= '\\';
+ *(result++)= '\\';
+ }
+ else if (is_space(*str))
+ *(result++)= ' ';
+ else
+ *(result++)= *str;
+ str++;
+ len--;
+ }
+ *result= 0;
+ return result - res_start;
+}
+
+
+
static int do_log_user(const char *name)
{
size_t len;
@@ -1008,6 +1221,96 @@ static int do_log_user(const char *name)
}
+static int get_next_word(const char *query, char *word)
+{
+ int len= 0;
+ char c;
+ while ((c= query[len]))
+ {
+ if (c >= 'a' && c <= 'z')
+ word[len]= 'A' + (c-'a');
+ else if (c >= 'A' && c <= 'Z')
+ word[len]= c;
+ else
+ break;
+
+ if (len++ == MAX_KEYWORD)
+ return 0;
+ }
+ word[len]= 0;
+ return len;
+}
+
+
+static int filter_query_type(const char *query, struct sa_keyword *kwd)
+{
+ int qwe_in_list;
+ char fword[MAX_KEYWORD + 1], nword[MAX_KEYWORD + 1];
+ int len, nlen= 0;
+ const struct sa_keyword *l_keywords;
+
+ while (*query && (is_space(*query) || *query == '(' || *query == '/'))
+ {
+ /* comment handling */
+ if (*query == '/' && query[1] == '*')
+ {
+ if (query[2] == '!')
+ {
+ query+= 3;
+ while (*query >= '0' && *query <= '9')
+ query++;
+ continue;
+ }
+ query+= 2;
+ while (*query)
+ {
+ if (*query=='*' && query[1] == '/')
+ {
+ query+= 2;
+ break;
+ }
+ query++;
+ }
+ continue;
+ }
+ query++;
+ }
+
+ qwe_in_list= 0;
+ if (!(len= get_next_word(query, fword)))
+ goto not_in_list;
+ query+= len+1;
+
+ l_keywords= kwd;
+ while (l_keywords->length)
+ {
+ if (l_keywords->length == len && strncmp(l_keywords->wd, fword, len) == 0)
+ {
+ if (l_keywords->next)
+ {
+ if (nlen == 0)
+ {
+ while (*query && is_space(*query))
+ query++;
+ nlen= get_next_word(query, nword);
+ }
+ if (l_keywords->next->length != nlen ||
+ strncmp(l_keywords->next->wd, nword, nlen) != 0)
+ goto do_loop;
+ }
+
+ qwe_in_list= l_keywords->type;
+ break;
+ };
+do_loop:
+ l_keywords++;
+ }
+
+not_in_list:
+ return qwe_in_list;
+}
+
+
static int log_statement_ex(const struct connection_info *cn,
time_t ev_time, unsigned long thd_id,
const char *query, unsigned int query_len,
@@ -1044,10 +1347,77 @@ static int log_statement_ex(const struct connection_info *cn,
/* Can happen after the error in mysqld_prepare_stmt() */
query= cn->query;
query_len= cn->query_length;
+ if (query == 0 || query_len == 0)
+ return 0;
+ }
+
+ if (query && !(events & EVENT_QUERY_ALL) &&
+ (events & EVENT_QUERY))
+ {
+ const char *orig_query= query;
+
+ if (filter_query_type(query, keywords_to_skip))
+ {
+ char fword[MAX_KEYWORD + 1];
+ int len;
+ do
+ {
+ len= get_next_word(query, fword);
+ query+= len ? len : 1;
+ if (len == 3 && strncmp(fword, "FOR", 3) == 0)
+ break;
+ } while (*query);
+
+ if (*query == 0)
+ return 0;
+ }
+
+ if (events & EVENT_QUERY_DDL)
+ {
+ if (!filter_query_type(query, not_ddl_keywords) &&
+ filter_query_type(query, ddl_keywords))
+ goto do_log_query;
+ }
+ if (events & EVENT_QUERY_DML)
+ {
+ if (filter_query_type(query, dml_keywords))
+ goto do_log_query;
+ }
+
+ return 0;
+do_log_query:
+ query= orig_query;
}
- esc_q_len= escape_string(query, query_len,
- uh_buffer, sizeof(uh_buffer));
+ switch (filter_query_type(query, passwd_keywords))
+ {
+ case SQLCOM_GRANT:
+ case SQLCOM_CREATE_USER:
+ esc_q_len= escape_string_hide_passwords(query, query_len,
+ uh_buffer, sizeof(uh_buffer),
+ "IDENTIFIED", 10, "BY", 2, 0);
+ break;
+ case SQLCOM_CHANGE_MASTER:
+ esc_q_len= escape_string_hide_passwords(query, query_len,
+ uh_buffer, sizeof(uh_buffer),
+ "MASTER_PASSWORD", 15, "=", 1, 0);
+ break;
+ case SQLCOM_CREATE_SERVER:
+ case SQLCOM_ALTER_SERVER:
+ esc_q_len= escape_string_hide_passwords(query, query_len,
+ uh_buffer, sizeof(uh_buffer),
+ "PASSWORD", 8, NULL, 0, 0);
+ break;
+ case SQLCOM_SET_OPTION:
+ esc_q_len= escape_string_hide_passwords(query, query_len,
+ uh_buffer, sizeof(uh_buffer),
+ "=", 1, NULL, 0, 1);
+ break;
+ default:
+ esc_q_len= escape_string(query, query_len,
+ uh_buffer, sizeof(uh_buffer));
+ break;
+ }
csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize,
",\'%.*s\',%d", esc_q_len, uh_buffer, error_code);
message[csize]= '\n';
@@ -1396,6 +1766,105 @@ exit_func:
}
+#ifdef DBUG_OFF
+ #ifdef __x86_64__
+static const int cmd_off= 4200;
+static const int db_off= 120;
+static const int db_len_off= 128;
+ #else
+static const int cmd_off= 2668;
+static const int db_off= 60;
+static const int db_len_off= 64;
+ #endif /*x86_64*/
+#else
+ #ifdef __x86_64__
+static const int cmd_off= 4432;
+static const int db_off= 120;
+static const int db_len_off= 128;
+ #else
+static const int cmd_off= 2808;
+static const int db_off= 64;
+static const int db_len_off= 68;
+ #endif /*x86_64*/
+#endif /*DBUG_OFF*/
+
+struct mysql_event_general_v8
+{
+ unsigned int event_class;
+ unsigned int event_subclass;
+ int general_error_code;
+ unsigned long general_thread_id;
+ const char *general_user;
+ unsigned int general_user_length;
+ const char *general_command;
+ unsigned int general_command_length;
+ const char *general_query;
+ unsigned int general_query_length;
+ struct charset_info_st *general_charset;
+ unsigned long long general_time;
+ unsigned long long general_rows;
+};
+
+static void auditing_v8(MYSQL_THD thd, struct mysql_event_general_v8 *ev_v8)
+{
+ struct mysql_event_general event;
+
+ if (ev_v8->event_class != MYSQL_AUDIT_GENERAL_CLASS)
+ return;
+
+ event.event_subclass= ev_v8->event_subclass;
+ event.general_error_code= ev_v8->general_error_code;
+ event.general_thread_id= ev_v8->general_thread_id;
+ event.general_user= ev_v8->general_user;
+ event.general_user_length= ev_v8->general_user_length;
+ event.general_command= ev_v8->general_command;
+ event.general_command_length= ev_v8->general_command_length;
+ event.general_query= ev_v8->general_query;
+ event.general_query_length= ev_v8->general_query_length;
+ event.general_charset= ev_v8->general_charset;
+ event.general_time= ev_v8->general_time;
+ event.general_rows= ev_v8->general_rows;
+ event.database= 0;
+ event.database_length= 0;
+
+ if (event.general_query_length > 0)
+ {
+ event.event_subclass= MYSQL_AUDIT_GENERAL_STATUS;
+ event.general_command= "Query";
+ event.general_command_length= 5;
+#ifdef __linux__
+ event.database= *(char **) (((char *) thd) + db_off);
+ event.database_length= *(size_t *) (((char *) thd) + db_len_off);
+#endif /*__linux*/
+ }
+#ifdef __linux__
+ else if (*((int *) (((char *)thd) + cmd_off)) == 2)
+ {
+ event.event_subclass= MYSQL_AUDIT_GENERAL_LOG;
+ event.general_command= "Init DB";
+ event.general_command_length= 7;
+ event.general_query= *(char **) (((char *) thd) + db_off);
+ event.general_query_length= *(size_t *) (((char *) thd) + db_len_off);
+ }
+#endif /*__linux*/
+ auditing(thd, ev_v8->event_class, &event);
+}
+
+
+static void auditing_v13(MYSQL_THD thd, unsigned int *ev_v0)
+{
+ struct mysql_event_general event= *(const struct mysql_event_general *) (ev_v0+1);
+
+ if (event.general_query_length > 0)
+ {
+ event.event_subclass= MYSQL_AUDIT_GENERAL_STATUS;
+ event.general_command= "Query";
+ event.general_command_length= 5;
+ }
+ auditing(thd, ev_v0[0], &event);
+}
+
+
/*
As it's just too difficult to #include "sql_class.h",
let's just copy the necessary part of the system_variables
@@ -1471,15 +1940,19 @@ typedef struct loc_system_variables
ulong query_cache_type;
} LOC_SV;
+
static int server_audit_init(void *p __attribute__((unused)))
{
const void *my_hash_init_ptr;
+
+ if (!serv_ver)
+ {
#ifdef _WIN32
- serv_ver= (const char *) GetProcAddress(0, "server_version");
+ serv_ver= (const char *) GetProcAddress(0, "server_version");
#else
- serv_ver= server_version;
+ serv_ver= server_version;
#endif /*_WIN32*/
-
+ }
my_hash_init_ptr= dlsym(RTLD_DEFAULT, "_my_hash_init");
if (!my_hash_init_ptr)
{
@@ -1487,8 +1960,14 @@ static int server_audit_init(void *p __attribute__((unused)))
my_hash_init_ptr= dlsym(RTLD_DEFAULT, "my_hash_init2");
}
+ if(!(int_mysql_data_home= dlsym(RTLD_DEFAULT, "mysql_data_home")))
+ {
+ if(!(int_mysql_data_home= dlsym(RTLD_DEFAULT, "?mysql_data_home@@3PADA")))
+ int_mysql_data_home= &default_home;
+ }
+
if (!serv_ver || !my_hash_init_ptr)
- return 0;
+ return 1;
if (!started_mysql)
{
@@ -1499,7 +1978,6 @@ static int server_audit_init(void *p __attribute__((unused)))
}
}
-
if (gethostname(servhost, sizeof(servhost)))
strcpy(servhost, "unknown");
@@ -1618,8 +2096,8 @@ mysql_declare_plugin(server_audit)
MYSQL_AUDIT_PLUGIN,
&mysql_descriptor,
"SERVER_AUDIT",
- " Alexey Botchkov (MariaDB)",
- "Audit the server activity.",
+ " Alexey Botchkov (MariaDB Corporation)",
+ "Audit the server activity",
PLUGIN_LICENSE_GPL,
server_audit_init_mysql,
server_audit_deinit,
@@ -1646,8 +2124,8 @@ maria_declare_plugin(server_audit)
MYSQL_AUDIT_PLUGIN,
&maria_descriptor,
"SERVER_AUDIT",
- "Alexey Botchkov (MariaDB)",
- "Audit the server activity.",
+ "Alexey Botchkov (MariaDB Corporation)",
+ "Audit the server activity",
PLUGIN_LICENSE_GPL,
server_audit_init,
server_audit_deinit,
@@ -1925,3 +2403,48 @@ static void update_syslog_ident(MYSQL_THD thd __attribute__((unused)),
}
+#ifdef _WIN32
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ if (fdwReason != DLL_PROCESS_ATTACH)
+ return 1;
+
+ serv_ver= (const char *) GetProcAddress(0, "server_version");
+#else
+void __attribute__ ((constructor)) audit_plugin_so_init(void)
+{
+ serv_ver= server_version;
+#endif /*_WIN32*/
+
+ if (!serv_ver)
+ goto exit;
+
+ started_mariadb= strstr(serv_ver, "MariaDB") != 0;
+
+ if (!started_mariadb)
+ {
+ if (serv_ver[0] == '5' && serv_ver[2] == '5')
+ {
+ int sc= serv_ver[4] - '0';
+ if (serv_ver[5] >= '0' && serv_ver[5] <= '9')
+ sc= sc * 10 + serv_ver[5] - '0';
+ if (sc <= 10)
+ {
+ mysql_descriptor.interface_version= 0x0200;
+ mysql_descriptor.event_notify= (void *) auditing_v8;
+ }
+ else if (sc < 14)
+ {
+ mysql_descriptor.interface_version= 0x0200;
+ mysql_descriptor.event_notify= (void *) auditing_v13;
+ }
+ }
+ }
+exit:
+#ifdef _WIN32
+ return 1;
+#else
+ return;
+#endif
+}
+
diff --git a/scripts/mysql_install_db.pl.in b/scripts/mysql_install_db.pl.in
index bfb910278b2..4d3641397d0 100644
--- a/scripts/mysql_install_db.pl.in
+++ b/scripts/mysql_install_db.pl.in
@@ -65,8 +65,8 @@ Usage: $0 [OPTIONS]
Read this file after the global files are read.
--defaults-file=name Only read default options from the given file name.
--force Causes mysql_install_db to run even if DNS does not
- work. In that case, grant table entries that normally
- use hostnames will use IP addresses.
+ work. In that case, grant table entries that
+ normally use hostnames will use IP addresses.
--help Display this help and exit.
--ldata=path The path to the MySQL data directory. Same as --datadir.
--no-defaults Don't read default options from any option file.
diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh
index 1bdfb10863e..cce9623962d 100644
--- a/scripts/mysql_install_db.sh
+++ b/scripts/mysql_install_db.sh
@@ -50,8 +50,8 @@ Usage: $0 [OPTIONS]
Read this file after the global files are read.
--defaults-file=name Only read default options from the given file name.
--force Causes mysql_install_db to run even if DNS does not
- work. In that case, grant table entries that normally
- use hostnames will use IP addresses.
+ work. In that case, grant table entries that
+ normally use hostnames will use IP addresses.
--help Display this help and exit.
--ldata=path The path to the MariaDB data directory. Same as
--datadir.
diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh
index f9fd1339c19..6424edc43c0 100644
--- a/scripts/mysqld_safe.sh
+++ b/scripts/mysqld_safe.sh
@@ -28,6 +28,7 @@ syslog_tag=
user='@MYSQLD_USER@'
pid_file=
err_log=
+err_log_base=
syslog_tag_mysqld=mysqld
syslog_tag_mysqld_safe=mysqld_safe
@@ -285,7 +286,7 @@ parse_arguments() {
--user=*) user="$val"; SET_USER=1 ;;
--log[-_]basename=*|--hostname=*|--loose[-_]log[-_]basename=*)
pid_file="$val.pid";
- err_log="$val.err";
+ err_log_base="$val";
;;
# these might have been set in a [mysqld_safe] section of my.cnf
@@ -661,7 +662,16 @@ then
* ) err_log="$DATADIR/$err_log" ;;
esac
else
- err_log=$DATADIR/`@HOSTNAME@`.err
+ if [ -n "$err_log_base" ]
+ then
+ err_log=$err_log_base.err
+ case "$err_log" in
+ /* ) ;;
+ * ) err_log="$DATADIR/$err_log" ;;
+ esac
+ else
+ err_log=$DATADIR/`@HOSTNAME@`.err
+ fi
fi
append_arg_to_args "--log-error=$err_log"
diff --git a/sql-common/client.c b/sql-common/client.c
index e53a125e4f5..8d03ffef534 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -1,5 +1,5 @@
-/* Copyright (c) 2003, 2013, Oracle and/or its affiliates.
- Copyright (c) 2009, 2013, Monty Program Ab
+/* Copyright (c) 2003, 2014, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2015, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index c78fa73bb51..9a2ab3c72c8 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Copyright (c) 2006, 2013, Oracle and/or its affiliates.
+# Copyright (c) 2006, 2014, Oracle and/or its affiliates.
+# Copyright (c) 2010, 2015, MariaDB
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -287,14 +288,15 @@ IF(WIN32 OR HAVE_DLOPEN AND NOT DISABLE_SHARED)
ENDIF()
FOREACH(tool glibtoolize libtoolize aclocal autoconf autoheader automake gtar
- tar bzr git)
+ tar git)
STRING(TOUPPER ${tool} TOOL)
FIND_PROGRAM(${TOOL}_EXECUTABLE ${tool} DOC "path to the executable")
MARK_AS_ADVANCED(${TOOL}_EXECUTABLE)
ENDFOREACH()
CONFIGURE_FILE(
- ${CMAKE_SOURCE_DIR}/cmake/make_dist.cmake.in ${CMAKE_BINARY_DIR}/make_dist.cmake @ONLY)
+ ${CMAKE_SOURCE_DIR}/cmake/make_dist.cmake.in
+ ${CMAKE_BINARY_DIR}/make_dist.cmake @ONLY)
ADD_CUSTOM_TARGET(dist
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/make_dist.cmake
diff --git a/sql/handler.cc b/sql/handler.cc
index 7c70babfea8..12d7ffb2f5e 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1476,7 +1476,13 @@ done:
/* Come here if error and we need to rollback. */
err:
error= 1; /* Transaction was rolled back */
- ha_rollback_trans(thd, all);
+ /*
+ In parallel replication, rollback is delayed, as there is extra replication
+ book-keeping to be done before rolling back and allowing a conflicting
+ transaction to continue (MDEV-7458).
+ */
+ if (!(thd->rgi_slave && thd->rgi_slave->is_parallel_exec))
+ ha_rollback_trans(thd, all);
end:
if (rw_trans && mdl_request.ticket)
diff --git a/sql/item.h b/sql/item.h
index baa6bf51728..4a57be8e9ce 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -2869,8 +2869,9 @@ public:
{
set_cs_specified(true);
}
- Item_string_with_introducer(const String *str, CHARSET_INFO *tocs)
- :Item_string(str->ptr(), str->length(), tocs)
+ Item_string_with_introducer(const char *name,
+ const char *str, uint length, CHARSET_INFO *tocs)
+ :Item_string(name, str, length, tocs)
{
set_cs_specified(true);
}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 9d0f2e62e5c..65b2c6148d4 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -734,6 +734,11 @@ public:
void fix_length_and_dec();
const char *func_name() const { return "interval"; }
uint decimal_precision() const { return 2; }
+ void print(String *str, enum_query_type query_type)
+ {
+ str->append(func_name());
+ print_args(str, 0, query_type);
+ }
};
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 92b20fbb15f..85a5f7c7ced 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2014, Oracle and/or its affiliates.
- Copyright (c) 2009, 2014, SkySQL Ab.
+ Copyright (c) 2009, 2015, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -3672,8 +3672,12 @@ bool udf_handler::get_arguments()
{
f_args.args[i]= (char*) res->ptr();
f_args.lengths[i]= res->length();
- break;
}
+ else
+ {
+ f_args.lengths[i]= 0;
+ }
+ break;
}
case INT_RESULT:
*((longlong*) to) = args[i]->val_int();
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index 3e5856f6cb0..e67ab9115e9 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -1793,6 +1793,13 @@ String *Item_func_buffer::val_str(String *str_value)
if (dist > 0.0)
mbr.buffer(dist);
+ else
+ {
+ /* This happens when dist is too far negative. */
+ if (mbr.xmax + dist < mbr.xmin || mbr.ymax + dist < mbr.ymin)
+ goto return_empty_result;
+ }
+
collector.set_extent(mbr.xmin, mbr.xmax, mbr.ymin, mbr.ymax);
/*
If the distance given is 0, the Buffer function is in fact NOOP,
@@ -1820,6 +1827,7 @@ String *Item_func_buffer::val_str(String *str_value)
goto mem_error;
+return_empty_result:
str_value->set_charset(&my_charset_bin);
if (str_value->reserve(SRID_SIZE, 512))
goto mem_error;
diff --git a/sql/log.cc b/sql/log.cc
index adb15f31198..94536e49145 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -5728,6 +5728,14 @@ end:
}
+/*
+ Initialize the binlog state from the master-bin.state file, at server startup.
+
+ Returns:
+ 0 for success.
+ 2 for when .state file did not exist.
+ 1 for other error.
+*/
int
MYSQL_BIN_LOG::read_state_from_file()
{
@@ -5755,7 +5763,7 @@ MYSQL_BIN_LOG::read_state_from_file()
with GTID enabled. So initialize to empty state.
*/
rpl_global_gtid_binlog_state.reset();
- err= 0;
+ err= 2;
goto end;
}
}
@@ -7490,6 +7498,8 @@ MYSQL_BIN_LOG::trx_group_commit_leader(group_commit_entry *leader)
my_error(ER_ERROR_ON_WRITE, MYF(ME_NOREFRESH), name, errno);
check_purge= false;
}
+ /* In case of binlog rotate, update the correct current binlog offset. */
+ commit_offset= my_b_write_tell(&log_file);
}
DEBUG_SYNC(leader->thd, "commit_before_get_LOCK_after_binlog_sync");
@@ -9649,7 +9659,17 @@ MYSQL_BIN_LOG::do_binlog_recovery(const char *opt_name, bool do_xa_recovery)
if (error != LOG_INFO_EOF)
sql_print_error("find_log_pos() failed (error: %d)", error);
else
+ {
error= read_state_from_file();
+ if (error == 2)
+ {
+ /*
+ No binlog files and no binlog state is not an error (eg. just initial
+ server start after fresh installation).
+ */
+ error= 0;
+ }
+ }
return error;
}
@@ -9675,15 +9695,42 @@ MYSQL_BIN_LOG::do_binlog_recovery(const char *opt_name, bool do_xa_recovery)
if ((ev= Log_event::read_log_event(&log, 0, &fdle,
opt_master_verify_checksum)) &&
- ev->get_type_code() == FORMAT_DESCRIPTION_EVENT &&
- ev->flags & LOG_EVENT_BINLOG_IN_USE_F)
+ ev->get_type_code() == FORMAT_DESCRIPTION_EVENT)
{
- sql_print_information("Recovering after a crash using %s", opt_name);
- error= recover(&log_info, log_name, &log,
- (Format_description_log_event *)ev, do_xa_recovery);
+ if (ev->flags & LOG_EVENT_BINLOG_IN_USE_F)
+ {
+ sql_print_information("Recovering after a crash using %s", opt_name);
+ error= recover(&log_info, log_name, &log,
+ (Format_description_log_event *)ev, do_xa_recovery);
+ }
+ else
+ {
+ error= read_state_from_file();
+ if (error == 2)
+ {
+ /*
+ The binlog exists, but the .state file is missing. This is normal if
+ this is the first master start after a major upgrade to 10.0 (with
+ GTID support).
+
+ However, it could also be that the .state file was lost somehow, and
+ in this case it could be a serious issue, as we would set the wrong
+ binlog state in the next binlog file to be created, and GTID
+ processing would be corrupted. A common way would be copying files
+ from an old server to a new one and forgetting the .state file.
+
+ So in this case, we want to try to recover the binlog state by
+ scanning the last binlog file (but we do not need any XA recovery).
+
+ ToDo: We could avoid one scan at first start after major upgrade, by
+ detecting that there is no GTID_LIST event at the start of the
+ binlog file, and stopping the scan in that case.
+ */
+ error= recover(&log_info, log_name, &log,
+ (Format_description_log_event *)ev, false);
+ }
+ }
}
- else
- error= read_state_from_file();
delete ev;
end_io_cache(&log);
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 4a7b1e221c9..e66096aa39c 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -52,6 +52,8 @@
#define my_b_write_string(A, B) my_b_write((A), (B), (uint) (sizeof(B) - 1))
+using std::max;
+
/**
BINLOG_CHECKSUM variable.
*/
@@ -1315,9 +1317,10 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet,
}
data_len= uint4korr(buf + EVENT_LEN_OFFSET);
if (data_len < LOG_EVENT_MINIMAL_HEADER_LEN ||
- data_len > current_thd->variables.max_allowed_packet)
+ data_len > max(current_thd->variables.max_allowed_packet,
+ opt_binlog_rows_event_max_size + MAX_LOG_EVENT_HEADER))
{
- DBUG_PRINT("error",("data_len: %ld", data_len));
+ DBUG_PRINT("error",("data_len: %lu", data_len));
result= ((data_len < LOG_EVENT_MINIMAL_HEADER_LEN) ? LOG_READ_BOGUS :
LOG_READ_TOO_LARGE);
goto end;
@@ -1438,7 +1441,7 @@ failed my_b_read"));
*/
DBUG_RETURN(0);
}
- uint data_len = uint4korr(head + EVENT_LEN_OFFSET);
+ ulong data_len = uint4korr(head + EVENT_LEN_OFFSET);
char *buf= 0;
const char *error= 0;
Log_event *res= 0;
@@ -1447,7 +1450,8 @@ failed my_b_read"));
uint max_allowed_packet= thd ? slave_max_allowed_packet:~(uint)0;
#endif
- if (data_len > max_allowed_packet)
+ if (data_len > max<ulong>(max_allowed_packet,
+ opt_binlog_rows_event_max_size + MAX_LOG_EVENT_HEADER))
{
error = "Event too big";
goto err;
@@ -1481,7 +1485,7 @@ err:
{
DBUG_ASSERT(error != 0);
sql_print_error("Error in Log_event::read_log_event(): "
- "'%s', data_len: %d, event_type: %d",
+ "'%s', data_len: %lu, event_type: %d",
error,data_len,(uchar)(head[EVENT_TYPE_OFFSET]));
my_free(buf);
/*
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 6503d110032..e26937441d1 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -513,8 +513,6 @@ bool is_materialization_applicable(THD *thd, Item_in_subselect *in_subs,
Subquery !contains {GROUP BY, ORDER BY [LIMIT],
aggregate functions}) && subquery predicate is not under "NOT IN"))
- (*) The subquery must be part of a SELECT or CREATE TABLE ... SELECT statement.
- The current condition also excludes multi-table update statements.
A note about prepared statements: we want the if-branch to be taken on
PREPARE and each EXECUTE. The rewrites are only done once, but we need
select_lex->sj_subselects list to be populated for every EXECUTE.
@@ -523,9 +521,7 @@ bool is_materialization_applicable(THD *thd, Item_in_subselect *in_subs,
if (optimizer_flag(thd, OPTIMIZER_SWITCH_MATERIALIZATION) && // 0
!child_select->is_part_of_union() && // 1
parent_unit->first_select()->leaf_tables.elements && // 2
- (thd->lex->sql_command == SQLCOM_SELECT || // *
- thd->lex->sql_command == SQLCOM_CREATE_TABLE) && // *
- child_select->outer_select()->leaf_tables.elements && // 2A
+ child_select->outer_select()->leaf_tables.elements && // 2A
subquery_types_allow_materialization(in_subs) &&
(in_subs->is_top_level_item() || //3
optimizer_flag(thd,
@@ -3894,7 +3890,6 @@ SJ_TMP_TABLE::create_sj_weedout_tmp_table(THD *thd)
/*
STEP 1: Get temporary table name
*/
- thd->inc_status_created_tmp_tables();
if (use_temp_pool && !(test_flags & TEST_KEEP_TMP_TABLES))
temp_pool_slot = bitmap_lock_set_next(&temp_pool);
diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc
index 756dafdf534..5a81db45551 100644
--- a/sql/rpl_parallel.cc
+++ b/sql/rpl_parallel.cc
@@ -688,7 +688,7 @@ handle_rpl_parallel_thread(void *arg)
}
DBUG_ASSERT(qev->typ==rpl_parallel_thread::queued_event::QUEUED_EVENT);
- thd->rgi_slave= group_rgi= rgi;
+ thd->rgi_slave= rgi;
gco= rgi->gco;
/* Handle a new event group, which will be initiated by a GTID event. */
if ((event_type= qev->ev->get_type_code()) == GTID_EVENT)
@@ -705,6 +705,21 @@ handle_rpl_parallel_thread(void *arg)
}
});
+ if(unlikely(thd->wait_for_commit_ptr) && group_rgi != NULL)
+ {
+ /*
+ This indicates that we get a new GTID event in the middle of
+ a not completed event group. This is corrupt binlog (the master
+ will never write such binlog), so it does not happen unless
+ someone tries to inject wrong crafted binlog, but let us still
+ try to handle it somewhat nicely.
+ */
+ group_rgi->cleanup_context(thd, true);
+ finish_event_group(rpt, group_rgi->gtid_sub_id,
+ group_rgi->parallel_entry, group_rgi);
+ rpt->loc_free_rgi(group_rgi);
+ }
+
thd->tx_isolation= (enum_tx_isolation)thd->variables.tx_isolation;
in_event_group= true;
/*
@@ -791,19 +806,6 @@ handle_rpl_parallel_thread(void *arg)
unlock_or_exit_cond(thd, &entry->LOCK_parallel_entry,
&did_enter_cond, &old_stage);
- if(thd->wait_for_commit_ptr)
- {
- /*
- This indicates that we get a new GTID event in the middle of
- a not completed event group. This is corrupt binlog (the master
- will never write such binlog), so it does not happen unless
- someone tries to inject wrong crafted binlog, but let us still
- try to handle it somewhat nicely.
- */
- rgi->cleanup_context(thd, true);
- thd->wait_for_commit_ptr->unregister_wait_for_prior_commit();
- thd->wait_for_commit_ptr->wakeup_subsequent_commits(rgi->worker_error);
- }
thd->wait_for_commit_ptr= &rgi->commit_orderer;
if (opt_gtid_ignore_duplicates)
@@ -841,6 +843,7 @@ handle_rpl_parallel_thread(void *arg)
}
}
+ group_rgi= rgi;
group_ending= is_group_ending(qev->ev, event_type);
if (group_ending && likely(!rgi->worker_error))
{
diff --git a/sql/slave.cc b/sql/slave.cc
index af441815169..2a852745470 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -372,6 +372,9 @@ int init_slave()
if (run_slave_init_thread())
return 1;
+ if (global_rpl_thread_pool.init(opt_slave_parallel_threads))
+ return 1;
+
/*
This is called when mysqld starts. Before client connections are
accepted. However bootstrap may conflict with us if it does START SLAVE.
@@ -405,9 +408,6 @@ int init_slave()
goto err;
}
- if (global_rpl_thread_pool.init(opt_slave_parallel_threads))
- return 1;
-
/*
If --slave-skip-errors=... was not used, the string value for the
system variable has not been set up yet. Do it now.
@@ -5722,6 +5722,18 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
}
break;
+#ifndef DBUG_OFF
+ case XID_EVENT:
+ DBUG_EXECUTE_IF("slave_discard_xid_for_gtid_0_x_1000",
+ {
+ /* Inject an event group that is missing its XID commit event. */
+ if (mi->last_queued_gtid.domain_id == 0 &&
+ mi->last_queued_gtid.seq_no == 1000)
+ goto skip_relay_logging;
+ });
+ /* Fall through to default case ... */
+#endif
+
default:
default_action:
DBUG_EXECUTE_IF("kill_slave_io_after_2_events",
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 1ee443cfb83..aaa12763cec 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -10079,7 +10079,6 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
List<LEX_USER> user_list;
bool result;
ACL_USER *au;
- char passwd_buff[SCRAMBLED_PASSWORD_CHAR_LENGTH+1];
Dummy_error_handler error_handler;
DBUG_ENTER("sp_grant_privileges");
@@ -10120,33 +10119,10 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
if(au)
{
- if (au->salt_len)
- {
- if (au->salt_len == SCRAMBLE_LENGTH)
- {
- make_password_from_salt(passwd_buff, au->salt);
- combo->auth.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
- }
- else if (au->salt_len == SCRAMBLE_LENGTH_323)
- {
- make_password_from_salt_323(passwd_buff, (ulong *) au->salt);
- combo->auth.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
- }
- else
- {
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_PASSWD_LENGTH,
- ER(ER_PASSWD_LENGTH), SCRAMBLED_PASSWORD_CHAR_LENGTH);
- return TRUE;
- }
- combo->auth.str= passwd_buff;
- }
-
if (au->plugin.str != native_password_plugin_name.str &&
au->plugin.str != old_password_plugin_name.str)
- {
combo->plugin= au->plugin;
- combo->auth= au->auth_string;
- }
+ combo->auth= au->auth_string;
}
if (user_list.push_back(combo))
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index a5d7881707c..4d22f7f88d3 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1478,6 +1478,9 @@ unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list,
bool check_alias)
{
TABLE_LIST *dup;
+
+ table= table->find_table_for_update();
+
if (table->table && table->table->file->ht->db_type == DB_TYPE_MRG_MYISAM)
{
TABLE_LIST *child;
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 24814497600..475afa882f8 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -1,6 +1,6 @@
/*
- Copyright (c) 2000, 2013, Oracle and/or its affiliates.
- Copyright (c) 2009, 2013, Monty Program Ab.
+ Copyright (c) 2000, 2014, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2015, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -977,7 +977,7 @@ update_binlog:
if (!(query= (char*) thd->alloc(MAX_DROP_TABLE_Q_LEN)))
goto exit; /* not much else we can do */
- query_pos= query_data_start= strmov(query,"DROP TABLE ");
+ query_pos= query_data_start= strmov(query,"DROP TABLE IF EXISTS ");
query_end= query + MAX_DROP_TABLE_Q_LEN;
db_len= strlen(db);
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index e16aade6bcb..8fd9b0b2ada 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -922,9 +922,10 @@ multi_delete::initialize_tables(JOIN *join)
delete_while_scanning= 1;
for (walk= delete_tables; walk; walk= walk->next_local)
{
- tables_to_delete_from|= walk->table->map;
+ TABLE_LIST *tbl= walk->correspondent_table->find_table_for_update();
+ tables_to_delete_from|= tbl->table->map;
if (delete_while_scanning &&
- unique_table(thd, walk, join->tables_list, false))
+ unique_table(thd, tbl, join->tables_list, false))
{
/*
If the table we are going to delete from appears
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 5d896748d87..5bc83aefb98 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -516,6 +516,9 @@ bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived)
DBUG_RETURN(FALSE);
if (derived->is_materialized_derived())
DBUG_RETURN(mysql_derived_prepare(thd, lex, derived));
+ if ((thd->lex->sql_command == SQLCOM_UPDATE_MULTI ||
+ thd->lex->sql_command == SQLCOM_DELETE_MULTI))
+ DBUG_RETURN(FALSE);
if (!derived->is_multitable())
{
if (!derived->single_table_updatable())
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index be57be9b223..9c084555475 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2491,11 +2491,15 @@ mysql_execute_command(THD *thd)
according to slave filtering rules.
Returning success without producing any errors in this case.
*/
- DBUG_RETURN(0);
+ if (!thd->lex->create_info.if_exists())
+ DBUG_RETURN(0);
+ /*
+ DROP TRIGGER IF NOT EXISTS will return without an error later
+ after possibly writing the query to a binlog
+ */
}
-
- // force searching in slave.cc:tables_ok()
- all_tables->updating= 1;
+ else // force searching in slave.cc:tables_ok()
+ all_tables->updating= 1;
}
/*
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index de713d6aca0..610687ce8f1 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2013 Oracle and/or its affiliates.
- Copyright (c) 2009, 2013 Monty Program Ab.
+/* Copyright (c) 2000, 2014 Oracle and/or its affiliates.
+ Copyright (c) 2009, 2015 MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -4983,7 +4983,18 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array, KEY_FIELD *key_field)
}
-#define FT_KEYPART (MAX_REF_PARTS+10)
+/*
+ A key part number that means we're using a fulltext scan.
+
+ In order not to confuse it with regular equalities, we need to pick
+ a number that's greater than MAX_REF_PARTS.
+
+ Hash Join code stores field->field_index in KEYUSE::keypart, so the
+ number needs to be bigger than MAX_FIELDS, also.
+
+ CAUTION: sql_test.cc has its own definition of FT_KEYPART.
+*/
+#define FT_KEYPART (MAX_FIELDS+10)
static bool
add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
@@ -7477,8 +7488,12 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
else
fldno= table->key_info[key].key_part[keyparts-1].fieldnr - 1;
if (keyuse->val->const_item())
- {
- sel /= table->field[fldno]->cond_selectivity;
+ {
+ if (table->field[fldno]->cond_selectivity > 0)
+ {
+ sel /= table->field[fldno]->cond_selectivity;
+ set_if_smaller(sel, 1.0);
+ }
/*
TODO: we could do better here:
1. cond_selectivity might be =1 (the default) because quick
@@ -7532,7 +7547,10 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
if (!(next_field->table->map & rem_tables) && next_field->table != table)
{
if (field->cond_selectivity > 0)
+ {
sel/= field->cond_selectivity;
+ set_if_smaller(sel, 1.0);
+ }
break;
}
}
@@ -8721,7 +8739,8 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab,
{
Field *field= table->field[keyuse->keypart];
uint fieldnr= keyuse->keypart+1;
- table->create_key_part_by_field(keyinfo, key_part_info, field, fieldnr);
+ table->create_key_part_by_field(key_part_info, field, fieldnr);
+ keyinfo->key_length += key_part_info->store_length;
key_part_info++;
}
}
@@ -15878,7 +15897,6 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
(int) distinct, (int) save_sum_fields,
(ulong) rows_limit, MY_TEST(group)));
- thd->inc_status_created_tmp_tables();
thd->query_plan_flags|= QPLAN_TMP_TABLE;
if (use_temp_pool && !(test_flags & TEST_KEEP_TMP_TABLES))
@@ -16833,14 +16851,19 @@ bool open_tmp_table(TABLE *table)
HA_OPEN_TMP_TABLE |
HA_OPEN_INTERNAL_TABLE)))
{
- table->file->print_error(error,MYF(0)); /* purecov: inspected */
- table->db_stat=0;
- return(1);
+ table->file->print_error(error, MYF(0)); /* purecov: inspected */
+ table->db_stat= 0;
+ return 1;
}
table->db_stat= HA_OPEN_KEYFILE+HA_OPEN_RNDFILE;
- (void) table->file->extra(HA_EXTRA_QUICK); /* Faster */
- table->created= TRUE;
- return(0);
+ (void) table->file->extra(HA_EXTRA_QUICK); /* Faster */
+ if (!table->created)
+ {
+ table->created= TRUE;
+ table->in_use->inc_status_created_tmp_tables();
+ }
+
+ return 0;
}
@@ -16898,7 +16921,7 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
goto err;
bzero(seg, sizeof(*seg) * keyinfo->user_defined_key_parts);
- if (keyinfo->key_length >= table->file->max_key_length() ||
+ if (keyinfo->key_length > table->file->max_key_length() ||
keyinfo->user_defined_key_parts > table->file->max_key_parts() ||
share->uniques)
{
@@ -17040,8 +17063,10 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
}
table->in_use->inc_status_created_tmp_disk_tables();
+ table->in_use->inc_status_created_tmp_tables();
table->in_use->query_plan_flags|= QPLAN_TMP_DISK;
share->db_record_offset= 1;
+ table->created= TRUE;
DBUG_RETURN(0);
err:
DBUG_RETURN(1);
@@ -17101,7 +17126,7 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
goto err;
bzero(seg, sizeof(*seg) * keyinfo->user_defined_key_parts);
- if (keyinfo->key_length >= table->file->max_key_length() ||
+ if (keyinfo->key_length > table->file->max_key_length() ||
keyinfo->user_defined_key_parts > table->file->max_key_parts() ||
share->uniques)
{
@@ -17186,6 +17211,7 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
goto err;
}
table->in_use->inc_status_created_tmp_disk_tables();
+ table->in_use->inc_status_created_tmp_tables();
table->in_use->query_plan_flags|= QPLAN_TMP_DISK;
share->db_record_offset= 1;
table->created= TRUE;
diff --git a/sql/sql_select.h b/sql/sql_select.h
index a50ed130df8..fb42b6ba08e 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -1809,10 +1809,6 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
bool table_cant_handle_bit_fields,
bool make_copy_field,
uint convert_blob_length);
-bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
- TMP_ENGINE_COLUMNDEF *start_recinfo,
- TMP_ENGINE_COLUMNDEF **recinfo,
- ulonglong options, my_bool big_tables);
/*
General routine to change field->ptr of a NULL-terminated array of Field
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index cad2bf4ba56..ec65bd037b9 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -222,7 +222,7 @@ TEST_join(JOIN *join)
}
-#define FT_KEYPART (MAX_REF_PARTS+10)
+#define FT_KEYPART (MAX_FIELDS+10)
void print_keyuse(KEYUSE *keyuse)
{
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index ae6ba56c1e7..dbfe501be81 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -13544,7 +13544,12 @@ literal:
| UNDERSCORE_CHARSET hex_or_bin_String
{
Item_string_with_introducer *item_str;
- item_str= new (thd->mem_root) Item_string_with_introducer($2, $1);
+ /*
+ Pass NULL as name. Name will be set in the "select_item" rule and
+ will include the introducer and the original hex/bin notation.
+ */
+ item_str= new (thd->mem_root)
+ Item_string_with_introducer(NULL, $2->ptr(), $2->length(), $1);
if (!item_str || !item_str->check_well_formed_result(true))
MYSQL_YYABORT;
diff --git a/sql/structs.h b/sql/structs.h
index 9e9d7f9045e..de062f4a2ad 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -77,6 +77,7 @@ typedef struct st_key_part_info { /* Info about a key part */
*/
uint16 store_length;
uint16 key_type;
+ /* Fieldnr begins counting from 1 */
uint16 fieldnr; /* Fieldnum in UNIREG */
uint16 key_part_flag; /* 0 or HA_REVERSE_SORT */
uint8 type;
diff --git a/sql/table.cc b/sql/table.cc
index 9b6b64b93df..33695e730b0 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2012, Oracle and/or its affiliates.
- Copyright (c) 2008, 2014, SkySQL Ab.
+/* Copyright (c) 2000, 2014, Oracle and/or its affiliates.
+ Copyright (c) 2008, 2015, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -2946,7 +2946,9 @@ partititon_err:
outparam->no_replicate= FALSE;
}
- thd->status_var.opened_tables++;
+ /* Increment the opened_tables counter, only when open flags set. */
+ if (db_stat)
+ thd->status_var.opened_tables++;
thd->lex->context_analysis_only= save_context_analysis_only;
DBUG_RETURN (OPEN_FRM_OK);
@@ -6096,16 +6098,19 @@ bool TABLE::alloc_keys(uint key_count)
}
-/*
- Given a field, fill key_part_info
- @param keyinfo Key to where key part is added (we will
- only adjust key_length there)
- @param field IN Table field for which key part is needed
- @param key_part_info OUT key part structure to be filled.
- @param fieldnr Field's number.
+/**
+ @brief
+ Populate a KEY_PART_INFO structure with the data related to a field entry.
+
+ @param key_part_info The structure to fill.
+ @param field The field entry that represents the key part.
+ @param fleldnr The number of the field, count starting from 1.
+
+ TODO: This method does not make use of any table specific fields. It
+ could be refactored to act as a constructor for KEY_PART_INFO instead.
*/
-void TABLE::create_key_part_by_field(KEY *keyinfo,
- KEY_PART_INFO *key_part_info,
+
+void TABLE::create_key_part_by_field(KEY_PART_INFO *key_part_info,
Field *field, uint fieldnr)
{
DBUG_ASSERT(field->field_index + 1 == (int)fieldnr);
@@ -6115,8 +6120,11 @@ void TABLE::create_key_part_by_field(KEY *keyinfo,
key_part_info->field= field;
key_part_info->fieldnr= fieldnr;
key_part_info->offset= field->offset(record[0]);
- key_part_info->length= (uint16) field->pack_length();
- keyinfo->key_length+= key_part_info->length;
+ /*
+ field->key_length() accounts for the raw length of the field, excluding
+ any metadata such as length of field or the NULL flag.
+ */
+ key_part_info->length= (uint16) field->key_length();
key_part_info->key_part_flag= 0;
/* TODO:
The below method of computing the key format length of the
@@ -6128,17 +6136,20 @@ void TABLE::create_key_part_by_field(KEY *keyinfo,
*/
key_part_info->store_length= key_part_info->length;
+ /*
+ The total store length of the key part is the raw length of the field +
+ any metadata information, such as its length for strings and/or the null
+ flag.
+ */
if (field->real_maybe_null())
{
key_part_info->store_length+= HA_KEY_NULL_LENGTH;
- keyinfo->key_length+= HA_KEY_NULL_LENGTH;
}
if (field->type() == MYSQL_TYPE_BLOB ||
field->type() == MYSQL_TYPE_GEOMETRY ||
field->real_type() == MYSQL_TYPE_VARCHAR)
{
key_part_info->store_length+= HA_KEY_BLOB_LENGTH;
- keyinfo->key_length+= HA_KEY_BLOB_LENGTH; // ???
key_part_info->key_part_flag|=
field->type() == MYSQL_TYPE_BLOB ? HA_BLOB_PART: HA_VAR_LENGTH_PART;
}
@@ -6264,7 +6275,8 @@ bool TABLE::add_tmp_key(uint key, uint key_parts,
if (key_start)
(*reg_field)->key_start.set_bit(key);
(*reg_field)->part_of_key.set_bit(key);
- create_key_part_by_field(keyinfo, key_part_info, *reg_field, fld_idx+1);
+ create_key_part_by_field(key_part_info, *reg_field, fld_idx+1);
+ keyinfo->key_length += key_part_info->store_length;
(*reg_field)->flags|= PART_KEY_FLAG;
key_start= FALSE;
key_part_info++;
diff --git a/sql/table.h b/sql/table.h
index b020223854b..ba829167ab9 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1323,7 +1323,7 @@ public:
bool add_tmp_key(uint key, uint key_parts,
uint (*next_field_no) (uchar *), uchar *arg,
bool unique);
- void create_key_part_by_field(KEY *keyinfo, KEY_PART_INFO *key_part_info,
+ void create_key_part_by_field(KEY_PART_INFO *key_part_info,
Field *field, uint fieldnr);
void use_index(int key_to_save);
void set_table_map(table_map map_arg, uint tablenr_arg)
@@ -2074,6 +2074,24 @@ struct TABLE_LIST
TABLE_LIST *find_underlying_table(TABLE *table);
TABLE_LIST *first_leaf_for_name_resolution();
TABLE_LIST *last_leaf_for_name_resolution();
+ /**
+ @brief
+ Find the bottom in the chain of embedded table VIEWs.
+
+ @detail
+ This is used for single-table UPDATE/DELETE when they are modifying a
+ single-table VIEW.
+ */
+ TABLE_LIST *find_table_for_update()
+ {
+ TABLE_LIST *tbl= this;
+ while(!tbl->is_multitable() && tbl->single_table_updatable() &&
+ tbl->merge_underlying_list)
+ {
+ tbl= tbl->merge_underlying_list;
+ }
+ return tbl;
+ }
TABLE *get_real_join_table();
bool is_leaf_for_name_resolution();
inline TABLE_LIST *top_table()
diff --git a/sql/udf_example.c b/sql/udf_example.c
index 36a5eafb704..a48801d1c4a 100644
--- a/sql/udf_example.c
+++ b/sql/udf_example.c
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2010, Oracle and/or its affiliates.
+ Copyright (c) 2000, 2014, Oracle and/or its affiliates.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -296,9 +296,12 @@ char *metaphon(UDF_INIT *initid __attribute__((unused)),
if (!word) /* Null argument */
{
+ /* The length is expected to be zero when the argument is NULL. */
+ assert(args->lengths[0] == 0);
*is_null=1;
return 0;
}
+
w_end=word+args->lengths[0];
org_result=result;
diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt
index 931a811d897..918f5954fab 100644
--- a/storage/connect/CMakeLists.txt
+++ b/storage/connect/CMakeLists.txt
@@ -21,9 +21,9 @@ ha_connect.cc connect.cc user_connect.cc mycat.cc
fmdlex.c osutil.c plugutil.c rcmsg.c rcmsg.h
array.cpp blkfil.cpp colblk.cpp csort.cpp
filamap.cpp filamdbf.cpp filamfix.cpp filamtxt.cpp filamvct.cpp filamzip.cpp
-filter.cpp json.cpp maputil.cpp myutil.cpp plgdbutl.cpp reldef.cpp tabcol.cpp
-tabdos.cpp tabfix.cpp tabfmt.cpp tabjson.cpp table.cpp tabmul.cpp taboccur.cpp
-tabpivot.cpp tabsys.cpp tabtbl.cpp tabutil.cpp tabvct.cpp tabvir.cpp
+filter.cpp json.cpp jsonudf.cpp maputil.cpp myutil.cpp plgdbutl.cpp reldef.cpp
+tabcol.cpp tabdos.cpp tabfix.cpp tabfmt.cpp tabjson.cpp table.cpp tabmul.cpp
+taboccur.cpp tabpivot.cpp tabsys.cpp tabtbl.cpp tabutil.cpp tabvct.cpp tabvir.cpp
tabxcl.cpp valblk.cpp value.cpp xindex.cpp xobject.cpp
array.h blkfil.h block.h catalog.h checklvl.h colblk.h connect.h csort.h
diff --git a/storage/connect/array.h b/storage/connect/array.h
index 4a818414e9c..6fb38ae6b47 100644
--- a/storage/connect/array.h
+++ b/storage/connect/array.h
@@ -50,6 +50,7 @@ class DllExport ARRAY : public XOBJECT, public CSORT { // Array descblock
// void SetCorrel(bool b) {Correlated = b;}
// Methods
+ using XOBJECT::GetIntValue;
virtual void Reset(void) {Bot = -1;}
virtual int Qcompare(int *, int *);
virtual bool Compare(PXOB) {assert(FALSE); return FALSE;}
diff --git a/storage/connect/checklvl.h b/storage/connect/checklvl.h
index d1e37afbc93..0c234dfb8b8 100644
--- a/storage/connect/checklvl.h
+++ b/storage/connect/checklvl.h
@@ -40,4 +40,11 @@ enum USETEMP {TMP_NO = 0, /* Never */
TMP_FORCE = 3, /* Forced for MAP tables */
TMP_TEST = 4}; /* Testing value */
+/***********************************************************************/
+/* Following definitions indicate conversion of TEXT columns. */
+/***********************************************************************/
+enum TYPCONV {TPC_NO = 0, /* Never */
+ TPC_YES = 1, /* Always */
+ TPC_SKIP = 2}; /* Skip TEXT columns */
+
#endif // _CHKLVL_DEFINED_
diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc
index a54d8ebcc44..1b0db6dca6b 100644
--- a/storage/connect/connect.cc
+++ b/storage/connect/connect.cc
@@ -469,9 +469,12 @@ RCODE CntReadNext(PGLOBAL g, PTDB tdbp)
} while (rc == RC_NF);
+ if (rc == RC_OK)
+ rc= EvalColumns(g, tdbp, false);
+
err:
g->jump_level--;
- return (rc != RC_OK) ? rc : EvalColumns(g, tdbp, false);
+ return rc;
} // end of CntReadNext
/***********************************************************************/
diff --git a/storage/connect/global.h b/storage/connect/global.h
index 88e5094d6d2..a67bb605755 100644
--- a/storage/connect/global.h
+++ b/storage/connect/global.h
@@ -235,7 +235,7 @@ typedef struct _global { /* Global structure */
void *Xchk; /* indexes in create/alter */
short Alchecked; /* Checked for ALTER */
short Mrr; /* True when doing mrr */
- short Trace;
+ int N; /* Utility */
int jump_level;
jmp_buf jumper[MAX_JUMP + 2];
} GLOBAL;
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index ba594bdafb0..72f3e601958 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -165,23 +165,24 @@
/***********************************************************************/
/* Initialize the ha_connect static members. */
/***********************************************************************/
-#define SZCONV 8192
-#define SZWORK 67108864 // Default work area size 64M
-#define SZWMIN 4194304 // Minimum work area size 4M
+#define SZCONV 8192
+#define SZWORK 67108864 // Default work area size 64M
+#define SZWMIN 4194304 // Minimum work area size 4M
+#define JSONMAX 10 // JSON Default max grp size
extern "C" {
- char version[]= "Version 1.03.0006 January 13, 2015";
- char compver[]= "Version 1.03.0006 " __DATE__ " " __TIME__;
+ char version[]= "Version 1.03.0006 February 06, 2015";
#if defined(WIN32)
+ char compver[]= "Version 1.03.0006 " __DATE__ " " __TIME__;
char slash= '\\';
#else // !WIN32
char slash= '/';
#endif // !WIN32
// int trace= 0; // The general trace value
- ulong xconv= 0; // The type conversion option
- int zconv= 0; // The text conversion size
+// ulong xconv= 0; // The type conversion option
+// int zconv= 0; // The text conversion size
} // extern "C"
#if defined(XMAP)
@@ -215,6 +216,9 @@ bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host,
const char *db, char *tab, const char *src, int port);
bool ExactInfo(void);
USETEMP UseTemp(void);
+int GetConvSize(void);
+TYPCONV GetTypeConv(void);
+uint GetJsonGrpSize(void);
uint GetWorkSize(void);
void SetWorkSize(uint);
extern "C" const char *msglang(void);
@@ -289,6 +293,44 @@ static MYSQL_THDVAR_UINT(work_size,
"Size of the CONNECT work area.",
NULL, NULL, SZWORK, SZWMIN, UINT_MAX, 1);
+// Size used when converting TEXT columns to VARCHAR
+static MYSQL_THDVAR_INT(conv_size,
+ PLUGIN_VAR_RQCMDARG, // opt
+ "Size used when converting TEXT columns.",
+ NULL, NULL, SZCONV, 0, 65500, 1);
+
+/**
+ Type conversion:
+ no: Unsupported types -> TYPE_ERROR
+ yes: TEXT -> VARCHAR
+ skip: skip unsupported type columns in Discovery
+*/
+const char *xconv_names[]=
+{
+ "NO", "YES", "SKIP", NullS
+};
+
+TYPELIB xconv_typelib=
+{
+ array_elements(xconv_names) - 1, "xconv_typelib",
+ xconv_names, NULL
+};
+
+static MYSQL_THDVAR_ENUM(
+ type_conv, // name
+ PLUGIN_VAR_RQCMDARG, // opt
+ "Unsupported types conversion.", // comment
+ NULL, // check
+ NULL, // update function
+ 0, // def (no)
+ &xconv_typelib); // typelib
+
+// Estimate max number of rows for JSON aggregate functions
+static MYSQL_THDVAR_UINT(json_grp_size,
+ PLUGIN_VAR_RQCMDARG, // opt
+ "max number of rows for JSON aggregate functions.",
+ NULL, NULL, JSONMAX, 1, INT_MAX, 1);
+
#if defined(XMSG) || defined(NEWMSG)
const char *language_names[]=
{
@@ -317,6 +359,9 @@ static MYSQL_THDVAR_ENUM(
extern "C" int GetTraceValue(void) {return THDVAR(current_thd, xtrace);}
bool ExactInfo(void) {return THDVAR(current_thd, exact_info);}
USETEMP UseTemp(void) {return (USETEMP)THDVAR(current_thd, use_tempfile);}
+int GetConvSize(void) {return THDVAR(current_thd, conv_size);}
+TYPCONV GetTypeConv(void) {return (TYPCONV)THDVAR(current_thd, type_conv);}
+uint GetJsonGrpSize(void) {return THDVAR(current_thd, json_grp_size);}
uint GetWorkSize(void) {return THDVAR(current_thd, work_size);}
void SetWorkSize(uint n)
{
@@ -598,7 +643,11 @@ static int connect_init_func(void *p)
}
#endif // 0 (LINUX)
+#if defined(WIN32)
sql_print_information("CONNECT: %s", compver);
+#else // !WIN32
+ sql_print_information("CONNECT: %s", version);
+#endif // !WIN32
#ifdef LIBXML2_SUPPORT
XmlInitParserLib();
@@ -934,6 +983,9 @@ ulonglong ha_connect::table_flags() const
char *GetListOption(PGLOBAL g, const char *opname,
const char *oplist, const char *def)
{
+ if (!oplist)
+ return (char*)def;
+
char key[16], val[256];
char *pk, *pv, *pn;
char *opval= (char*) def;
@@ -997,8 +1049,12 @@ char *ha_connect::GetRealString(const char *s)
char *sv;
if (IsPartitioned() && s) {
- sv= (char*)PlugSubAlloc(xp->g, NULL, strlen(s) + strlen(partname));
+// sv= (char*)PlugSubAlloc(xp->g, NULL, strlen(s) + strlen(partname));
+ // With wrong string pattern, the size of the constructed string
+ // can be more than strlen(s) + strlen(partname)
+ sv= (char*)PlugSubAlloc(xp->g, NULL, 0);
sprintf(sv, s, partname);
+ PlugSubAlloc(xp->g, NULL, strlen(sv) + 1);
} else
sv= (char*)s;
@@ -1064,9 +1120,16 @@ char *ha_connect::GetStringOption(char *opname, char *sdef)
} // endif Table_charset
- if (!opval && options && options->oplist)
+ if (!opval && options && options->oplist) {
opval= GetListOption(xp->g, opname, options->oplist);
+ if (opval && (!stricmp(opname, "connect")
+ || !stricmp(opname, "tabname")
+ || !stricmp(opname, "filename")))
+ opval = GetRealString(opval);
+
+ } // endif opval
+
if (!opval) {
if (sdef && !strcmp(sdef, "*")) {
// Return the handler default value
@@ -2467,6 +2530,8 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
char *body= filp->Body;
unsigned int i;
bool ismul= false, x= (tty == TYPE_AM_MYX || tty == TYPE_AM_XDBC);
+ bool nonul= (tty == TYPE_AM_ODBC && (tdbp->GetMode() == MODE_INSERT ||
+ tdbp->GetMode() == MODE_DELETE));
OPVAL vop= OP_XX;
if (!cond)
@@ -2484,7 +2549,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
if (trace)
htrc("Cond: Ftype=%d name=%s\n", cond_item->functype(),
- cond_item->func_name());
+ cond_item->func_name());
switch (cond_item->functype()) {
case Item_func::COND_AND_FUNC: vop= OP_AND; break;
@@ -2503,7 +2568,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
for (i= 0; i < arglist->elements; i++)
if ((subitem= li++)) {
if (!CheckCond(g, filp, tty, subitem)) {
- if (vop == OP_OR)
+ if (vop == OP_OR || nonul)
return NULL;
else
*p2= 0;
@@ -2599,6 +2664,8 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
if (trace) {
htrc("Field index=%d\n", pField->field->field_index);
htrc("Field name=%s\n", pField->field->field_name);
+ htrc("Field type=%d\n", pField->field->type());
+ htrc("Field_type=%d\n", args[i]->field_type());
} // endif trace
// IN and BETWEEN clauses should be col VOP list
@@ -2618,8 +2685,9 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
char buff[256];
String *res, tmp(buff, sizeof(buff), &my_charset_bin);
Item_basic_constant *pval= (Item_basic_constant *)args[i];
+ Item::Type type= args[i]->real_type();
- switch (args[i]->real_type()) {
+ switch (type) {
case COND::STRING_ITEM:
case COND::INT_ITEM:
case COND::REAL_ITEM:
@@ -2644,10 +2712,64 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
if (!x) {
// Append the value to the filter
- if (args[i]->field_type() == MYSQL_TYPE_VARCHAR)
- strcat(strncat(strcat(body, "'"), res->ptr(), res->length()), "'");
- else
- strncat(body, res->ptr(), res->length());
+ switch (args[i]->field_type()) {
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_DATETIME:
+ if (tty == TYPE_AM_ODBC) {
+ strcat(body, "{ts '");
+ strcat(strncat(body, res->ptr(), res->length()), "'}");
+ break;
+ } // endif ODBC
+
+ case MYSQL_TYPE_DATE:
+ if (tty == TYPE_AM_ODBC) {
+ strcat(body, "{d '");
+ strcat(strncat(body, res->ptr(), res->length()), "'}");
+ break;
+ } // endif ODBC
+
+ case MYSQL_TYPE_TIME:
+ if (tty == TYPE_AM_ODBC) {
+ strcat(body, "{t '");
+ strcat(strncat(body, res->ptr(), res->length()), "'}");
+ break;
+ } // endif ODBC
+
+ case MYSQL_TYPE_VARCHAR:
+ if (tty == TYPE_AM_ODBC && i) {
+ switch (args[0]->field_type()) {
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_DATETIME:
+ strcat(body, "{ts '");
+ strncat(body, res->ptr(), res->length());
+ strcat(body, "'}");
+ break;
+ case MYSQL_TYPE_DATE:
+ strcat(body, "{d '");
+ strncat(body, res->ptr(), res->length());
+ strcat(body, "'}");
+ break;
+ case MYSQL_TYPE_TIME:
+ strcat(body, "{t '");
+ strncat(body, res->ptr(), res->length());
+ strcat(body, "'}");
+ break;
+ default:
+ strcat(body, "'");
+ strncat(body, res->ptr(), res->length());
+ strcat(body, "'");
+ } // endswitch field type
+
+ } else {
+ strcat(body, "'");
+ strncat(body, res->ptr(), res->length());
+ strcat(body, "'");
+ } // endif tty
+
+ break;
+ default:
+ strncat(body, res->ptr(), res->length());
+ } // endswitch field type
} else {
if (args[i]->field_type() == MYSQL_TYPE_VARCHAR) {
@@ -2753,7 +2875,7 @@ const COND *ha_connect::cond_push(const COND *cond)
} else if (x && cond)
tdbp->SetCondFil(filp); // Wrong filter
- } else
+ } else if (tty != TYPE_AM_JSN && tty != TYPE_AM_JSON)
tdbp->SetFilter(CondFilter(g, (Item *)cond));
fin:
@@ -3987,6 +4109,7 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
case SQLCOM_UPDATE_MULTI:
case SQLCOM_SELECT:
case SQLCOM_OPTIMIZE:
+ case SQLCOM_SET_OPTION:
break;
case SQLCOM_LOCK_TABLES:
locked= 1;
@@ -4617,7 +4740,7 @@ static bool add_field(String *sql, const char *field_name, int typ,
char *dft, char *xtra, int flag, bool dbf, char v)
{
char var = (len > 255) ? 'V' : v;
- bool error= false;
+ bool q, error= false;
const char *type= PLGtoMYSQLtype(typ, dbf, var);
error|= sql->append('`');
@@ -4658,7 +4781,12 @@ static bool add_field(String *sql, const char *field_name, int typ,
if (dft && *dft) {
error|= sql->append(" DEFAULT ");
- if (!IsTypeNum(typ)) {
+ if (typ == TYPE_DATE)
+ q = (strspn(dft, "0123456789 -:/") == strlen(dft));
+ else
+ q = !IsTypeNum(typ);
+
+ if (q) {
error|= sql->append("'");
error|= sql->append_for_single_quote(dft, strlen(dft));
error|= sql->append("'");
@@ -4828,6 +4956,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
int port= 0, hdr= 0, mxr __attribute__((unused))= 0, mxe= 0, rc= 0;
int cop __attribute__((unused)) = 0;
#if defined(ODBC_SUPPORT)
+ POPARM sop = NULL;
+ char *ucnc = NULL;
+ bool cnc= false;
int cto= -1, qto= -1;
#endif // ODBC_SUPPORT
uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL);
@@ -4872,7 +5003,8 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
if (topt->oplist) {
host= GetListOption(g, "host", topt->oplist, "localhost");
- user= GetListOption(g, "user", topt->oplist, "root");
+ user= GetListOption(g, "user", topt->oplist,
+ (ttp == TAB_ODBC ? NULL : "root"));
// Default value db can come from the DBNAME=xxx option.
db= GetListOption(g, "database", topt->oplist, db);
col= GetListOption(g, "colist", topt->oplist, col);
@@ -4891,6 +5023,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
mxr= atoi(GetListOption(g,"maxres", topt->oplist, "0"));
cto= atoi(GetListOption(g,"ConnectTimeout", topt->oplist, "-1"));
qto= atoi(GetListOption(g,"QueryTimeout", topt->oplist, "-1"));
+
+ if ((ucnc= GetListOption(g, "UseDSN", topt->oplist)))
+ cnc= (!*ucnc || *ucnc == 'y' || *ucnc == 'Y' || atoi(ucnc) != 0);
#endif
mxe= atoi(GetListOption(g,"maxerr", topt->oplist, "0"));
#if defined(PROMPT_OK)
@@ -4898,7 +5033,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
#endif // PROMPT_OK
} else {
host= "localhost";
- user= "root";
+ user= (ttp == TAB_ODBC ? NULL : "root");
} // endif option_list
if (!(shm= (char*)db))
@@ -4975,10 +5110,18 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
} // endif dsn
#endif // PROMPT_OK
- } else if (!dsn)
+ } else if (!dsn) {
sprintf(g->Message, "Missing %s connection string", topt->type);
- else
+ } else {
+ // Store ODBC additional parameters
+ sop= (POPARM)PlugSubAlloc(g, NULL, sizeof(ODBCPARM));
+ sop->User= (char*)user;
+ sop->Pwd= (char*)pwd;
+ sop->Cto= cto;
+ sop->Qto= qto;
+ sop->UseCnc= cnc;
ok= true;
+ } // endif's
supfnc |= (FNC_TABLE | FNC_DSN | FNC_DRIVER);
break;
@@ -5109,15 +5252,15 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
case FNC_NO:
case FNC_COL:
if (src) {
- qrp= ODBCSrcCols(g, dsn, (char*)src, cto, qto);
+ qrp= ODBCSrcCols(g, dsn, (char*)src, sop);
src= NULL; // for next tests
} else
- qrp= ODBCColumns(g, dsn, shm, tab, NULL,
- mxr, cto, qto, fnc == FNC_COL);
+ qrp= ODBCColumns(g, dsn, shm, tab, NULL,
+ mxr, fnc == FNC_COL, sop);
break;
case FNC_TABLE:
- qrp= ODBCTables(g, dsn, shm, tab, mxr, cto, qto, true);
+ qrp= ODBCTables(g, dsn, shm, tab, mxr, true, sop);
break;
case FNC_DSN:
qrp= ODBCDataSources(g, mxr, true);
@@ -5234,9 +5377,10 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
for (crp= qrp->Colresp; crp; crp= crp->Next)
switch (crp->Fld) {
case FLD_NAME:
- if (ttp == TAB_CSV && topt->data_charset &&
+ if (ttp == TAB_PRX ||
+ (ttp == TAB_CSV && topt->data_charset &&
(!stricmp(topt->data_charset, "UTF8") ||
- !stricmp(topt->data_charset, "UTF-8")))
+ !stricmp(topt->data_charset, "UTF-8"))))
cnm= crp->Kdata->GetCharValue(i);
else
cnm= encode(g, crp->Kdata->GetCharValue(i));
@@ -5296,9 +5440,18 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
// typ must be PLG type, not SQL type
if (!(plgtyp= TranslateSQLType(typ, dec, prec, v))) {
- sprintf(g->Message, "Unsupported SQL type %d", typ);
- my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
- goto err;
+ if (GetTypeConv() == TPC_SKIP) {
+ // Skip this column
+ sprintf(g->Message, "Column %s skipped (unsupported type %d)",
+ cnm, typ);
+ push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
+ continue;
+ } else {
+ sprintf(g->Message, "Unsupported SQL type %d", typ);
+ my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ goto err;
+ } // endif type_conv
+
} else
typ= plgtyp;
@@ -5306,7 +5459,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
case TYPE_DOUBLE:
// Some data sources do not count dec in length (prec)
prec += (dec + 2); // To be safe
+ break;
case TYPE_DECIM:
+ prec= len;
break;
default:
dec= 0;
@@ -6338,58 +6493,6 @@ struct st_mysql_storage_engine connect_storage_engine=
/***********************************************************************/
/* CONNECT global variables definitions. */
/***********************************************************************/
-// Size used when converting TEXT columns to VARCHAR
-#if defined(_DEBUG)
-static MYSQL_SYSVAR_INT(conv_size, zconv,
- PLUGIN_VAR_RQCMDARG, // opt
- "Size used when converting TEXT columns.",
- NULL, NULL, SZCONV, 0, 65500, 1);
-#else
-static MYSQL_SYSVAR_INT(conv_size, zconv,
- PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, // opt
- "Size used when converting TEXT columns.",
- NULL, NULL, SZCONV, 0, 65500, 1);
-#endif
-
-/**
- Type conversion:
- no: Unsupported types -> TYPE_ERROR
- yes: TEXT -> VARCHAR
- skip: skip unsupported type columns in Discovery
-*/
-const char *xconv_names[]=
-{
- "NO", "YES", "SKIP", NullS
-};
-
-TYPELIB xconv_typelib=
-{
- array_elements(xconv_names) - 1, "xconv_typelib",
- xconv_names, NULL
-};
-
-#if defined(_DEBUG)
-static MYSQL_SYSVAR_ENUM(
- type_conv, // name
- xconv, // varname
- PLUGIN_VAR_RQCMDARG, // opt
- "Unsupported types conversion.", // comment
- NULL, // check
- NULL, // update function
- 0, // def (no)
- &xconv_typelib); // typelib
-#else
-static MYSQL_SYSVAR_ENUM(
- type_conv, // name
- xconv, // varname
- PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
- "Unsupported types conversion.", // comment
- NULL, // check
- NULL, // update function
- 0, // def (no)
- &xconv_typelib); // typelib
-#endif
-
#if defined(XMAP)
// Using file mapping for indexes if true
static MYSQL_SYSVAR_BOOL(indx_map, xmap, PLUGIN_VAR_RQCMDARG,
@@ -6422,6 +6525,7 @@ static struct st_mysql_sys_var* connect_system_variables[]= {
#if defined(XMSG)
MYSQL_SYSVAR(errmsg_dir_path),
#endif // XMSG
+ MYSQL_SYSVAR(json_grp_size),
NULL
};
diff --git a/storage/connect/json.cpp b/storage/connect/json.cpp
index 983f45d9cee..6f4bd18457b 100644
--- a/storage/connect/json.cpp
+++ b/storage/connect/json.cpp
@@ -1,1055 +1,1162 @@
-/*************** json CPP Declares Source Code File (.H) ***************/
-/* Name: json.cpp Version 1.0 */
-/* */
-/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */
-/* */
-/* This file contains the JSON classes functions. */
-/***********************************************************************/
-
-/***********************************************************************/
-/* Include relevant sections of the MariaDB header file. */
-/***********************************************************************/
-#include <my_global.h>
-
-/***********************************************************************/
-/* Include application header files: */
-/* global.h is header containing all global declarations. */
-/* plgdbsem.h is header containing the DB application declarations. */
-/* xjson.h is header containing the JSON classes declarations. */
-/***********************************************************************/
-#include "global.h"
-#include "plgdbsem.h"
-#include "json.h"
-
-#define ARGS MY_MIN(24,len-i),s+MY_MAX(i-3,0)
-
-#if defined(WIN32)
-#define EL "\r\n"
-#else
-#define EL "\n"
-#endif
-
-/***********************************************************************/
-/* Parse a json string. */
-/***********************************************************************/
-PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
-{
- int i;
- bool b = false;
- PJSON jsp = NULL;
- STRG src;
-
- if (!s || !len) {
- strcpy(g->Message, "Void JSON object");
- return NULL;
- } else if (comma)
- *comma = false;
-
- src.str = s;
- src.len = len;
-
- for (i = 0; i < len; i++)
- switch (s[i]) {
- case '[':
- if (jsp) {
- strcpy(g->Message, "More than one item in file");
- return NULL;
- } else if (!(jsp = ParseArray(g, ++i, src)))
- return NULL;
-
- break;
- case '{':
- if (jsp) {
- strcpy(g->Message, "More than one item in file");
- return NULL;
- } else if (!(jsp = ParseObject(g, ++i, src)))
- return NULL;
- break;
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- break;
- case ',':
- if (jsp && pretty == 1) {
- if (comma)
- *comma = true;
-
- break;
- } // endif pretty
-
- sprintf(g->Message, "Unexpected ',' (pretty=%d)", pretty);
- return NULL;
- case '(':
- b = true;
- break;
- case ')':
- if (b) {
- b = false;
- break;
- } // endif b
-
- default:
- sprintf(g->Message, "Bad '%c' character near %.*s",
- s[i], ARGS);
- return NULL;
- }; // endswitch s[i]
-
- if (!jsp)
- sprintf(g->Message, "Invalid Json string '%.*s'", 50, s);
-
- return jsp;
-} // end of ParseJson
-
-/***********************************************************************/
-/* Parse a JSON Array. */
-/***********************************************************************/
-PJAR ParseArray(PGLOBAL g, int& i, STRG& src)
-{
- char *s = src.str;
- int len = src.len;
- int level = 0;
- PJAR jarp = new(g) JARRAY;
- PJVAL jvp = NULL;
-
- for (; i < len; i++)
- switch (s[i]) {
- case ',':
- if (level < 2) {
- sprintf(g->Message, "Unexpected ',' near %.*s",ARGS);
- return NULL;
- } else
- level = 1;
-
- break;
- case ']':
- if (level == 1) {
- sprintf(g->Message, "Unexpected ',]' near %.*s", ARGS);
- return NULL;
- } // endif level
-
- jarp->InitArray(g);
- return jarp;
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- break;
- default:
- if (level == 2) {
- sprintf(g->Message, "Unexpected value near %.*s", ARGS);
- return NULL;
- } else if ((jvp = ParseValue(g, i, src))) {
- jarp->AddValue(g, jvp);
- level = 2;
- } else
- return NULL;
-
- level = 2;
- break;
- }; // endswitch s[i]
-
- strcpy(g->Message, "Unexpected EOF in array");
- return NULL;
-} // end of ParseArray
-
-/***********************************************************************/
-/* Parse a JSON Object. */
-/***********************************************************************/
-PJOB ParseObject(PGLOBAL g, int& i, STRG& src)
-{
- PSZ key;
- char *s = src.str;
- int len = src.len;
- int level = 0;
- PJOB jobp = new(g) JOBJECT;
- PJPR jpp = NULL;
-
- for (; i < len; i++)
- switch (s[i]) {
- case '"':
- if (level < 2) {
- if ((key = ParseString(g, ++i, src))) {
- jpp = jobp->AddPair(g, key);
- level = 1;
- } else
- return NULL;
-
- } else {
- sprintf(g->Message, "misplaced string near %.*s", ARGS);
- return NULL;
- } // endif level
-
- break;
- case ':':
- if (level == 1) {
- if (!(jpp->Val = ParseValue(g, ++i, src)))
- return NULL;
-
- level = 2;
- } else {
- sprintf(g->Message, "Unexpected ':' near %.*s", ARGS);
- return NULL;
- } // endif level
-
- break;
- case ',':
- if (level < 2) {
- sprintf(g->Message, "Unexpected ',' near %.*s", ARGS);
- return NULL;
- } else
- level = 1;
-
- break;
- case '}':
- if (level == 1) {
- sprintf(g->Message, "Unexpected '}' near %.*s", ARGS);
- return NULL;
- } // endif level
-
- return jobp;
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- break;
- default:
- sprintf(g->Message, "Unexpected character '%c' near %.*s",
- s[i], ARGS);
- return NULL;
- }; // endswitch s[i]
-
- strcpy(g->Message, "Unexpected EOF in Object");
- return NULL;
-} // end of ParseObject
-
-/***********************************************************************/
-/* Parse a JSON Value. */
-/***********************************************************************/
-PJVAL ParseValue(PGLOBAL g, int& i, STRG& src)
-{
- char *strval, *s = src.str;
- int n, len = src.len;
- PJVAL jvp = new(g) JVALUE;
-
- for (; i < len; i++)
- switch (s[i]) {
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- break;
- default:
- goto suite;
- } // endswitch
-
- suite:
- switch (s[i]) {
- case '[':
- if (!(jvp->Jsp = ParseArray(g, ++i, src)))
- return NULL;
-
- break;
- case '{':
- if (!(jvp->Jsp = ParseObject(g, ++i, src)))
- return NULL;
-
- break;
- case '"':
- if ((strval = ParseString(g, ++i, src)))
- jvp->Value = AllocateValue(g, strval, TYPE_STRING);
- else
- return NULL;
-
- break;
- case 't':
- if (!strncmp(s + i, "true", 4)) {
- n = 1;
- jvp->Value = AllocateValue(g, &n, TYPE_TINY);
- i += 3;
- } else
- goto err;
-
- break;
- case 'f':
- if (!strncmp(s + i, "false", 5)) {
- n = 0;
- jvp->Value = AllocateValue(g, &n, TYPE_TINY);
- i += 4;
- } else
- goto err;
-
- break;
- case 'n':
- if (!strncmp(s + i, "null", 4))
- i += 3;
- else
- goto err;
-
- break;
- case '-':
- default:
- if (s[i] == '-' || isdigit(s[i])) {
- if (!(jvp->Value = ParseNumeric(g, i, src)))
- goto err;
-
- } else
- goto err;
-
- }; // endswitch s[i]
-
- jvp->Size = 1;
- return jvp;
-
-err:
- sprintf(g->Message, "Unexpected character '%c' near %.*s",
- s[i], ARGS);
- return NULL;
-} // end of ParseValue
-
-/***********************************************************************/
-/* Unescape and parse a JSON string. */
-/***********************************************************************/
-char *ParseString(PGLOBAL g, int& i, STRG& src)
-{
- char *p, *s = src.str;
- int n = 0, len = src.len;
-
- // The size to allocate is not known yet
- p = (char*)PlugSubAlloc(g, NULL, 0);
-
- for (; i < len; i++)
- switch (s[i]) {
- case '"':
- p[n++] = 0;
- PlugSubAlloc(g, NULL, n);
- return p;
- case '\\':
- if (++i < len) {
- if (s[i] == 'u') {
- if (len - i > 5) {
-// if (charset == utf8) {
- char xs[5];
- uint hex;
-
- xs[0] = s[++i];
- xs[1] = s[++i];
- xs[2] = s[++i];
- xs[3] = s[++i];
- xs[4] = 0;
- hex = strtoul(xs, NULL, 16);
-
- if (hex < 0x80) {
- p[n] = (uchar)hex;
- } else if (hex < 0x800) {
- p[n++] = (uchar)(0xC0 | (hex >> 6));
- p[n] = (uchar)(0x80 | (hex & 0x3F));
- } else if (hex < 0x10000) {
- p[n++] = (uchar)(0xE0 | (hex >> 12));
- p[n++] = (uchar)(0x80 | ((hex >> 6) & 0x3f));
- p[n] = (uchar)(0x80 | (hex & 0x3f));
- } else
- p[n] = '?';
-
-#if 0
- } else {
- char xs[3];
- UINT hex;
-
- i += 2;
- xs[0] = s[++i];
- xs[1] = s[++i];
- xs[2] = 0;
- hex = strtoul(xs, NULL, 16);
- p[n] = (char)hex;
- } // endif charset
-#endif // 0
- } else
- goto err;
-
- } else switch(s[i]) {
- case 't': p[n] = '\t'; break;
- case 'n': p[n] = '\n'; break;
- case 'r': p[n] = '\r'; break;
- case 'b': p[n] = '\b'; break;
- case 'f': p[n] = '\f'; break;
- default: p[n] = s[i]; break;
- } // endswitch
-
- n++;
- } else
- goto err;
-
- break;
- default:
- p[n++] = s[i];
- break;
- }; // endswitch s[i]
-
- err:
- strcpy(g->Message, "Unexpected EOF in String");
- return NULL;
-} // end of ParseString
-
-/***********************************************************************/
-/* Parse a JSON numeric value. */
-/***********************************************************************/
-PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src)
-{
- char *s = src.str, buf[50];
- int n = 0, len = src.len;
- short nd = 0;
- bool has_dot = false;
- bool has_e = false;
- bool found_digit = false;
- PVAL valp = NULL;
-
- for (; i < len; i++) {
- switch (s[i]) {
- case '.':
- if (!found_digit || has_dot || has_e)
- goto err;
-
- has_dot = true;
- break;
- case 'e':
- case 'E':
- if (!found_digit || has_e)
- goto err;
-
- has_e = true;
- found_digit = false;
- break;
- case '+':
- if (!has_e)
- goto err;
-
- // passthru
- case '-':
- if (found_digit)
- goto err;
-
- break;
- default:
- if (isdigit(s[i])) {
- if (has_dot && !has_e)
- nd++; // Number of decimals
-
- found_digit = true;
- } else
- goto fin;
-
- }; // endswitch s[i]
-
- buf[n++] = s[i];
- } // endfor i
-
- fin:
- if (found_digit) {
- buf[n] = 0;
-
- if (has_dot || has_e) {
- double dv = strtod(buf, NULL);
-
- valp = AllocateValue(g, &dv, TYPE_DOUBLE, nd);
- } else {
- int iv = strtol(buf, NULL, 10);
-
- valp = AllocateValue(g, &iv, TYPE_INT);
- } // endif has
-
- i--; // Unstack following character
- return valp;
- } else {
- strcpy(g->Message, "No digit found");
- return NULL;
- } // endif found_digit
-
- err:
- strcpy(g->Message, "Unexpected EOF in number");
- return NULL;
-} // end of ParseNumeric
-
-/***********************************************************************/
-/* Serialize a JSON tree: */
-/***********************************************************************/
-PSZ Serialize(PGLOBAL g, PJSON jsp, FILE *fs, int pretty)
-{
- bool b = false, err = true;
- JOUT *jp;
-
- g->Message[0] = 0;
-
- if (!jsp) {
- strcpy(g->Message, "Null json tree");
- return NULL;
- } else if (!fs) {
- // Serialize to a string
- jp = new(g) JOUTSTR(g);
- b = pretty == 1;
- } else if (pretty == 2) {
- // Serialize to a pretty file
- jp = new(g) JOUTPRT(g, fs);
- } else {
- // Serialize to a flat file
- jp = new(g) JOUTFILE(g, fs);
- b = pretty == 1;
- } // endif's
-
- switch (jsp->GetType()) {
- case TYPE_JAR:
- err = SerializeArray(jp, (PJAR)jsp, b);
- break;
- case TYPE_JOB:
- err = (b && jp->WriteChr('\t'));
- err |= SerializeObject(jp, (PJOB)jsp);
- break;
- default:
- strcpy(g->Message, "json tree is not an Array or an Object");
- } // endswitch Type
-
- if (fs) {
- fputc('\n', fs);
- fclose(fs);
- return (err) ? g->Message : NULL;
- } else if (!err) {
- PSZ str = ((JOUTSTR*)jp)->Strp;
-
- jp->WriteChr('\0');
- PlugSubAlloc(g, NULL, ((JOUTSTR*)jp)->N);
- return str;
- } else {
- if (!g->Message[0])
- strcpy(g->Message, "Error in Serialize");
-
- return NULL;
- } // endif's
-
-} // end of Serialize
-
-/***********************************************************************/
-/* Serialize a JSON Array. */
-/***********************************************************************/
-bool SerializeArray(JOUT *js, PJAR jarp, bool b)
-{
- bool first = true;
-
-
- if (js->WriteChr('['))
- return true;
- else if (b && (js->WriteStr(EL) || js->WriteChr('\t')))
- return true;
-
- for (int i = 0; i < jarp->size(); i++) {
- if (first)
- first = false;
- else if (js->WriteChr(','))
- return true;
- else if (b && (js->WriteStr(EL) || js->WriteChr('\t')))
- return true;
-
- if (SerializeValue(js, jarp->GetValue(i)))
- return true;
-
- } // endfor i
-
- if (b && js->WriteStr(EL))
- return true;
-
- return js->WriteChr(']');
-} // end of SerializeArray
-
-/***********************************************************************/
-/* Serialize a JSON Object. */
-/***********************************************************************/
-bool SerializeObject(JOUT *js, PJOB jobp)
-{
- bool first = true;
-
- if (js->WriteChr('{'))
- return true;
-
- for (PJPR pair = jobp->First; pair; pair = pair->Next) {
- if (first)
- first = false;
- else if (js->WriteChr(','))
- return true;
-
- if (js->WriteChr('\"') ||
- js->WriteStr(pair->Key) ||
- js->WriteChr('\"') ||
- js->WriteChr(':') ||
- SerializeValue(js, pair->Val))
- return true;
-
- } // endfor i
-
- return js->WriteChr('}');
-} // end of SerializeObject
-
-/***********************************************************************/
-/* Serialize a JSON Value. */
-/***********************************************************************/
-bool SerializeValue(JOUT *js, PJVAL jvp)
-{
- PJAR jap;
- PJOB jop;
- PVAL valp;
-
- if ((jap = jvp->GetArray()))
- return SerializeArray(js, jap, false);
- else if ((jop = jvp->GetObject()))
- return SerializeObject(js, jop);
- else if (!(valp = jvp->Value) || valp->IsNull())
- return js->WriteStr("null");
- else switch (valp->GetType()) {
- case TYPE_TINY:
- return js->WriteStr(valp->GetTinyValue() ? "true" : "false");
- case TYPE_STRING:
- return js->Escape(valp->GetCharValue());
- default:
- if (valp->IsTypeNum()) {
- char buf[32];
-
- return js->WriteStr(valp->GetCharString(buf));
- } // endif valp
-
- } // endswitch Type
-
-strcpy(js->g->Message, "Unrecognized value");
-return true;
-} // end of SerializeValue
-
-/* -------------------------- Class JOUTSTR -------------------------- */
-
-/***********************************************************************/
-/* JOUTSTR constructor. */
-/***********************************************************************/
-JOUTSTR::JOUTSTR(PGLOBAL g) : JOUT(g)
-{
- PPOOLHEADER pph = (PPOOLHEADER)g->Sarea;
-
- N = 0;
- Max = pph->FreeBlk;
- Max = (Max > 512) ? Max - 512 : Max;
- Strp = (char*)PlugSubAlloc(g, NULL, 0); // Size not know yet
-} // end of JOUTSTR constructor
-
-/***********************************************************************/
-/* Concatenate a string to the Serialize string. */
-/***********************************************************************/
-bool JOUTSTR::WriteStr(const char *s)
-{
- if (s) {
- size_t len = strlen(s);
-
- if (N + len > Max)
- return true;
-
- memcpy(Strp + N, s, len);
- N += len;
- return false;
- } else
- return true;
-
-} // end of WriteStr
-
-/***********************************************************************/
-/* Concatenate a character to the Serialize string. */
-/***********************************************************************/
-bool JOUTSTR::WriteChr(const char c)
-{
- if (N + 1 > Max)
- return true;
-
- Strp[N++] = c;
- return false;
-} // end of WriteChr
-
-/***********************************************************************/
-/* Escape and Concatenate a string to the Serialize string. */
-/***********************************************************************/
-bool JOUTSTR::Escape(const char *s)
-{
- WriteChr('"');
-
- for (unsigned int i = 0; i < strlen(s); i++)
- switch (s[i]) {
- case '\t':
- case '\n':
- case '\r':
- case '\b':
- case '\f':
- case '"': WriteChr('\\');
- // passthru
- default:
- WriteChr(s[i]);
- break;
- } // endswitch s[i]
-
- WriteChr('"');
- return false;
-} // end of Escape
-
-/* ------------------------- Class JOUTFILE -------------------------- */
-
-/***********************************************************************/
-/* Write a string to the Serialize file. */
-/***********************************************************************/
-bool JOUTFILE::WriteStr(const char *s)
-{
- // This is temporary
- fputs(s, Stream);
- return false;
-} // end of WriteStr
-
-/***********************************************************************/
-/* Write a character to the Serialize file. */
-/***********************************************************************/
-bool JOUTFILE::WriteChr(const char c)
-{
- // This is temporary
- fputc(c, Stream);
- return false;
-} // end of WriteChr
-
-/***********************************************************************/
-/* Escape and Concatenate a string to the Serialize string. */
-/***********************************************************************/
-bool JOUTFILE::Escape(const char *s)
-{
- // This is temporary
- fputc('"', Stream);
-
- for (unsigned int i = 0; i < strlen(s); i++)
- switch (s[i]) {
- case '\t': fputs("\\t", Stream); break;
- case '\n': fputs("\\n", Stream); break;
- case '\r': fputs("\\r", Stream); break;
- case '\b': fputs("\\b", Stream); break;
- case '\f': fputs("\\f", Stream); break;
- case '"': fputs("\\\"", Stream); break;
- default:
- fputc(s[i], Stream);
- break;
- } // endswitch s[i]
-
- fputc('"', Stream);
- return false;
-} // end of Escape
-
-/* ------------------------- Class JOUTPRT --------------------------- */
-
-/***********************************************************************/
-/* Write a string to the Serialize pretty file. */
-/***********************************************************************/
-bool JOUTPRT::WriteStr(const char *s)
-{
- // This is temporary
- if (B) {
- fputs(EL, Stream);
- M--;
-
- for (int i = 0; i < M; i++)
- fputc('\t', Stream);
-
- B = false;
- } // endif B
-
- fputs(s, Stream);
- return false;
-} // end of WriteStr
-
-/***********************************************************************/
-/* Write a character to the Serialize pretty file. */
-/***********************************************************************/
-bool JOUTPRT::WriteChr(const char c)
-{
- switch (c) {
- case ':':
- fputs(": ", Stream);
- break;
- case '{':
- case '[':
-#if 0
- if (M)
- fputs(EL, Stream);
-
- for (int i = 0; i < M; i++)
- fputc('\t', Stream);
-#endif // 0
-
- fputc(c, Stream);
- fputs(EL, Stream);
- M++;
-
- for (int i = 0; i < M; i++)
- fputc('\t', Stream);
-
- break;
- case '}':
- case ']':
- M--;
- fputs(EL, Stream);
-
- for (int i = 0; i < M; i++)
- fputc('\t', Stream);
-
- fputc(c, Stream);
- B = true;
- break;
- case ',':
- fputc(c, Stream);
- fputs(EL, Stream);
-
- for (int i = 0; i < M; i++)
- fputc('\t', Stream);
-
- B = false;
- break;
- default:
- fputc(c, Stream);
- } // endswitch c
-
-return false;
-} // end of WriteChr
-
-/* -------------------------- Class JOBJECT -------------------------- */
-
-/***********************************************************************/
-/* Add a new pair to an Object. */
-/***********************************************************************/
-PJPR JOBJECT::AddPair(PGLOBAL g, PSZ key)
-{
- PJPR jpp = new(g) JPAIR(key);
-
- if (Last)
- Last->Next = jpp;
- else
- First = jpp;
-
- Last = jpp;
- Size++;
- return jpp;
-} // end of AddPair
-
-/***********************************************************************/
-/* Get the value corresponding to the given key. */
-/***********************************************************************/
-PJVAL JOBJECT::GetValue(const char* key)
-{
- for (PJPR jp = First; jp; jp = jp->Next)
- if (!strcmp(jp->Key, key))
- return jp->Val;
-
- return NULL;
-} // end of GetValue;
-
-/***********************************************************************/
-/* Return the text corresponding to all keys (XML like). */
-/***********************************************************************/
-PSZ JOBJECT::GetText(PGLOBAL g)
-{
- char *p, *text = (char*)PlugSubAlloc(g, NULL, 0);
- bool b = true;
-
- if (!First)
- return NULL;
- else for (PJPR jp = First; jp; jp = jp->Next) {
- if (!(p = jp->Val->GetString()))
- p = "???";
-
- if (b) {
- strcpy(text, p);
- b = false;
- } else
- strcat(strcat(text, " "), p);
-
- } // endfor jp
-
- PlugSubAlloc(g, NULL, strlen(text) + 1);
- return text;
-} // end of GetValue;
-
-/***********************************************************************/
-/* Set or add a value corresponding to the given key. */
-/***********************************************************************/
-void JOBJECT::SetValue(PGLOBAL g, PJVAL jvp, PSZ key)
-{
- PJPR jp;
-
- for (jp = First; jp; jp = jp->Next)
- if (!strcmp(jp->Key, key)) {
- jp->Val = jvp;
- break;
- } // endif key
-
- if (!jp) {
- jp = AddPair(g, key);
- jp->Val = jvp;
- } // endif jp
-
-} // end of SetValue
-
-/* -------------------------- Class JARRAY --------------------------- */
-
-/***********************************************************************/
-/* Make the array of values from the values list. */
-/***********************************************************************/
-void JARRAY::InitArray(PGLOBAL g)
-{
- int i;
- PJVAL jvp;
-
- for (Size = 0, jvp = First; jvp; jvp = jvp->Next)
- if (!jvp->Del)
- Size++;
-
- if (!Size) {
- return;
- } else if (Size > Alloc) {
- // No need to realloc after deleting values
- Mvals = (PJVAL*)PlugSubAlloc(g, NULL, Size * sizeof(PJVAL));
- Alloc = Size;
- } // endif Size
-
- for (i = 0, jvp = First; jvp; jvp = jvp->Next)
- if (!jvp->Del)
- Mvals[i++] = jvp;
-
-} // end of InitArray
-
-/***********************************************************************/
-/* Get the Nth value of an Array. */
-/***********************************************************************/
-PJVAL JARRAY::GetValue(int i)
-{
- if (Mvals && i >= 0 && i < Size)
- return Mvals[i];
- else
- return NULL;
-} // end of GetValue
-
-/***********************************************************************/
-/* Add a Value to the Arrays Value list. */
-/***********************************************************************/
-PJVAL JARRAY::AddValue(PGLOBAL g, PJVAL jvp)
-{
- if (!jvp)
- jvp = new(g) JVALUE;
-
- if (Last)
- Last->Next = jvp;
- else
- First = jvp;
-
- Last = jvp;
- return jvp;
-} // end of AddValue
-
-/***********************************************************************/
-/* Add a Value to the Arrays Value list. */
-/***********************************************************************/
-bool JARRAY::SetValue(PGLOBAL g, PJVAL jvp, int n)
-{
- int i = 0;
- PJVAL jp, *jpp = &First;
-
- for (i = 0, jp = First; i < n; i++, jp = *(jpp = &jp->Next))
- if (!jp)
- *jpp = jp = new(g) JVALUE;
-
- *jpp = jvp;
- jvp->Next = (jp ? jp->Next : NULL);
- return false;
-} // end of SetValue
-
-/***********************************************************************/
-/* Delete a Value from the Arrays Value list. */
-/***********************************************************************/
-bool JARRAY::DeleteValue(int n)
-{
- PJVAL jvp = GetValue(n);
-
- if (jvp) {
- jvp->Del = true;
- return false;
- } else
- return true;
-
-} // end of DeleteValue
-
-/* -------------------------- Class JVALUE- -------------------------- */
-
-/***********************************************************************/
-/* Constructor for a Value with a given string or numeric value. */
-/***********************************************************************/
-JVALUE::JVALUE(PGLOBAL g, PVAL valp) : JSON()
-{
- Jsp = NULL;
- Value = AllocateValue(g, valp);
- Next = NULL;
- Del = false;
-} // end of JVALUE constructor
-
-/***********************************************************************/
-/* Returns the type of the Value's value. */
-/***********************************************************************/
-JTYP JVALUE::GetValType(void)
-{
- if (Jsp)
- return Jsp->GetType();
- else if (Value)
- return (JTYP)Value->GetType();
- else
- return (JTYP)TYPE_VOID;
-
-} // end of GetValType
-
-/***********************************************************************/
-/* Return the Value's Object value. */
-/***********************************************************************/
-PJOB JVALUE::GetObject(void)
-{
- if (Jsp && Jsp->GetType() == TYPE_JOB)
- return (PJOB)Jsp;
-
- return NULL;
-} // end of GetObject
-
-/***********************************************************************/
-/* Return the Value's Array value. */
-/***********************************************************************/
-PJAR JVALUE::GetArray(void)
-{
- if (Jsp && Jsp->GetType() == TYPE_JAR)
- return (PJAR)Jsp;
-
- return NULL;
-} // end of GetArray
-
-/***********************************************************************/
-/* Return the Value's Integer value. */
-/***********************************************************************/
-int JVALUE::GetInteger(void)
-{
- return (Value) ? Value->GetIntValue() : 0;
-} // end of GetInteger
-
-/***********************************************************************/
-/* Return the Value's Double value. */
-/***********************************************************************/
-double JVALUE::GetFloat(void)
-{
- return (Value) ? Value->GetFloatValue() : 0.0;
-} // end of GetFloat
-
-/***********************************************************************/
-/* Return the Value's String value. */
-/***********************************************************************/
-PSZ JVALUE::GetString(void)
-{
- char buf[32];
- return (Value) ? Value->GetCharString(buf) : NULL;
-} // end of GetString
-
+/*************** json CPP Declares Source Code File (.H) ***************/
+/* Name: json.cpp Version 1.0 */
+/* */
+/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */
+/* */
+/* This file contains the JSON classes functions. */
+/***********************************************************************/
+
+/***********************************************************************/
+/* Include relevant sections of the MariaDB header file. */
+/***********************************************************************/
+#include <my_global.h>
+
+/***********************************************************************/
+/* Include application header files: */
+/* global.h is header containing all global declarations. */
+/* plgdbsem.h is header containing the DB application declarations. */
+/* xjson.h is header containing the JSON classes declarations. */
+/***********************************************************************/
+#include "global.h"
+#include "plgdbsem.h"
+#include "json.h"
+
+#define ARGS MY_MIN(24,len-i),s+MY_MAX(i-3,0)
+
+#if defined(WIN32)
+#define EL "\r\n"
+#else
+#define EL "\n"
+#endif
+
+/***********************************************************************/
+/* Parse a json string. */
+/***********************************************************************/
+PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
+{
+ int i, rc;
+ bool b = false;
+ PJSON jsp = NULL;
+ STRG src;
+
+ if (!s || !len) {
+ strcpy(g->Message, "Void JSON object");
+ return NULL;
+ } else if (comma)
+ *comma = false;
+
+ src.str = s;
+ src.len = len;
+
+ // Save stack and allocation environment and prepare error return
+ if (g->jump_level == MAX_JUMP) {
+ strcpy(g->Message, MSG(TOO_MANY_JUMPS));
+ return NULL;
+ } // endif jump_level
+
+ if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
+ goto err;
+ } // endif rc
+
+ for (i = 0; i < len; i++)
+ switch (s[i]) {
+ case '[':
+ if (jsp) {
+ strcpy(g->Message, "More than one item in file");
+ goto err;
+ } else if (!(jsp = ParseArray(g, ++i, src)))
+ goto err;
+
+ break;
+ case '{':
+ if (jsp) {
+ strcpy(g->Message, "More than one item in file");
+ goto err;
+ } else if (!(jsp = ParseObject(g, ++i, src)))
+ goto err;
+
+ break;
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ break;
+ case ',':
+ if (jsp && pretty == 1) {
+ if (comma)
+ *comma = true;
+
+ break;
+ } // endif pretty
+
+ sprintf(g->Message, "Unexpected ',' (pretty=%d)", pretty);
+ goto err;
+ case '"':
+ if (!(jsp = ParseValue(g, i, src)))
+ goto err;
+
+ break;
+ case '(':
+ b = true;
+ break;
+ case ')':
+ if (b) {
+ b = false;
+ break;
+ } // endif b
+
+ default:
+ sprintf(g->Message, "Bad '%c' character near %.*s",
+ s[i], ARGS);
+ goto err;
+ }; // endswitch s[i]
+
+ if (!jsp)
+ sprintf(g->Message, "Invalid Json string '%.*s'", 50, s);
+
+ g->jump_level--;
+ return jsp;
+
+ err:
+ g->jump_level--;
+ return NULL;
+} // end of ParseJson
+
+/***********************************************************************/
+/* Parse a JSON Array. */
+/***********************************************************************/
+PJAR ParseArray(PGLOBAL g, int& i, STRG& src)
+{
+ char *s = src.str;
+ int len = src.len;
+ int level = 0;
+ PJAR jarp = new(g) JARRAY;
+ PJVAL jvp = NULL;
+
+ for (; i < len; i++)
+ switch (s[i]) {
+ case ',':
+ if (level < 2) {
+ sprintf(g->Message, "Unexpected ',' near %.*s",ARGS);
+ return NULL;
+ } else
+ level = 1;
+
+ break;
+ case ']':
+ if (level == 1) {
+ sprintf(g->Message, "Unexpected ',]' near %.*s", ARGS);
+ return NULL;
+ } // endif level
+
+ jarp->InitArray(g);
+ return jarp;
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ break;
+ default:
+ if (level == 2) {
+ sprintf(g->Message, "Unexpected value near %.*s", ARGS);
+ return NULL;
+ } else if ((jvp = ParseValue(g, i, src))) {
+ jarp->AddValue(g, jvp);
+ level = 2;
+ } else
+ return NULL;
+
+ level = 2;
+ break;
+ }; // endswitch s[i]
+
+ strcpy(g->Message, "Unexpected EOF in array");
+ return NULL;
+} // end of ParseArray
+
+/***********************************************************************/
+/* Parse a JSON Object. */
+/***********************************************************************/
+PJOB ParseObject(PGLOBAL g, int& i, STRG& src)
+{
+ PSZ key;
+ char *s = src.str;
+ int len = src.len;
+ int level = 0;
+ PJOB jobp = new(g) JOBJECT;
+ PJPR jpp = NULL;
+
+ for (; i < len; i++)
+ switch (s[i]) {
+ case '"':
+ if (level < 2) {
+ if ((key = ParseString(g, ++i, src))) {
+ jpp = jobp->AddPair(g, key);
+ level = 1;
+ } else
+ return NULL;
+
+ } else {
+ sprintf(g->Message, "misplaced string near %.*s", ARGS);
+ return NULL;
+ } // endif level
+
+ break;
+ case ':':
+ if (level == 1) {
+ if (!(jpp->Val = ParseValue(g, ++i, src)))
+ return NULL;
+
+ level = 2;
+ } else {
+ sprintf(g->Message, "Unexpected ':' near %.*s", ARGS);
+ return NULL;
+ } // endif level
+
+ break;
+ case ',':
+ if (level < 2) {
+ sprintf(g->Message, "Unexpected ',' near %.*s", ARGS);
+ return NULL;
+ } else
+ level = 1;
+
+ break;
+ case '}':
+ if (level == 1) {
+ sprintf(g->Message, "Unexpected '}' near %.*s", ARGS);
+ return NULL;
+ } // endif level
+
+ return jobp;
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ break;
+ default:
+ sprintf(g->Message, "Unexpected character '%c' near %.*s",
+ s[i], ARGS);
+ return NULL;
+ }; // endswitch s[i]
+
+ strcpy(g->Message, "Unexpected EOF in Object");
+ return NULL;
+} // end of ParseObject
+
+/***********************************************************************/
+/* Parse a JSON Value. */
+/***********************************************************************/
+PJVAL ParseValue(PGLOBAL g, int& i, STRG& src)
+{
+ char *strval, *s = src.str;
+ int n, len = src.len;
+ PJVAL jvp = new(g) JVALUE;
+
+ for (; i < len; i++)
+ switch (s[i]) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ break;
+ default:
+ goto suite;
+ } // endswitch
+
+ suite:
+ switch (s[i]) {
+ case '[':
+ if (!(jvp->Jsp = ParseArray(g, ++i, src)))
+ return NULL;
+
+ break;
+ case '{':
+ if (!(jvp->Jsp = ParseObject(g, ++i, src)))
+ return NULL;
+
+ break;
+ case '"':
+ if ((strval = ParseString(g, ++i, src)))
+ jvp->Value = AllocateValue(g, strval, TYPE_STRING);
+ else
+ return NULL;
+
+ break;
+ case 't':
+ if (!strncmp(s + i, "true", 4)) {
+ n = 1;
+ jvp->Value = AllocateValue(g, &n, TYPE_TINY);
+ i += 3;
+ } else
+ goto err;
+
+ break;
+ case 'f':
+ if (!strncmp(s + i, "false", 5)) {
+ n = 0;
+ jvp->Value = AllocateValue(g, &n, TYPE_TINY);
+ i += 4;
+ } else
+ goto err;
+
+ break;
+ case 'n':
+ if (!strncmp(s + i, "null", 4))
+ i += 3;
+ else
+ goto err;
+
+ break;
+ case '-':
+ default:
+ if (s[i] == '-' || isdigit(s[i])) {
+ if (!(jvp->Value = ParseNumeric(g, i, src)))
+ goto err;
+
+ } else
+ goto err;
+
+ }; // endswitch s[i]
+
+ jvp->Size = 1;
+ return jvp;
+
+err:
+ sprintf(g->Message, "Unexpected character '%c' near %.*s",
+ s[i], ARGS);
+ return NULL;
+} // end of ParseValue
+
+/***********************************************************************/
+/* Unescape and parse a JSON string. */
+/***********************************************************************/
+char *ParseString(PGLOBAL g, int& i, STRG& src)
+{
+ char *s = src.str;
+ uchar *p;
+ int n = 0, len = src.len;
+
+ // Be sure of memory availability
+ if (len + 1 - i > (signed)((PPOOLHEADER)g->Sarea)->FreeBlk) {
+ strcpy(g->Message, "ParseString: Out of memory");
+ return NULL;
+ } // endif len
+
+ // The size to allocate is not known yet
+ p = (uchar*)PlugSubAlloc(g, NULL, 0);
+
+ for (; i < len; i++)
+ switch (s[i]) {
+ case '"':
+ p[n++] = 0;
+ PlugSubAlloc(g, NULL, n);
+ return (char*)p;
+ case '\\':
+ if (++i < len) {
+ if (s[i] == 'u') {
+ if (len - i > 5) {
+// if (charset == utf8) {
+ char xs[5];
+ uint hex;
+
+ xs[0] = s[++i];
+ xs[1] = s[++i];
+ xs[2] = s[++i];
+ xs[3] = s[++i];
+ xs[4] = 0;
+ hex = strtoul(xs, NULL, 16);
+
+ if (hex < 0x80) {
+ p[n] = (uchar)hex;
+ } else if (hex < 0x800) {
+ p[n++] = (uchar)(0xC0 | (hex >> 6));
+ p[n] = (uchar)(0x80 | (hex & 0x3F));
+ } else if (hex < 0x10000) {
+ p[n++] = (uchar)(0xE0 | (hex >> 12));
+ p[n++] = (uchar)(0x80 | ((hex >> 6) & 0x3f));
+ p[n] = (uchar)(0x80 | (hex & 0x3f));
+ } else
+ p[n] = '?';
+
+#if 0
+ } else {
+ char xs[3];
+ UINT hex;
+
+ i += 2;
+ xs[0] = s[++i];
+ xs[1] = s[++i];
+ xs[2] = 0;
+ hex = strtoul(xs, NULL, 16);
+ p[n] = (char)hex;
+ } // endif charset
+#endif // 0
+ } else
+ goto err;
+
+ } else switch(s[i]) {
+ case 't': p[n] = '\t'; break;
+ case 'n': p[n] = '\n'; break;
+ case 'r': p[n] = '\r'; break;
+ case 'b': p[n] = '\b'; break;
+ case 'f': p[n] = '\f'; break;
+ default: p[n] = s[i]; break;
+ } // endswitch
+
+ n++;
+ } else
+ goto err;
+
+ break;
+ default:
+ p[n++] = s[i];
+ break;
+ }; // endswitch s[i]
+
+ err:
+ strcpy(g->Message, "Unexpected EOF in String");
+ return NULL;
+} // end of ParseString
+
+/***********************************************************************/
+/* Parse a JSON numeric value. */
+/***********************************************************************/
+PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src)
+{
+ char *s = src.str, buf[50];
+ int n = 0, len = src.len;
+ short nd = 0;
+ bool has_dot = false;
+ bool has_e = false;
+ bool found_digit = false;
+ PVAL valp = NULL;
+
+ for (; i < len; i++) {
+ switch (s[i]) {
+ case '.':
+ if (!found_digit || has_dot || has_e)
+ goto err;
+
+ has_dot = true;
+ break;
+ case 'e':
+ case 'E':
+ if (!found_digit || has_e)
+ goto err;
+
+ has_e = true;
+ found_digit = false;
+ break;
+ case '+':
+ if (!has_e)
+ goto err;
+
+ // passthru
+ case '-':
+ if (found_digit)
+ goto err;
+
+ break;
+ default:
+ if (isdigit(s[i])) {
+ if (has_dot && !has_e)
+ nd++; // Number of decimals
+
+ found_digit = true;
+ } else
+ goto fin;
+
+ }; // endswitch s[i]
+
+ buf[n++] = s[i];
+ } // endfor i
+
+ fin:
+ if (found_digit) {
+ buf[n] = 0;
+
+ if (has_dot || has_e) {
+ double dv = strtod(buf, NULL);
+
+ valp = AllocateValue(g, &dv, TYPE_DOUBLE, nd);
+ } else {
+ int iv = strtol(buf, NULL, 10);
+
+ valp = AllocateValue(g, &iv, TYPE_INT);
+ } // endif has
+
+ i--; // Unstack following character
+ return valp;
+ } else {
+ strcpy(g->Message, "No digit found");
+ return NULL;
+ } // endif found_digit
+
+ err:
+ strcpy(g->Message, "Unexpected EOF in number");
+ return NULL;
+} // end of ParseNumeric
+
+/***********************************************************************/
+/* Serialize a JSON tree: */
+/***********************************************************************/
+PSZ Serialize(PGLOBAL g, PJSON jsp, FILE *fs, int pretty)
+{
+ bool b = false, err = true;
+ JOUT *jp;
+
+ g->Message[0] = 0;
+
+ if (!jsp) {
+ strcpy(g->Message, "Null json tree");
+ return NULL;
+ } else if (!fs) {
+ // Serialize to a string
+ jp = new(g) JOUTSTR(g);
+ b = pretty == 1;
+ } else if (pretty == 2) {
+ // Serialize to a pretty file
+ jp = new(g) JOUTPRT(g, fs);
+ } else {
+ // Serialize to a flat file
+ jp = new(g) JOUTFILE(g, fs);
+ b = pretty == 1;
+ } // endif's
+
+ switch (jsp->GetType()) {
+ case TYPE_JAR:
+ err = SerializeArray(jp, (PJAR)jsp, b);
+ break;
+ case TYPE_JOB:
+ err = (b && jp->WriteChr('\t'));
+ err |= SerializeObject(jp, (PJOB)jsp);
+ break;
+ case TYPE_JVAL:
+ err = SerializeValue(jp, (PJVAL)jsp);
+ break;
+ default:
+ strcpy(g->Message, "Invalid json tree");
+ } // endswitch Type
+
+ if (fs) {
+ fputc('\n', fs);
+ fclose(fs);
+ return (err) ? g->Message : NULL;
+ } else if (!err) {
+ PSZ str = ((JOUTSTR*)jp)->Strp;
+
+ jp->WriteChr('\0');
+ PlugSubAlloc(g, NULL, ((JOUTSTR*)jp)->N);
+ return str;
+ } else {
+ if (!g->Message[0])
+ strcpy(g->Message, "Error in Serialize");
+
+ return NULL;
+ } // endif's
+
+} // end of Serialize
+
+/***********************************************************************/
+/* Serialize a JSON Array. */
+/***********************************************************************/
+bool SerializeArray(JOUT *js, PJAR jarp, bool b)
+{
+ bool first = true;
+
+
+ if (js->WriteChr('['))
+ return true;
+ else if (b && (js->WriteStr(EL) || js->WriteChr('\t')))
+ return true;
+
+ for (int i = 0; i < jarp->size(); i++) {
+ if (first)
+ first = false;
+ else if (js->WriteChr(','))
+ return true;
+ else if (b && (js->WriteStr(EL) || js->WriteChr('\t')))
+ return true;
+
+ if (SerializeValue(js, jarp->GetValue(i)))
+ return true;
+
+ } // endfor i
+
+ if (b && js->WriteStr(EL))
+ return true;
+
+ return js->WriteChr(']');
+} // end of SerializeArray
+
+/***********************************************************************/
+/* Serialize a JSON Object. */
+/***********************************************************************/
+bool SerializeObject(JOUT *js, PJOB jobp)
+{
+ bool first = true;
+
+ if (js->WriteChr('{'))
+ return true;
+
+ for (PJPR pair = jobp->First; pair; pair = pair->Next) {
+ if (first)
+ first = false;
+ else if (js->WriteChr(','))
+ return true;
+
+ if (js->WriteChr('"') ||
+ js->WriteStr(pair->Key) ||
+ js->WriteChr('"') ||
+ js->WriteChr(':') ||
+ SerializeValue(js, pair->Val))
+ return true;
+
+ } // endfor i
+
+ return js->WriteChr('}');
+} // end of SerializeObject
+
+/***********************************************************************/
+/* Serialize a JSON Value. */
+/***********************************************************************/
+bool SerializeValue(JOUT *js, PJVAL jvp)
+{
+ PJAR jap;
+ PJOB jop;
+ PVAL valp;
+
+ if ((jap = jvp->GetArray()))
+ return SerializeArray(js, jap, false);
+ else if ((jop = jvp->GetObject()))
+ return SerializeObject(js, jop);
+ else if (!(valp = jvp->Value) || valp->IsNull())
+ return js->WriteStr("null");
+ else switch (valp->GetType()) {
+ case TYPE_TINY:
+ return js->WriteStr(valp->GetTinyValue() ? "true" : "false");
+ case TYPE_STRING:
+ return js->Escape(valp->GetCharValue());
+ default:
+ if (valp->IsTypeNum()) {
+ char buf[32];
+
+ return js->WriteStr(valp->GetCharString(buf));
+ } // endif valp
+
+ } // endswitch Type
+
+strcpy(js->g->Message, "Unrecognized value");
+return true;
+} // end of SerializeValue
+
+/* -------------------------- Class JOUTSTR -------------------------- */
+
+/***********************************************************************/
+/* JOUTSTR constructor. */
+/***********************************************************************/
+JOUTSTR::JOUTSTR(PGLOBAL g) : JOUT(g)
+{
+ PPOOLHEADER pph = (PPOOLHEADER)g->Sarea;
+
+ N = 0;
+ Max = pph->FreeBlk;
+ Max = (Max > 32) ? Max - 32 : Max;
+ Strp = (char*)PlugSubAlloc(g, NULL, 0); // Size not know yet
+} // end of JOUTSTR constructor
+
+/***********************************************************************/
+/* Concatenate a string to the Serialize string. */
+/***********************************************************************/
+bool JOUTSTR::WriteStr(const char *s)
+{
+ if (s) {
+ size_t len = strlen(s);
+
+ if (N + len > Max)
+ return true;
+
+ memcpy(Strp + N, s, len);
+ N += len;
+ return false;
+ } else
+ return true;
+
+} // end of WriteStr
+
+/***********************************************************************/
+/* Concatenate a character to the Serialize string. */
+/***********************************************************************/
+bool JOUTSTR::WriteChr(const char c)
+{
+ if (N + 1 > Max)
+ return true;
+
+ Strp[N++] = c;
+ return false;
+} // end of WriteChr
+
+/***********************************************************************/
+/* Escape and Concatenate a string to the Serialize string. */
+/***********************************************************************/
+bool JOUTSTR::Escape(const char *s)
+{
+ WriteChr('"');
+
+ for (unsigned int i = 0; i < strlen(s); i++)
+ switch (s[i]) {
+ case '"':
+ case '\\':
+ case '\t':
+ case '\n':
+ case '\r':
+ case '\b':
+ case '\f': WriteChr('\\');
+ // passthru
+ default:
+ WriteChr(s[i]);
+ break;
+ } // endswitch s[i]
+
+ WriteChr('"');
+ return false;
+} // end of Escape
+
+/* ------------------------- Class JOUTFILE -------------------------- */
+
+/***********************************************************************/
+/* Write a string to the Serialize file. */
+/***********************************************************************/
+bool JOUTFILE::WriteStr(const char *s)
+{
+ // This is temporary
+ fputs(s, Stream);
+ return false;
+} // end of WriteStr
+
+/***********************************************************************/
+/* Write a character to the Serialize file. */
+/***********************************************************************/
+bool JOUTFILE::WriteChr(const char c)
+{
+ // This is temporary
+ fputc(c, Stream);
+ return false;
+} // end of WriteChr
+
+/***********************************************************************/
+/* Escape and Concatenate a string to the Serialize string. */
+/***********************************************************************/
+bool JOUTFILE::Escape(const char *s)
+{
+ // This is temporary
+ fputc('"', Stream);
+
+ for (unsigned int i = 0; i < strlen(s); i++)
+ switch (s[i]) {
+ case '"': fputs("\\\"", Stream); break;
+ case '\\': fputs("\\\\", Stream); break;
+ case '\t': fputs("\\t", Stream); break;
+ case '\n': fputs("\\n", Stream); break;
+ case '\r': fputs("\\r", Stream); break;
+ case '\b': fputs("\\b", Stream); break;
+ case '\f': fputs("\\f", Stream); break;
+ default:
+ fputc(s[i], Stream);
+ break;
+ } // endswitch s[i]
+
+ fputc('"', Stream);
+ return false;
+} // end of Escape
+
+/* ------------------------- Class JOUTPRT --------------------------- */
+
+/***********************************************************************/
+/* Write a string to the Serialize pretty file. */
+/***********************************************************************/
+bool JOUTPRT::WriteStr(const char *s)
+{
+ // This is temporary
+ if (B) {
+ fputs(EL, Stream);
+ M--;
+
+ for (int i = 0; i < M; i++)
+ fputc('\t', Stream);
+
+ B = false;
+ } // endif B
+
+ fputs(s, Stream);
+ return false;
+} // end of WriteStr
+
+/***********************************************************************/
+/* Write a character to the Serialize pretty file. */
+/***********************************************************************/
+bool JOUTPRT::WriteChr(const char c)
+{
+ switch (c) {
+ case ':':
+ fputs(": ", Stream);
+ break;
+ case '{':
+ case '[':
+#if 0
+ if (M)
+ fputs(EL, Stream);
+
+ for (int i = 0; i < M; i++)
+ fputc('\t', Stream);
+#endif // 0
+
+ fputc(c, Stream);
+ fputs(EL, Stream);
+ M++;
+
+ for (int i = 0; i < M; i++)
+ fputc('\t', Stream);
+
+ break;
+ case '}':
+ case ']':
+ M--;
+ fputs(EL, Stream);
+
+ for (int i = 0; i < M; i++)
+ fputc('\t', Stream);
+
+ fputc(c, Stream);
+ B = true;
+ break;
+ case ',':
+ fputc(c, Stream);
+ fputs(EL, Stream);
+
+ for (int i = 0; i < M; i++)
+ fputc('\t', Stream);
+
+ B = false;
+ break;
+ default:
+ fputc(c, Stream);
+ } // endswitch c
+
+return false;
+} // end of WriteChr
+
+/* -------------------------- Class JOBJECT -------------------------- */
+
+/***********************************************************************/
+/* Add a new pair to an Object. */
+/***********************************************************************/
+PJPR JOBJECT::AddPair(PGLOBAL g, PSZ key)
+{
+ PJPR jpp = new(g) JPAIR(key);
+
+ if (Last)
+ Last->Next = jpp;
+ else
+ First = jpp;
+
+ Last = jpp;
+ Size++;
+ return jpp;
+} // end of AddPair
+
+/***********************************************************************/
+/* Get the value corresponding to the given key. */
+/***********************************************************************/
+PJVAL JOBJECT::GetValue(const char* key)
+{
+ for (PJPR jp = First; jp; jp = jp->Next)
+ if (!strcmp(jp->Key, key))
+ return jp->Val;
+
+ return NULL;
+} // end of GetValue;
+
+/***********************************************************************/
+/* Return the text corresponding to all keys (XML like). */
+/***********************************************************************/
+PSZ JOBJECT::GetText(PGLOBAL g, PSZ text)
+{
+ int n;
+
+ if (!text) {
+ text = (char*)PlugSubAlloc(g, NULL, 0);
+ text[0] = 0;
+ n = 1;
+ } else
+ n = 0;
+
+ if (!First && n)
+ return NULL;
+ else for (PJPR jp = First; jp; jp = jp->Next)
+ jp->Val->GetText(g, text);
+
+ if (n)
+ PlugSubAlloc(g, NULL, strlen(text) + 1);
+
+ return text + n;
+} // end of GetValue;
+
+/***********************************************************************/
+/* Set or add a value corresponding to the given key. */
+/***********************************************************************/
+void JOBJECT::SetValue(PGLOBAL g, PJVAL jvp, PSZ key)
+{
+ PJPR jp;
+
+ for (jp = First; jp; jp = jp->Next)
+ if (!strcmp(jp->Key, key)) {
+ jp->Val = jvp;
+ break;
+ } // endif key
+
+ if (!jp) {
+ jp = AddPair(g, key);
+ jp->Val = jvp;
+ } // endif jp
+
+} // end of SetValue
+
+/***********************************************************************/
+/* True if void or if all members are nulls. */
+/***********************************************************************/
+bool JOBJECT::IsNull(void)
+{
+ for (PJPR jp = First; jp; jp = jp->Next)
+ if (!jp->Val->IsNull())
+ return false;
+
+ return true;
+} // end of IsNull
+
+/* -------------------------- Class JARRAY --------------------------- */
+
+/***********************************************************************/
+/* Make the array of values from the values list. */
+/***********************************************************************/
+void JARRAY::InitArray(PGLOBAL g)
+{
+ int i;
+ PJVAL jvp;
+
+ for (Size = 0, jvp = First; jvp; jvp = jvp->Next)
+ if (!jvp->Del)
+ Size++;
+
+ if (!Size) {
+ return;
+ } else if (Size > Alloc) {
+ // No need to realloc after deleting values
+ Mvals = (PJVAL*)PlugSubAlloc(g, NULL, Size * sizeof(PJVAL));
+ Alloc = Size;
+ } // endif Size
+
+ for (i = 0, jvp = First; jvp; jvp = jvp->Next)
+ if (!jvp->Del)
+ Mvals[i++] = jvp;
+
+} // end of InitArray
+
+/***********************************************************************/
+/* Get the Nth value of an Array. */
+/***********************************************************************/
+PJVAL JARRAY::GetValue(int i)
+{
+ if (Mvals && i >= 0 && i < Size)
+ return Mvals[i];
+ else
+ return NULL;
+} // end of GetValue
+
+/***********************************************************************/
+/* Add a Value to the Arrays Value list. */
+/***********************************************************************/
+PJVAL JARRAY::AddValue(PGLOBAL g, PJVAL jvp)
+{
+ if (!jvp)
+ jvp = new(g) JVALUE;
+
+ if (Last)
+ Last->Next = jvp;
+ else
+ First = jvp;
+
+ Last = jvp;
+ return jvp;
+} // end of AddValue
+
+/***********************************************************************/
+/* Add a Value to the Arrays Value list. */
+/***********************************************************************/
+bool JARRAY::SetValue(PGLOBAL g, PJVAL jvp, int n)
+{
+ int i = 0;
+ PJVAL jp, *jpp = &First;
+
+ for (i = 0, jp = First; i < n; i++, jp = *(jpp = &jp->Next))
+ if (!jp)
+ *jpp = jp = new(g) JVALUE;
+
+ *jpp = jvp;
+ jvp->Next = (jp ? jp->Next : NULL);
+ return false;
+} // end of SetValue
+
+/***********************************************************************/
+/* Delete a Value from the Arrays Value list. */
+/***********************************************************************/
+bool JARRAY::DeleteValue(int n)
+{
+ PJVAL jvp = GetValue(n);
+
+ if (jvp) {
+ jvp->Del = true;
+ return false;
+ } else
+ return true;
+
+} // end of DeleteValue
+
+/***********************************************************************/
+/* True if void or if all members are nulls. */
+/***********************************************************************/
+bool JARRAY::IsNull(void)
+{
+ for (int i = 0; i < Size; i++)
+ if (!Mvals[i]->IsNull())
+ return false;
+
+ return true;
+} // end of IsNull
+
+/* -------------------------- Class JVALUE- -------------------------- */
+
+/***********************************************************************/
+/* Constructor for a Value with a given string or numeric value. */
+/***********************************************************************/
+JVALUE::JVALUE(PGLOBAL g, PVAL valp) : JSON()
+{
+ Jsp = NULL;
+ Value = AllocateValue(g, valp);
+ Next = NULL;
+ Del = false;
+} // end of JVALUE constructor
+
+/***********************************************************************/
+/* Returns the type of the Value's value. */
+/***********************************************************************/
+JTYP JVALUE::GetValType(void)
+{
+ if (Jsp)
+ return Jsp->GetType();
+ else if (Value)
+ return (JTYP)Value->GetType();
+ else
+ return (JTYP)TYPE_VOID;
+
+} // end of GetValType
+
+/***********************************************************************/
+/* Return the Value's Object value. */
+/***********************************************************************/
+PJOB JVALUE::GetObject(void)
+{
+ if (Jsp && Jsp->GetType() == TYPE_JOB)
+ return (PJOB)Jsp;
+
+ return NULL;
+} // end of GetObject
+
+/***********************************************************************/
+/* Return the Value's Array value. */
+/***********************************************************************/
+PJAR JVALUE::GetArray(void)
+{
+ if (Jsp && Jsp->GetType() == TYPE_JAR)
+ return (PJAR)Jsp;
+
+ return NULL;
+} // end of GetArray
+
+/***********************************************************************/
+/* Return the Value's Integer value. */
+/***********************************************************************/
+int JVALUE::GetInteger(void)
+{
+ return (Value) ? Value->GetIntValue() : 0;
+} // end of GetInteger
+
+/***********************************************************************/
+/* Return the Value's Double value. */
+/***********************************************************************/
+double JVALUE::GetFloat(void)
+{
+ return (Value) ? Value->GetFloatValue() : 0.0;
+} // end of GetFloat
+
+/***********************************************************************/
+/* Return the Value's String value. */
+/***********************************************************************/
+PSZ JVALUE::GetString(void)
+{
+ char buf[32];
+ return (Value) ? Value->GetCharString(buf) : NULL;
+} // end of GetString
+
+/***********************************************************************/
+/* Return the Value's String value. */
+/***********************************************************************/
+PSZ JVALUE::GetText(PGLOBAL g, PSZ text)
+{
+ if (Jsp && Jsp->GetType() == TYPE_JOB)
+ return Jsp->GetText(g, text);
+
+ char buf[32];
+ PSZ s = (Value) ? Value->GetCharString(buf) : NULL;
+
+ if (s)
+ strcat(strcat(text, " "), s);
+ else
+ strcat(text, " ???");
+
+ return text;
+} // end of GetText
+
+/***********************************************************************/
+/* Set the Value's value as the given integer. */
+/***********************************************************************/
+void JVALUE::SetInteger(PGLOBAL g, int n)
+{
+ Value = AllocateValue(g, &n, TYPE_INT);
+} // end of AddInteger
+
+/***********************************************************************/
+/* Set the Value's value as the given DOUBLE. */
+/***********************************************************************/
+void JVALUE::SetFloat(PGLOBAL g, double f)
+{
+ Value = AllocateValue(g, &f, TYPE_DOUBLE, 6);
+} // end of AddFloat
+
+/***********************************************************************/
+/* Set the Value's value as the given string. */
+/***********************************************************************/
+void JVALUE::SetString(PGLOBAL g, PSZ s)
+{
+ Value = AllocateValue(g, s, TYPE_STRING);
+} // end of AddFloat
+
+/***********************************************************************/
+/* True when its JSON or normal value is null. */
+/***********************************************************************/
+bool JVALUE::IsNull(void)
+{
+ return (Jsp) ? Jsp->IsNull() : (Value) ? Value->IsNull() : true;
+} // end of IsNull
+
diff --git a/storage/connect/json.h b/storage/connect/json.h
index 11e15c3acd4..cdf9034e07f 100644
--- a/storage/connect/json.h
+++ b/storage/connect/json.h
@@ -18,7 +18,8 @@ enum JTYP {TYPE_STRG = 1,
TYPE_BOOL = 4,
TYPE_INTG = 7,
TYPE_JSON = 12,
- TYPE_JAR, TYPE_JOB,
+ TYPE_JAR,
+ TYPE_JOB,
TYPE_JVAL};
class JOUT;
@@ -151,12 +152,16 @@ class JSON : public BLOCK {
virtual int GetInteger(void) {X return 0;}
virtual double GetFloat() {X return 0.0;}
virtual PSZ GetString() {X return NULL;}
- virtual PSZ GetText(PGLOBAL g) {X return NULL;}
+ virtual PSZ GetText(PGLOBAL g, PSZ text) {X return NULL;}
virtual bool SetValue(PGLOBAL g, PJVAL jvp, int i) {X return true;}
virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key) {X}
virtual void SetValue(PVAL valp) {X}
virtual void SetValue(PJSON jsp) {X}
+ virtual void SetString(PGLOBAL g, PSZ s) {X}
+ virtual void SetInteger(PGLOBAL g, int n) {X}
+ virtual void SetFloat(PGLOBAL g, double f) {X}
virtual bool DeleteValue(int i) {X return true;}
+ virtual bool IsNull(void) {X return true;}
protected:
int Size;
@@ -171,13 +176,16 @@ class JOBJECT : public JSON {
public:
JOBJECT(void) : JSON() {First = Last = NULL;}
+ using JSON::GetValue;
+ using JSON::SetValue;
virtual void Clear(void) {First = Last = NULL; Size = 0;}
virtual JTYP GetType(void) {return TYPE_JOB;}
virtual PJPR AddPair(PGLOBAL g, PSZ key);
virtual PJOB GetObject(void) {return this;}
virtual PJVAL GetValue(const char* key);
- virtual PSZ GetText(PGLOBAL g);
+ virtual PSZ GetText(PGLOBAL g, PSZ text);
virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key);
+ virtual bool IsNull(void);
protected:
PJPR First;
@@ -192,6 +200,8 @@ class JARRAY : public JSON {
public:
JARRAY(void) : JSON() {Alloc = 0; First = Last = NULL; Mvals = NULL;}
+ using JSON::GetValue;
+ using JSON::SetValue;
virtual void Clear(void) {First = Last = NULL; Size = 0;}
virtual JTYP GetType(void) {return TYPE_JAR;}
virtual PJAR GetArray(void) {return this;}
@@ -200,6 +210,7 @@ class JARRAY : public JSON {
virtual PJVAL GetValue(int i);
virtual bool SetValue(PGLOBAL g, PJVAL jvp, int i);
virtual bool DeleteValue(int n);
+ virtual bool IsNull(void);
protected:
// Members
@@ -223,6 +234,8 @@ class JVALUE : public JSON {
{Jsp = jsp; Value = NULL; Next = NULL; Del = false;}
JVALUE(PGLOBAL g, PVAL valp);
+ using JSON::GetValue;
+ using JSON::SetValue;
virtual void Clear(void)
{Jsp = NULL; Value = NULL; Next = NULL; Del = false; Size = 0;}
virtual JTYP GetType(void) {return TYPE_JVAL;}
@@ -234,8 +247,13 @@ class JVALUE : public JSON {
virtual int GetInteger(void);
virtual double GetFloat(void);
virtual PSZ GetString(void);
+ virtual PSZ GetText(PGLOBAL g, PSZ text);
virtual void SetValue(PVAL valp) {Value = valp;}
virtual void SetValue(PJSON jsp) {Jsp = jsp;}
+ virtual void SetString(PGLOBAL g, PSZ s);
+ virtual void SetInteger(PGLOBAL g, int n);
+ virtual void SetFloat(PGLOBAL g, double f);
+ virtual bool IsNull(void);
protected:
PJSON Jsp; // To the json value
diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp
new file mode 100644
index 00000000000..194cb6defd6
--- /dev/null
+++ b/storage/connect/jsonudf.cpp
@@ -0,0 +1,626 @@
+/************* jsonudf C++ Program Source Code File (.CPP) *************/
+/* PROGRAM NAME: jsonudf Version 1.0 */
+/* (C) Copyright to the author Olivier BERTRAND 2015 */
+/* This program are the JSON User Defined Functions . */
+/***********************************************************************/
+
+/***********************************************************************/
+/* Include relevant sections of the MariaDB header file. */
+/***********************************************************************/
+#include <my_global.h>
+#include <mysqld.h>
+#include <mysql.h>
+#include <sql_error.h>
+
+#include "global.h"
+#include "plgdbsem.h"
+#include "json.h"
+
+#define MEMFIX 512
+
+uint GetJsonGrpSize(void);
+
+extern "C" {
+DllExport my_bool Json_Value_init(UDF_INIT*, UDF_ARGS*, char*);
+DllExport char *Json_Value(UDF_INIT*, UDF_ARGS*, char*,
+ unsigned long*, char *, char *);
+DllExport void Json_Value_deinit(UDF_INIT*);
+DllExport my_bool Json_Array_init(UDF_INIT*, UDF_ARGS*, char*);
+DllExport char *Json_Array(UDF_INIT*, UDF_ARGS*, char*,
+ unsigned long*, char *, char *);
+DllExport void Json_Array_deinit(UDF_INIT*);
+DllExport my_bool Json_Array_Add_init(UDF_INIT*, UDF_ARGS*, char*);
+DllExport char *Json_Array_Add(UDF_INIT*, UDF_ARGS*, char*,
+ unsigned long*, char *, char *);
+DllExport void Json_Array_Add_deinit(UDF_INIT*);
+DllExport my_bool Json_Object_init(UDF_INIT*, UDF_ARGS*, char*);
+DllExport char *Json_Object(UDF_INIT*, UDF_ARGS*, char*,
+ unsigned long*, char *, char *);
+DllExport void Json_Object_deinit(UDF_INIT*);
+DllExport my_bool Json_Object_Nonull_init(UDF_INIT*, UDF_ARGS*, char*);
+DllExport char *Json_Object_Nonull(UDF_INIT*, UDF_ARGS*, char*,
+ unsigned long*, char *, char *);
+DllExport void Json_Object_Nonull_deinit(UDF_INIT*);
+DllExport my_bool Json_Array_Grp_init(UDF_INIT*, UDF_ARGS*, char*);
+DllExport void Json_Array_Grp_add(UDF_INIT *, UDF_ARGS *, char *, char *);
+DllExport char *Json_Array_Grp(UDF_INIT*, UDF_ARGS*, char*,
+ unsigned long*, char *, char *);
+DllExport void Json_Array_Grp_clear(UDF_INIT *, char *, char *);
+DllExport void Json_Array_Grp_deinit(UDF_INIT*);
+DllExport my_bool Json_Object_Grp_init(UDF_INIT*, UDF_ARGS*, char*);
+DllExport void Json_Object_Grp_add(UDF_INIT *, UDF_ARGS *, char *, char *);
+DllExport char *Json_Object_Grp(UDF_INIT*, UDF_ARGS*, char*,
+ unsigned long*, char *, char *);
+DllExport void Json_Object_Grp_clear(UDF_INIT *, char *, char *);
+DllExport void Json_Object_Grp_deinit(UDF_INIT*);
+} // extern "C"
+
+/***********************************************************************/
+/* Allocate and initialise the memory area. */
+/***********************************************************************/
+static my_bool JsonInit(UDF_INIT *initid, char *message,
+ unsigned long reslen, unsigned long memlen)
+{
+ PGLOBAL g = PlugInit(NULL, memlen);
+
+ if (!g) {
+ strcpy(message, "Allocation error");
+ return true;
+ } else if (g->Sarea_Size == 0) {
+ strcpy(message, g->Message);
+ PlugExit(g);
+ return true;
+ } else
+ initid->ptr = (char*)g;
+
+ initid->maybe_null = false;
+ initid->max_length = reslen;
+ return false;
+} // end of Json_Object_init
+
+/***********************************************************************/
+/* Returns true if the argument is a JSON string. */
+/***********************************************************************/
+static my_bool IsJson(UDF_ARGS *args, int i)
+{
+ return (args->arg_type[i] == STRING_RESULT &&
+ !strnicmp(args->attributes[i], "Json_", 5));
+} // end of IsJson
+
+/***********************************************************************/
+/* Calculate the reslen and memlen needed by a function. */
+/***********************************************************************/
+static my_bool CalcLen(UDF_ARGS *args, my_bool obj,
+ unsigned long& reslen, unsigned long& memlen)
+{
+ unsigned long i, k;
+ reslen = args->arg_count + 2;
+
+ // Calculate the result max length
+ for (i = 0; i < args->arg_count; i++) {
+ if (obj) {
+ if (!(k = args->attribute_lengths[i]))
+ k = strlen(args->attributes[i]);
+
+ reslen += (k + 3); // For quotes and :
+ } // endif obj
+
+ switch (args->arg_type[i]) {
+ case STRING_RESULT:
+ if (IsJson(args, i))
+ reslen += args->lengths[i];
+ else
+ reslen += (args->lengths[i] + 1) * 2; // Pessimistic !
+
+ break;
+ case INT_RESULT:
+ reslen += 20;
+ break;
+ case REAL_RESULT:
+ reslen += 31;
+ break;
+ case DECIMAL_RESULT:
+ reslen += (args->lengths[i] + 7); // 6 decimals
+ break;
+ case TIME_RESULT:
+ case ROW_RESULT:
+ case IMPOSSIBLE_RESULT:
+ default:
+ // What should we do here ?
+ break;
+ } // endswitch arg_type
+
+ } // endfor i
+
+ // Calculate the amount of memory needed
+ memlen = MEMFIX + sizeof(JOUTSTR) + reslen;
+
+ for (i = 0; i < args->arg_count; i++) {
+ memlen += (args->lengths[i] + sizeof(JVALUE));
+
+ if (obj) {
+ if (!(k = args->attribute_lengths[i]))
+ k = strlen(args->attributes[i]);
+
+ memlen += (k + sizeof(JOBJECT) + sizeof(JPAIR));
+ } else
+ memlen += sizeof(JARRAY);
+
+ switch (args->arg_type[i]) {
+ case STRING_RESULT:
+ if (IsJson(args, i))
+ memlen += args->lengths[i] * 5; // Estimate parse memory
+
+ memlen += sizeof(TYPVAL<PSZ>);
+ break;
+ case INT_RESULT:
+ memlen += sizeof(TYPVAL<int>);
+ break;
+ case REAL_RESULT:
+ case DECIMAL_RESULT:
+ memlen += sizeof(TYPVAL<double>);
+ break;
+ case TIME_RESULT:
+ case ROW_RESULT:
+ case IMPOSSIBLE_RESULT:
+ default:
+ // What should we do here ?
+ break;
+ } // endswitch arg_type
+
+ } // endfor i
+
+ return false;
+} // end of CalcLen
+
+/***********************************************************************/
+/* Make a zero terminated string from the passed argument. */
+/***********************************************************************/
+static PSZ MakePSZ(PGLOBAL g, UDF_ARGS *args, int i)
+{
+ if (args->args[i]) {
+ int n = args->lengths[i];
+ PSZ s = (PSZ)PlugSubAlloc(g, NULL, n + 1);
+
+ memcpy(s, args->args[i], n);
+ s[n] = 0;
+ return s;
+ } else
+ return NULL;
+
+} // end of MakePSZ
+
+/***********************************************************************/
+/* Make a valid key from the passed argument. */
+/***********************************************************************/
+static PSZ MakeKey(PGLOBAL g, UDF_ARGS *args, int i)
+{
+ int n = args->attribute_lengths[i];
+ bool b; // true if attribute is zero terminated
+ PSZ p, s = args->attributes[i];
+
+ if (s && *s && (n || *s == '\'')) {
+ if ((b = (!n || !s[n])))
+ n = strlen(s);
+
+ if (n > 5 && IsJson(args, i)) {
+ s += 5;
+ n -= 5;
+ } else if (*s == '\'' && s[n-1] == '\'') {
+ s++;
+ n -= 2;
+ b = false;
+ } // endif *s
+
+ if (n < 1)
+ return "Key";
+
+ if (!b) {
+ p = (PSZ)PlugSubAlloc(g, NULL, n + 1);
+ memcpy(p, s, n);
+ p[n] = 0;
+ s = p;
+ } // endif b
+
+ } // endif s
+
+ return s;
+} // end of MakeKey
+
+/***********************************************************************/
+/* Make a JSON value from the passed argument. */
+/***********************************************************************/
+static PJVAL MakeValue(PGLOBAL g, UDF_ARGS *args, int i)
+{
+ char *sap = (args->arg_count > (unsigned)i) ? args->args[i] : NULL;
+ PJSON jsp;
+ PJVAL jvp = new(g) JVALUE;
+
+ if (sap) switch (args->arg_type[i]) {
+ case STRING_RESULT:
+ if (args->lengths[i]) {
+ if (IsJson(args, i)) {
+ if (!(jsp = ParseJson(g, sap, args->lengths[i], 0)))
+ push_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, 0,
+ g->Message);
+
+ if (jsp && jsp->GetType() == TYPE_JVAL)
+ jvp = (PJVAL)jsp;
+ else
+ jvp->SetValue(jsp);
+
+ } else
+ jvp->SetString(g, MakePSZ(g, args, i));
+
+ } // endif str
+
+ break;
+ case INT_RESULT:
+ jvp->SetInteger(g, *(int*)sap);
+ break;
+ case REAL_RESULT:
+ jvp->SetFloat(g, *(double*)sap);
+ break;
+ case DECIMAL_RESULT:
+ jvp->SetFloat(g, atof(MakePSZ(g, args, i)));
+ break;
+ case TIME_RESULT:
+ case ROW_RESULT:
+ case IMPOSSIBLE_RESULT:
+ default:
+ break;
+ } // endswitch arg_type
+
+ return jvp;
+} // end of MakeValue
+
+/***********************************************************************/
+/* Make a Json value containing the parameter. */
+/***********************************************************************/
+my_bool Json_Value_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ unsigned long reslen, memlen;
+
+ if (args->arg_count > 1) {
+ strcpy(message, "Json_Value cannot accept more than 1 argument");
+ return true;
+ } else
+ CalcLen(args, false, reslen, memlen);
+
+ return JsonInit(initid, message, reslen, memlen);
+} // end of Json_Value_init
+
+char *Json_Value(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *error)
+{
+ char *str;
+ PJVAL jvp;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ PlugSubSet(g, g->Sarea, g->Sarea_Size);
+ jvp = MakeValue(g, args, 0);
+
+ if (!(str = Serialize(g, jvp, NULL, 0)))
+ str = strcpy(result, g->Message);
+
+ *res_length = strlen(str);
+ return str;
+} // end of Json_Value
+
+void Json_Value_deinit(UDF_INIT* initid)
+{
+ PlugExit((PGLOBAL)initid->ptr);
+} // end of Json_Value_deinit
+
+/***********************************************************************/
+/* Make a Json array containing all the parameters. */
+/***********************************************************************/
+my_bool Json_Array_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ unsigned long reslen, memlen;
+
+ CalcLen(args, false, reslen, memlen);
+ return JsonInit(initid, message, reslen, memlen);
+} // end of Json_Array_init
+
+char *Json_Array(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *error)
+{
+ char *str;
+ uint i;
+ PJAR arp;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ PlugSubSet(g, g->Sarea, g->Sarea_Size);
+ arp = new(g) JARRAY;
+
+ for (i = 0; i < args->arg_count; i++)
+ arp->AddValue(g, MakeValue(g, args, i));
+
+ arp->InitArray(g);
+
+ if (!(str = Serialize(g, arp, NULL, 0)))
+ str = strcpy(result, g->Message);
+
+ *res_length = strlen(str);
+ return str;
+} // end of Json_Array
+
+void Json_Array_deinit(UDF_INIT* initid)
+{
+ PlugExit((PGLOBAL)initid->ptr);
+} // end of Json_Array_deinit
+
+/***********************************************************************/
+/* Add values to a Json array. */
+/***********************************************************************/
+my_bool Json_Array_Add_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ unsigned long reslen, memlen;
+
+ if (args->arg_count < 2) {
+ strcpy(message, "Json_Value_Add must have at least 2 arguments");
+ return true;
+ } else if (!IsJson(args, 0)) {
+ strcpy(message, "Json_Value_Add first argument must be a json item");
+ return true;
+ } else
+ CalcLen(args, false, reslen, memlen);
+
+ return JsonInit(initid, message, reslen, memlen);
+} // end of Json_Array_Add_init
+
+char *Json_Array_Add(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *error)
+{
+ char *str;
+ PJVAL jvp;
+ PJAR arp;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ PlugSubSet(g, g->Sarea, g->Sarea_Size);
+ jvp = MakeValue(g, args, 0);
+
+ if (jvp->GetValType() != TYPE_JAR) {
+ arp = new(g) JARRAY;
+ arp->AddValue(g, jvp);
+ } else
+ arp = jvp->GetArray();
+
+ for (uint i = 1; i < args->arg_count; i++)
+ arp->AddValue(g, MakeValue(g, args, i));
+
+ arp->InitArray(g);
+
+ if (!(str = Serialize(g, arp, NULL, 0)))
+ str = strcpy(result, g->Message);
+
+ *res_length = strlen(str);
+ return str;
+} // end of Json_Array_Add
+
+void Json_Array_Add_deinit(UDF_INIT* initid)
+{
+ PlugExit((PGLOBAL)initid->ptr);
+} // end of Json_Array_Add_deinit
+
+/***********************************************************************/
+/* Make a Json Oject containing all the parameters. */
+/***********************************************************************/
+my_bool Json_Object_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ unsigned long reslen, memlen;
+
+ CalcLen(args, true, reslen, memlen);
+ return JsonInit(initid, message, reslen, memlen);
+} // end of Json_Object_init
+
+char *Json_Object(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *error)
+{
+ char *str;
+ uint i;
+ PJOB objp;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ PlugSubSet(g, g->Sarea, g->Sarea_Size);
+ objp = new(g) JOBJECT;
+
+ for (i = 0; i < args->arg_count; i++)
+ objp->SetValue(g, MakeValue(g, args, i), MakeKey(g, args, i));
+
+ if (!(str = Serialize(g, objp, NULL, 0)))
+ str = strcpy(result, g->Message);
+
+ *res_length = strlen(str);
+ return str;
+} // end of Json_Object
+
+void Json_Object_deinit(UDF_INIT* initid)
+{
+ PlugExit((PGLOBAL)initid->ptr);
+} // end of Json_Object_deinit
+
+/***********************************************************************/
+/* Make a Json Oject containing all not null parameters. */
+/***********************************************************************/
+my_bool Json_Object_Nonull_init(UDF_INIT *initid, UDF_ARGS *args,
+ char *message)
+{
+ unsigned long reslen, memlen;
+
+ CalcLen(args, true, reslen, memlen);
+ return JsonInit(initid, message, reslen, memlen);
+} // end of Json_Object_Nonull_init
+
+char *Json_Object_Nonull(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *error)
+{
+ char *str;
+ uint i;
+ PJOB objp;
+ PJVAL jvp;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ PlugSubSet(g, g->Sarea, g->Sarea_Size);
+ objp = new(g) JOBJECT;
+
+ for (i = 0; i < args->arg_count; i++)
+ if (!(jvp = MakeValue(g, args, i))->IsNull())
+ objp->SetValue(g, jvp, MakeKey(g, args, i));
+
+ if (!(str = Serialize(g, objp, NULL, 0)))
+ str = strcpy(result, g->Message);
+
+ *res_length = strlen(str);
+ return str;
+} // end of Json_Object_Nonull
+
+void Json_Object_Nonull_deinit(UDF_INIT* initid)
+{
+ PlugExit((PGLOBAL)initid->ptr);
+} // end of Json_Object_nonull_deinit
+
+/***********************************************************************/
+/* Make a Json array from values comming from rows. */
+/***********************************************************************/
+my_bool Json_Array_Grp_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ unsigned long reslen, memlen, n = GetJsonGrpSize();
+
+ if (args->arg_count != 1) {
+ strcpy(message, "Json_Array_Grp can only accept 1 argument");
+ return true;
+ } else
+ CalcLen(args, false, reslen, memlen);
+
+ reslen *= n;
+ memlen += ((memlen - MEMFIX) * (n - 1));
+
+ if (JsonInit(initid, message, reslen, memlen))
+ return true;
+
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ PlugSubSet(g, g->Sarea, g->Sarea_Size);
+ g->Activityp = (PACTIVITY)new(g) JARRAY;
+ g->N = (int)n;
+ return false;
+} // end of Json_Array_Grp_init
+
+void Json_Array_Grp_add(UDF_INIT *initid, UDF_ARGS *args,
+ char *is_null, char *error)
+{
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+ PJAR arp = (PJAR)g->Activityp;
+
+ if (g->N-- > 0)
+ arp->AddValue(g, MakeValue(g, args, 0));
+
+} // end of Json_Array_Grp_add
+
+char *Json_Array_Grp(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *error)
+{
+ char *str;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+ PJAR arp = (PJAR)g->Activityp;
+
+ if (g->N < 0)
+ push_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, 0,
+ "Result truncated to json_grp_size values");
+
+ arp->InitArray(g);
+
+ if (!(str = Serialize(g, arp, NULL, 0)))
+ str = strcpy(result, g->Message);
+
+ *res_length = strlen(str);
+ return str;
+} // end of Json_Array_Grp
+
+void Json_Array_Grp_clear(UDF_INIT *initid, char *is_null, char *error)
+{
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ PlugSubSet(g, g->Sarea, g->Sarea_Size);
+ g->Activityp = (PACTIVITY)new(g) JARRAY;
+ g->N = GetJsonGrpSize();
+} // end of Json_Array_Grp_clear
+
+void Json_Array_Grp_deinit(UDF_INIT* initid)
+{
+ PlugExit((PGLOBAL)initid->ptr);
+} // end of Json_Array_Grp_deinit
+
+/***********************************************************************/
+/* Make a Json object from values comming from rows. */
+/***********************************************************************/
+my_bool Json_Object_Grp_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ unsigned long reslen, memlen, n = GetJsonGrpSize();
+
+ if (args->arg_count != 2) {
+ strcpy(message, "Json_Array_Grp can only accept 2 arguments");
+ return true;
+ } else
+ CalcLen(args, true, reslen, memlen);
+
+ reslen *= n;
+ memlen += ((memlen - MEMFIX) * (n - 1));
+
+ if (JsonInit(initid, message, reslen, memlen))
+ return true;
+
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ PlugSubSet(g, g->Sarea, g->Sarea_Size);
+ g->Activityp = (PACTIVITY)new(g) JOBJECT;
+ g->N = (int)n;
+ return false;
+} // end of Json_Object_Grp_init
+
+void Json_Object_Grp_add(UDF_INIT *initid, UDF_ARGS *args,
+ char *is_null, char *error)
+{
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+ PJOB objp = (PJOB)g->Activityp;
+
+ if (g->N-- > 0)
+ objp->SetValue(g, MakeValue(g, args, 0), MakePSZ(g, args, 1));
+
+} // end of Json_Object_Grp_add
+
+char *Json_Object_Grp(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *error)
+{
+ char *str;
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+ PJOB objp = (PJOB)g->Activityp;
+
+ if (g->N < 0)
+ push_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, 0,
+ "Result truncated to json_grp_size values");
+
+ if (!(str = Serialize(g, objp, NULL, 0)))
+ str = strcpy(result, g->Message);
+
+ *res_length = strlen(str);
+ return str;
+} // end of Json_Object_Grp
+
+void Json_Object_Grp_clear(UDF_INIT *initid, char *is_null, char *error)
+{
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+
+ PlugSubSet(g, g->Sarea, g->Sarea_Size);
+ g->Activityp = (PACTIVITY)new(g) JOBJECT;
+ g->N = GetJsonGrpSize();
+} // end of Json_Object_Grp_clear
+
+void Json_Object_Grp_deinit(UDF_INIT* initid)
+{
+ PlugExit((PGLOBAL)initid->ptr);
+} // end of Json_Object_Grp_deinit
+
+
diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp
index 2f3d75b52fa..47d781d9ff6 100644
--- a/storage/connect/myconn.cpp
+++ b/storage/connect/myconn.cpp
@@ -51,7 +51,8 @@
#define DLL_EXPORT // Items are exported from this DLL
#include "myconn.h"
-extern "C" int zconv;
+//extern "C" int zconv;
+int GetConvSize(void);
extern MYSQL_PLUGIN_IMPORT uint mysqld_port;
extern MYSQL_PLUGIN_IMPORT char *mysqld_unix_port;
@@ -265,7 +266,7 @@ PQRYRES MyColumns(PGLOBAL g, THD *thd, const char *host, const char *db,
return NULL;
} else if (type == TYPE_STRING) {
if (v == 'X') {
- len = zconv;
+ len = GetConvSize();
sprintf(g->Message, "Column %s converted to varchar(%d)",
colname, len);
PushWarning(g, thd);
diff --git a/storage/connect/mysql-test/connect/r/json.result b/storage/connect/mysql-test/connect/r/json.result
index 094bb669d18..ebcad699759 100644
--- a/storage/connect/mysql-test/connect/r/json.result
+++ b/storage/connect/mysql-test/connect/r/json.result
@@ -12,7 +12,7 @@ TRANSLATION CHAR(32),
TRANSLATOR CHAR(80),
PUBLISHER CHAR(32),
DATEPUB int(4)
-) ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.jsn';
+) ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
SELECT * FROM t1;
ISBN LANG SUBJECT AUTHOR TITLE TRANSLATION TRANSLATOR PUBLISHER DATEPUB
9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML Eyrolles Paris 1999
@@ -34,7 +34,7 @@ Publisher CHAR(20) FIELD_FORMAT='PUBLISHER:NAME',
Location CHAR(16) FIELD_FORMAT='PUBLISHER:PLACE',
Year int(4) FIELD_FORMAT='DATEPUB'
)
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
SELECT * FROM t1;
ISBN Language Subject Authors Title Translation Translator Publisher Location Year
9782212090819 fr applications 2 Construire une application XML Eyrolles Paris 1999
@@ -57,7 +57,7 @@ Publisher CHAR(20) FIELD_FORMAT='PUBLISHER:NAME',
Location CHAR(16) FIELD_FORMAT='PUBLISHER:PLACE',
Year int(4) FIELD_FORMAT='DATEPUB'
)
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
SELECT * FROM t1;
ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher Location Year
9782212090819 fr applications Jean-Christophe and François Bernadac and Knab Construire une application XML Eyrolles Paris 1999
@@ -80,7 +80,7 @@ Publisher CHAR(20) FIELD_FORMAT='PUBLISHER:NAME',
Location CHAR(16) FIELD_FORMAT='PUBLISHER:PLACE',
Year int(4) FIELD_FORMAT='DATEPUB'
)
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
SELECT * FROM t1;
ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher Location Year
9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML Eyrolles Paris 1999
@@ -89,23 +89,23 @@ ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher L
UPDATE t1 SET AuthorFN = 'Philippe' WHERE AuthorLN = 'Knab';
SELECT * FROM t1 WHERE ISBN = '9782212090819';
ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher Location Year
-9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML Eyrolles Paris 1999
-9782212090819 fr applications Philippe Knab Construire une application XML Eyrolles Paris 1999
+9782212090819 fr applications Philippe Bernadac Construire une application XML Eyrolles Paris 1999
+9782212090819 fr applications François Knab Construire une application XML Eyrolles Paris 1999
#
# To add an author a new table must be created
#
CREATE TABLE t2 (
FIRSTNAME CHAR(32),
LASTNAME CHAR(32))
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.jsn' OPTION_LIST='Object=[2]:AUTHOR';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json' OPTION_LIST='Object=[2]:AUTHOR';
SELECT * FROM t2;
FIRSTNAME LASTNAME
William J. Pardi
INSERT INTO t2 VALUES('Charles','Dickens');
SELECT * FROM t1;
ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher Location Year
-9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML Eyrolles Paris 1999
-9782212090819 fr applications Philippe Knab Construire une application XML Eyrolles Paris 1999
+9782212090819 fr applications Philippe Bernadac Construire une application XML Eyrolles Paris 1999
+9782212090819 fr applications François Knab Construire une application XML Eyrolles Paris 1999
9782840825685 fr applications William J. Pardi XML en Action adapté de l'anglais par James Guerin Microsoft Press Paris 1999
9782840825685 fr applications Charles Dickens XML en Action adapté de l'anglais par James Guerin Microsoft Press Paris 1999
DROP TABLE t1;
@@ -117,7 +117,7 @@ CREATE TABLE t1
(
line char(255)
)
-ENGINE=CONNECT TABLE_TYPE=DOS FILE_NAME='biblio.jsn';
+ENGINE=CONNECT TABLE_TYPE=DOS FILE_NAME='biblio.json';
SELECT * FROM t1;
line
[
@@ -127,11 +127,11 @@ line
"SUBJECT": "applications",
"AUTHOR": [
{
- "FIRSTNAME": "Jean-Christophe",
+ "FIRSTNAME": "Philippe",
"LASTNAME": "Bernadac"
},
{
- "FIRSTNAME": "Philippe",
+ "FIRSTNAME": "François",
"LASTNAME": "Knab"
}
],
@@ -178,7 +178,7 @@ WHO CHAR(12),
WEEK INT(2) FIELD_FORMAT='WEEK:[X]:NUMBER',
WHAT CHAR(32) FIELD_FORMAT='WEEK::EXPENSE:["+"]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK::EXPENSE:[+]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.json';
SELECT * FROM t1;
WHO WEEK WHAT AMOUNT
Joe 3 Beer+Food+Food+Car 69.00
@@ -192,16 +192,60 @@ Janet 4 Car 17.00
Janet 5 Beer+Car+Beer+Food 57.00
DROP TABLE t1;
#
-# Cannot be fully expanded
+# Now it can be fully expanded
#
CREATE TABLE t1 (
WHO CHAR(12),
WEEK INT(2) FIELD_FORMAT='WEEK:[X]:NUMBER',
WHAT CHAR(32) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.json';
+SELECT * FROM t1;
+WHO WEEK WHAT AMOUNT
+Joe 3 Beer 18.00
+Joe 3 Food 12.00
+Joe 3 Food 19.00
+Joe 3 Car 20.00
+Joe 4 Beer 19.00
+Joe 4 Beer 16.00
+Joe 4 Food 17.00
+Joe 4 Food 17.00
+Joe 4 Beer 14.00
+Joe 5 Beer 14.00
+Joe 5 Food 12.00
+Beth 3 Beer 16.00
+Beth 4 Food 17.00
+Beth 4 Beer 15.00
+Beth 5 Food 12.00
+Beth 5 Beer 20.00
+Janet 3 Car 19.00
+Janet 3 Food 18.00
+Janet 3 Beer 18.00
+Janet 4 Car 17.00
+Janet 5 Beer 14.00
+Janet 5 Car 12.00
+Janet 5 Beer 19.00
+Janet 5 Food 12.00
+DROP TABLE t1;
+#
+# A table showing many calculated results
+#
+CREATE TABLE t1 (
+WHO CHAR(12) NOT NULL,
+WEEKS CHAR(12) NOT NULL FIELD_FORMAT='WEEK:[", "]:NUMBER',
+SUMS CHAR(64) NOT NULL FIELD_FORMAT='WEEK:["+"]:EXPENSE:[+]:AMOUNT',
+SUM DOUBLE(8,2) NOT NULL FIELD_FORMAT='WEEK:[+]:EXPENSE:[+]:AMOUNT',
+AVGS CHAR(64) NOT NULL FIELD_FORMAT='WEEK:["+"]:EXPENSE:[!]:AMOUNT',
+SUMAVG DOUBLE(8,2) NOT NULL FIELD_FORMAT='WEEK:[+]:EXPENSE:[!]:AMOUNT',
+AVGSUM DOUBLE(8,2) NOT NULL FIELD_FORMAT='WEEK:[!]:EXPENSE:[+]:AMOUNT',
+AVGAVG DOUBLE(8,2) NOT NULL FIELD_FORMAT='WEEK:[!]:EXPENSE:[!]:AMOUNT',
+AVERAGE DOUBLE(8,2) NOT NULL FIELD_FORMAT='WEEK:[!]:EXPENSE:[X]:AMOUNT')
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.json';
SELECT * FROM t1;
-ERROR HY000: Got error 174 'Cannot expand more than one array' from CONNECT
+WHO WEEKS SUMS SUM AVGS SUMAVG AVGSUM AVGAVG AVERAGE
+Joe 3, 4, 5 69.00+83.00+26.00 178.00 17.25+16.60+13.00 46.85 59.33 15.62 16.18
+Beth 3, 4, 5 16.00+32.00+32.00 80.00 16.00+16.00+16.00 48.00 26.67 16.00 16.00
+Janet 3, 4, 5 55.00+17.00+57.00 129.00 18.33+17.00+14.25 49.58 43.00 16.53 16.12
DROP TABLE t1;
#
# Expand expense in 3 one week tables
@@ -211,7 +255,7 @@ WHO CHAR(12),
WEEK INT(2) FIELD_FORMAT='WEEK:[1]:NUMBER',
WHAT CHAR(32) FIELD_FORMAT='WEEK:[1]:EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[1]:EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.json';
SELECT * FROM t2;
WHO WEEK WHAT AMOUNT
Joe 3 Beer 18.00
@@ -227,7 +271,7 @@ WHO CHAR(12),
WEEK INT(2) FIELD_FORMAT='WEEK:[2]:NUMBER',
WHAT CHAR(32) FIELD_FORMAT='WEEK:[2]:EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[2]:EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.json';
SELECT * FROM t3;
WHO WEEK WHAT AMOUNT
Joe 4 Beer 19.00
@@ -243,7 +287,7 @@ WHO CHAR(12),
WEEK INT(2) FIELD_FORMAT='WEEK:[3]:NUMBER',
WHAT CHAR(32) FIELD_FORMAT='WEEK:[3]:EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[3]:EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.json';
SELECT * FROM t4;
WHO WEEK WHAT AMOUNT
Joe 5 Beer 14.00
@@ -298,7 +342,7 @@ WHO CHAR(12),
WEEK INT(2),
WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp3.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp3.json';
SELECT * FROM t2;
WHO WEEK WHAT AMOUNT
Joe 3 Beer 18.00
@@ -314,7 +358,7 @@ WHO CHAR(12),
WEEK INT(2),
WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp4.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp4.json';
SELECT * FROM t3;
WHO WEEK WHAT AMOUNT
Joe 4 Beer 19.00
@@ -330,7 +374,7 @@ WHO CHAR(12),
WEEK INT(2),
WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp5.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp5.json';
SELECT * FROM t4;
WHO WEEK WHAT AMOUNT
Joe 5 Beer 14.00
@@ -349,7 +393,7 @@ WHO CHAR(12),
WEEK INT(2),
WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp*.jsn' MULTIPLE=1;
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp*.json' MULTIPLE=1;
SELECT * FROM t1 ORDER BY WHO, WEEK, WHAT, AMOUNT;
WHO WEEK WHAT AMOUNT
Beth 3 Beer 16.00
@@ -385,7 +429,7 @@ WHO CHAR(12),
WEEK INT(2),
WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp%s.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp%s.json';
ALTER TABLE t1
PARTITION BY LIST COLUMNS(WEEK) (
PARTITION `3` VALUES IN(3),
diff --git a/storage/connect/mysql-test/connect/r/json_udf.result b/storage/connect/mysql-test/connect/r/json_udf.result
new file mode 100644
index 00000000000..1455bac9017
--- /dev/null
+++ b/storage/connect/mysql-test/connect/r/json_udf.result
@@ -0,0 +1,167 @@
+#
+# Test UDF's with constant arguments
+#
+SELECT Json_Array();
+Json_Array()
+[]
+SELECT Json_Object(56,3.1416,'foo',NULL);
+Json_Object(56,3.1416,'foo',NULL)
+{"56":56,"3.1416":3.141600,"foo":"foo","NULL":null}
+SELECT Json_Object(56 qty,3.1416 price,'foo' truc, NULL garanty);
+Json_Object(56 qty,3.1416 price,'foo' truc, NULL garanty)
+{"qty":56,"price":3.141600,"truc":"foo","garanty":null}
+SELECT Json_Array(56,3.1416,'My name is "Foo"',NULL);
+Json_Array(56,3.1416,'My name is "Foo"',NULL)
+[56,3.141600,"My name is \"Foo\"",null]
+SELECT Json_Array_Add(Json_Array(56,3.1416,'foo',NULL)) Array;
+ERROR HY000: Can't initialize function 'Json_Array_Add'; Json_Value_Add must have at least 2 arguments
+SELECT Json_Array_Add(Json_Array(56,3.1416,'foo',NULL),'One more') Array;
+Array
+[56,3.141600,"foo",null,"One more"]
+SELECT Json_Array_Add(Json_Value('one value'),'One more');
+Json_Array_Add(Json_Value('one value'),'One more')
+["one value","One more"]
+SELECT Json_Array_Add('one value','One more');
+ERROR HY000: Can't initialize function 'Json_Array_Add'; Json_Value_Add first argument must be a json item
+SELECT Json_Array_Add('one value' json_,'One more');
+Json_Array_Add('one value' json_,'One more')
+[null,"One more"]
+Warnings:
+Warning 1105 Bad 'o' character near one value
+SELECT Json_Value(56,3.1416,'foo',NULL);
+ERROR HY000: Can't initialize function 'Json_Value'; Json_Value cannot accept more than 1 argument
+SELECT Json_Value(3.1416);
+Json_Value(3.1416)
+3.141600
+SELECT Json_Value('foo');
+Json_Value('foo')
+"foo"
+SELECT Json_Value(NULL);
+Json_Value(NULL)
+null
+SELECT Json_Value();
+Json_Value()
+null
+SELECT Json_Object();
+Json_Object()
+{}
+SELECT Json_Object(Json_Array(56,3.1416,'foo'),NULL);
+Json_Object(Json_Array(56,3.1416,'foo'),NULL)
+{"Array(56,3.1416,'foo')":[56,3.141600,"foo"],"NULL":null}
+SELECT Json_Array(Json_Array(56,3.1416,'foo'),NULL);
+Json_Array(Json_Array(56,3.1416,'foo'),NULL)
+[[56,3.141600,"foo"],null]
+SELECT Json_Array(Json_Object(56 "qty",3.1416 "price",'foo'),NULL);
+Json_Array(Json_Object(56 "qty",3.1416 "price",'foo'),NULL)
+[{"qty":56,"price":3.141600,"foo":"foo"},null]
+#
+# Test UDF's with column arguments
+#
+CREATE TABLE t1
+(
+ISBN CHAR(15),
+LANG CHAR(2),
+SUBJECT CHAR(32),
+AUTHOR CHAR(64),
+TITLE CHAR(32),
+TRANSLATION CHAR(32),
+TRANSLATOR CHAR(80),
+PUBLISHER CHAR(32),
+DATEPUB int(4)
+) ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
+SELECT Json_Array(AUTHOR, TITLE, DATEPUB) FROM t1;
+Json_Array(AUTHOR, TITLE, DATEPUB)
+["Jean-Christophe Bernadac","Construire une application XML",1999]
+["William J. Pardi","XML en Action",1999]
+SELECT Json_Object(AUTHOR, TITLE, DATEPUB) FROM t1;
+Json_Object(AUTHOR, TITLE, DATEPUB)
+{"AUTHOR":"Jean-Christophe Bernadac","TITLE":"Construire une application XML","DATEPUB":1999}
+{"AUTHOR":"William J. Pardi","TITLE":"XML en Action","DATEPUB":1999}
+SELECT Json_Array_Grp(TITLE, DATEPUB) FROM t1;
+ERROR HY000: Can't initialize function 'Json_Array_Grp'; Json_Array_Grp can only accept 1 argument
+SELECT Json_Array_Grp(TITLE) FROM t1;
+Json_Array_Grp(TITLE)
+["Construire une application XML","XML en Action"]
+DROP TABLE t1;
+CREATE TABLE t1 (
+SERIALNO CHAR(5) NOT NULL,
+NAME VARCHAR(12) NOT NULL FLAG=6,
+SEX SMALLINT(1) NOT NULL,
+TITLE VARCHAR(15) NOT NULL FLAG=20,
+MANAGER CHAR(5) DEFAULT NULL,
+DEPARTMENT CHAr(4) NOT NULL FLAG=41,
+SECRETARY CHAR(5) DEFAULT NULL FLAG=46,
+SALARY DOUBLE(8,2) NOT NULL FLAG=52
+) ENGINE=CONNECT TABLE_TYPE=FIX BLOCK_SIZE=8 FILE_NAME='employee.dat' ENDING=1;
+SELECT Json_Object(SERIALNO, NAME, TITLE, SALARY) FROM t1 WHERE NAME = 'MERCHANT';
+Json_Object(SERIALNO, NAME, TITLE, SALARY)
+{"SERIALNO":"78943","NAME":"MERCHANT","TITLE":"SALESMAN","SALARY":8700.000000}
+SELECT DEPARTMENT, Json_Array_Grp(NAME) FROM t1 GROUP BY DEPARTMENT;
+DEPARTMENT Json_Array_Grp(NAME)
+0021 ["STRONG","SHORTSIGHT"]
+0318 ["BANCROFT","PLUMHEAD","HONEY","TONGHO","WALTER","SHRINKY","WERTHER","MERCHANT","WHEELFOR"]
+0319 ["BULLOZER","QUINN","BROWNY","KITTY","MONAPENNY","MARTIN","FUNNIGUY","BUGHAPPY","FODDERMAN","MESSIFUL"]
+2452 ["BIGHEAD","ORELLY","BIGHORN","SMITH","CHERRY"]
+Warnings:
+Warning 1105 Result truncated to json_grp_size values
+set connect_json_grp_size=30;
+SELECT Json_Array(DEPARTMENT, Json_Array_Grp(NAME)) FROM t1 GROUP BY DEPARTMENT;
+Json_Array(DEPARTMENT, Json_Array_Grp(NAME))
+["0021",["STRONG","SHORTSIGHT"]]
+["0318",["BANCROFT","PLUMHEAD","HONEY","TONGHO","WALTER","SHRINKY","WERTHER","MERCHANT","WHEELFOR"]]
+["0319",["BULLOZER","QUINN","BROWNY","KITTY","MONAPENNY","MARTIN","FUNNIGUY","BUGHAPPY","FODDERMAN","MESSIFUL","GOOSEPEN"]]
+["2452",["BIGHEAD","ORELLY","BIGHORN","SMITH","CHERRY"]]
+SELECT Json_Object(DEPARTMENT, Json_Array_Grp(NAME) json_NAMES) FROM t1 GROUP BY DEPARTMENT;
+Json_Object(DEPARTMENT, Json_Array_Grp(NAME) json_NAMES)
+{"DEPARTMENT":"0021","NAMES":["STRONG","SHORTSIGHT"]}
+{"DEPARTMENT":"0318","NAMES":["BANCROFT","PLUMHEAD","HONEY","TONGHO","WALTER","SHRINKY","WERTHER","MERCHANT","WHEELFOR"]}
+{"DEPARTMENT":"0319","NAMES":["BULLOZER","QUINN","BROWNY","KITTY","MONAPENNY","MARTIN","FUNNIGUY","BUGHAPPY","FODDERMAN","MESSIFUL","GOOSEPEN"]}
+{"DEPARTMENT":"2452","NAMES":["BIGHEAD","ORELLY","BIGHORN","SMITH","CHERRY"]}
+SELECT Json_Object(DEPARTMENT, Json_Array_Grp(Json_Object(SERIALNO, NAME, TITLE, SALARY)) json_EMPLOYES) FROM t1 GROUP BY DEPARTMENT;
+Json_Object(DEPARTMENT, Json_Array_Grp(Json_Object(SERIALNO, NAME, TITLE, SALARY)) json_EMPLOYES)
+{"DEPARTMENT":"0021","EMPLOYES":[{"SERIALNO":"87777","NAME":"STRONG","TITLE":"DIRECTOR","SALARY":23000.000000},{"SERIALNO":"22222","NAME":"SHORTSIGHT","TITLE":"SECRETARY","SALARY":5500.000000}]}
+{"DEPARTMENT":"0318","EMPLOYES":[{"SERIALNO":"74200","NAME":"BANCROFT","TITLE":"SALESMAN","SALARY":9600.000000},{"SERIALNO":"24888","NAME":"PLUMHEAD","TITLE":"TYPIST","SALARY":2800.000000},{"SERIALNO":"27845","NAME":"HONEY","TITLE":"SECRETARY","SALARY":4900.000000},{"SERIALNO":"73452","NAME":"TONGHO","TITLE":"ENGINEER","SALARY":6800.000000},{"SERIALNO":"74234","NAME":"WALTER","TITLE":"ENGINEER","SALARY":7400.000000},{"SERIALNO":"77777","NAME":"SHRINKY","TITLE":"ADMINISTRATOR","SALARY":7500.000000},{"SERIALNO":"70012","NAME":"WERTHER","TITLE":"DIRECTOR","SALARY":14500.000000},{"SERIALNO":"78943","NAME":"MERCHANT","TITLE":"SALESMAN","SALARY":8700.000000},{"SERIALNO":"73111","NAME":"WHEELFOR","TITLE":"SALESMAN","SALARY":10030.000000}]}
+{"DEPARTMENT":"0319","EMPLOYES":[{"SERIALNO":"76543","NAME":"BULLOZER","TITLE":"SALESMAN","SALARY":14800.000000},{"SERIALNO":"40567","NAME":"QUINN","TITLE":"DIRECTOR","SALARY":14000.000000},{"SERIALNO":"00137","NAME":"BROWNY","TITLE":"ENGINEER","SALARY":10500.000000},{"SERIALNO":"12345","NAME":"KITTY","TITLE":"TYPIST","SALARY":3000.450000},{"SERIALNO":"33333","NAME":"MONAPENNY","TITLE":"SECRETARY","SALARY":3800.000000},{"SERIALNO":"00023","NAME":"MARTIN","TITLE":"ENGINEER","SALARY":10000.000000},{"SERIALNO":"07654","NAME":"FUNNIGUY","TITLE":"ADMINISTRATOR","SALARY":8500.000000},{"SERIALNO":"45678","NAME":"BUGHAPPY","TITLE":"PROGRAMMER","SALARY":8500.000000},{"SERIALNO":"56789","NAME":"FODDERMAN","TITLE":"SALESMAN","SALARY":7000.000000},{"SERIALNO":"55555","NAME":"MESSIFUL","TITLE":"SECRETARY","SALARY":5000.500000},{"SERIALNO":"98765","NAME":"GOOSEPEN","TITLE":"ADMINISTRATOR","SALARY":4700.000000}]}
+{"DEPARTMENT":"2452","EMPLOYES":[{"SERIALNO":"34567","NAME":"BIGHEAD","TITLE":"SCIENTIST","SALARY":8000.000000},{"SERIALNO":"31416","NAME":"ORELLY","TITLE":"ENGINEER","SALARY":13400.000000},{"SERIALNO":"36666","NAME":"BIGHORN","TITLE":"SCIENTIST","SALARY":11000.000000},{"SERIALNO":"02345","NAME":"SMITH","TITLE":"ENGINEER","SALARY":9000.000000},{"SERIALNO":"11111","NAME":"CHERRY","TITLE":"SECRETARY","SALARY":4500.000000}]}
+SELECT Json_Object(DEPARTMENT, TITLE, Json_Array_Grp(Json_Object(SERIALNO, NAME, SALARY)) json_EMPLOYES) FROM t1 GROUP BY DEPARTMENT, TITLE;
+Json_Object(DEPARTMENT, TITLE, Json_Array_Grp(Json_Object(SERIALNO, NAME, SALARY)) json_EMPLOYES)
+{"DEPARTMENT":"0021","TITLE":"DIRECTOR","EMPLOYES":[{"SERIALNO":"87777","NAME":"STRONG","SALARY":23000.000000}]}
+{"DEPARTMENT":"0021","TITLE":"SECRETARY","EMPLOYES":[{"SERIALNO":"22222","NAME":"SHORTSIGHT","SALARY":5500.000000}]}
+{"DEPARTMENT":"0318","TITLE":"ADMINISTRATOR","EMPLOYES":[{"SERIALNO":"77777","NAME":"SHRINKY","SALARY":7500.000000}]}
+{"DEPARTMENT":"0318","TITLE":"DIRECTOR","EMPLOYES":[{"SERIALNO":"70012","NAME":"WERTHER","SALARY":14500.000000}]}
+{"DEPARTMENT":"0318","TITLE":"ENGINEER","EMPLOYES":[{"SERIALNO":"73452","NAME":"TONGHO","SALARY":6800.000000},{"SERIALNO":"74234","NAME":"WALTER","SALARY":7400.000000}]}
+{"DEPARTMENT":"0318","TITLE":"SALESMAN","EMPLOYES":[{"SERIALNO":"74200","NAME":"BANCROFT","SALARY":9600.000000},{"SERIALNO":"78943","NAME":"MERCHANT","SALARY":8700.000000},{"SERIALNO":"73111","NAME":"WHEELFOR","SALARY":10030.000000}]}
+{"DEPARTMENT":"0318","TITLE":"SECRETARY","EMPLOYES":[{"SERIALNO":"27845","NAME":"HONEY","SALARY":4900.000000}]}
+{"DEPARTMENT":"0318","TITLE":"TYPIST","EMPLOYES":[{"SERIALNO":"24888","NAME":"PLUMHEAD","SALARY":2800.000000}]}
+{"DEPARTMENT":"0319","TITLE":"ADMINISTRATOR","EMPLOYES":[{"SERIALNO":"98765","NAME":"GOOSEPEN","SALARY":4700.000000},{"SERIALNO":"07654","NAME":"FUNNIGUY","SALARY":8500.000000}]}
+{"DEPARTMENT":"0319","TITLE":"DIRECTOR","EMPLOYES":[{"SERIALNO":"40567","NAME":"QUINN","SALARY":14000.000000}]}
+{"DEPARTMENT":"0319","TITLE":"ENGINEER","EMPLOYES":[{"SERIALNO":"00023","NAME":"MARTIN","SALARY":10000.000000},{"SERIALNO":"00137","NAME":"BROWNY","SALARY":10500.000000}]}
+{"DEPARTMENT":"0319","TITLE":"PROGRAMMER","EMPLOYES":[{"SERIALNO":"45678","NAME":"BUGHAPPY","SALARY":8500.000000}]}
+{"DEPARTMENT":"0319","TITLE":"SALESMAN","EMPLOYES":[{"SERIALNO":"76543","NAME":"BULLOZER","SALARY":14800.000000},{"SERIALNO":"56789","NAME":"FODDERMAN","SALARY":7000.000000}]}
+{"DEPARTMENT":"0319","TITLE":"SECRETARY","EMPLOYES":[{"SERIALNO":"33333","NAME":"MONAPENNY","SALARY":3800.000000},{"SERIALNO":"55555","NAME":"MESSIFUL","SALARY":5000.500000}]}
+{"DEPARTMENT":"0319","TITLE":"TYPIST","EMPLOYES":[{"SERIALNO":"12345","NAME":"KITTY","SALARY":3000.450000}]}
+{"DEPARTMENT":"2452","TITLE":"ENGINEER","EMPLOYES":[{"SERIALNO":"31416","NAME":"ORELLY","SALARY":13400.000000},{"SERIALNO":"02345","NAME":"SMITH","SALARY":9000.000000}]}
+{"DEPARTMENT":"2452","TITLE":"SCIENTIST","EMPLOYES":[{"SERIALNO":"34567","NAME":"BIGHEAD","SALARY":8000.000000},{"SERIALNO":"36666","NAME":"BIGHORN","SALARY":11000.000000}]}
+{"DEPARTMENT":"2452","TITLE":"SECRETARY","EMPLOYES":[{"SERIALNO":"11111","NAME":"CHERRY","SALARY":4500.000000}]}
+SELECT Json_Object_Grp(SALARY) FROM t1;
+ERROR HY000: Can't initialize function 'Json_Object_Grp'; Json_Array_Grp can only accept 2 arguments
+SELECT Json_Object_Grp(SALARY, NAME) FROM t1;
+Json_Object_Grp(SALARY, NAME)
+{"BANCROFT":9600.000000,"SMITH":9000.000000,"MERCHANT":8700.000000,"FUNNIGUY":8500.000000,"BUGHAPPY":8500.000000,"BIGHEAD":8000.000000,"SHRINKY":7500.000000,"WALTER":7400.000000,"FODDERMAN":7000.000000,"TONGHO":6800.000000,"SHORTSIGHT":5500.000000,"MESSIFUL":5000.500000,"HONEY":4900.000000,"GOOSEPEN":4700.000000,"CHERRY":4500.000000,"MONAPENNY":3800.000000,"KITTY":3000.450000,"PLUMHEAD":2800.000000,"STRONG":23000.000000,"BULLOZER":14800.000000,"WERTHER":14500.000000,"QUINN":14000.000000,"ORELLY":13400.000000,"BIGHORN":11000.000000,"BROWNY":10500.000000,"WHEELFOR":10030.000000,"MARTIN":10000.000000}
+SELECT Json_Object(DEPARTMENT, Json_Object_Grp(SALARY, NAME) "Json_SALARIES") FROM t1 GROUP BY DEPARTMENT;
+Json_Object(DEPARTMENT, Json_Object_Grp(SALARY, NAME) "Json_SALARIES")
+{"DEPARTMENT":"0021","SALARIES":{"STRONG":23000.000000,"SHORTSIGHT":5500.000000}}
+{"DEPARTMENT":"0318","SALARIES":{"BANCROFT":9600.000000,"PLUMHEAD":2800.000000,"HONEY":4900.000000,"TONGHO":6800.000000,"WALTER":7400.000000,"SHRINKY":7500.000000,"WERTHER":14500.000000,"MERCHANT":8700.000000,"WHEELFOR":10030.000000}}
+{"DEPARTMENT":"0319","SALARIES":{"BULLOZER":14800.000000,"QUINN":14000.000000,"BROWNY":10500.000000,"KITTY":3000.450000,"MONAPENNY":3800.000000,"MARTIN":10000.000000,"FUNNIGUY":8500.000000,"BUGHAPPY":8500.000000,"FODDERMAN":7000.000000,"MESSIFUL":5000.500000,"GOOSEPEN":4700.000000}}
+{"DEPARTMENT":"2452","SALARIES":{"BIGHEAD":8000.000000,"ORELLY":13400.000000,"BIGHORN":11000.000000,"SMITH":9000.000000,"CHERRY":4500.000000}}
+SELECT Json_Array_Grp(NAME) from t1;
+Json_Array_Grp(NAME)
+["BANCROFT","SMITH","MERCHANT","FUNNIGUY","BUGHAPPY","BIGHEAD","SHRINKY","WALTER","FODDERMAN","TONGHO","SHORTSIGHT","MESSIFUL","HONEY","GOOSEPEN","CHERRY","MONAPENNY","KITTY","PLUMHEAD","STRONG","BULLOZER","WERTHER","QUINN","ORELLY","BIGHORN","BROWNY","WHEELFOR","MARTIN"]
+DROP TABLE t1;
+DROP FUNCTION Json_Array;
+DROP FUNCTION Json_Array_Add;
+DROP FUNCTION Json_Object;
+DROP FUNCTION Json_Object_Nonull;
+DROP FUNCTION Json_Value;
+DROP FUNCTION Json_Array_Grp;
+DROP FUNCTION Json_Object_Grp;
diff --git a/storage/connect/mysql-test/connect/r/odbc_oracle.result b/storage/connect/mysql-test/connect/r/odbc_oracle.result
index fff2f192184..96d8e53b8e5 100644
--- a/storage/connect/mysql-test/connect/r/odbc_oracle.result
+++ b/storage/connect/mysql-test/connect/r/odbc_oracle.result
@@ -126,7 +126,7 @@ TABNAME='T1';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `A` decimal(38,0) DEFAULT NULL,
+ `A` decimal(40,0) DEFAULT NULL,
`B` double(40,0) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' `TABLE_TYPE`='ODBC' `TABNAME`='T1'
SELECT * FROM t1 ORDER BY A;
@@ -138,7 +138,7 @@ CREATE TABLE t2 AS SELECT * FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `A` decimal(38,0) DEFAULT NULL,
+ `A` decimal(40,0) DEFAULT NULL,
`B` double(40,0) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM t2;
@@ -162,7 +162,7 @@ TABNAME='MTR.T1';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `A` decimal(38,0) DEFAULT NULL,
+ `A` decimal(40,0) DEFAULT NULL,
`B` double(40,0) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' `TABLE_TYPE`='ODBC' `TABNAME`='MTR.T1'
SELECT * FROM t1;
@@ -178,7 +178,7 @@ TABNAME='MTR.V1';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `A` decimal(38,0) DEFAULT NULL,
+ `A` decimal(40,0) DEFAULT NULL,
`B` double(40,0) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' `TABLE_TYPE`='ODBC' `TABNAME`='MTR.V1'
SELECT * FROM t1;
@@ -190,7 +190,7 @@ CREATE TABLE t2 AS SELECT * FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `A` decimal(38,0) DEFAULT NULL,
+ `A` decimal(40,0) DEFAULT NULL,
`B` double(40,0) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM t2;
diff --git a/storage/connect/mysql-test/connect/std_data/biblio.jsn b/storage/connect/mysql-test/connect/std_data/biblio.json
index bab8fd24305..bab8fd24305 100644
--- a/storage/connect/mysql-test/connect/std_data/biblio.jsn
+++ b/storage/connect/mysql-test/connect/std_data/biblio.json
diff --git a/storage/connect/mysql-test/connect/std_data/expense.jsn b/storage/connect/mysql-test/connect/std_data/expense.json
index e65ad5261f1..e65ad5261f1 100644
--- a/storage/connect/mysql-test/connect/std_data/expense.jsn
+++ b/storage/connect/mysql-test/connect/std_data/expense.json
diff --git a/storage/connect/mysql-test/connect/std_data/mulexp3.jsn b/storage/connect/mysql-test/connect/std_data/mulexp3.json
index c228448b073..c228448b073 100644
--- a/storage/connect/mysql-test/connect/std_data/mulexp3.jsn
+++ b/storage/connect/mysql-test/connect/std_data/mulexp3.json
diff --git a/storage/connect/mysql-test/connect/std_data/mulexp4.jsn b/storage/connect/mysql-test/connect/std_data/mulexp4.json
index 0e43ffec07b..0e43ffec07b 100644
--- a/storage/connect/mysql-test/connect/std_data/mulexp4.jsn
+++ b/storage/connect/mysql-test/connect/std_data/mulexp4.json
diff --git a/storage/connect/mysql-test/connect/std_data/mulexp5.jsn b/storage/connect/mysql-test/connect/std_data/mulexp5.json
index 7a707506c2f..7a707506c2f 100644
--- a/storage/connect/mysql-test/connect/std_data/mulexp5.jsn
+++ b/storage/connect/mysql-test/connect/std_data/mulexp5.json
diff --git a/storage/connect/mysql-test/connect/t/json.test b/storage/connect/mysql-test/connect/t/json.test
index a7e630ed0cf..79588e9fe5b 100644
--- a/storage/connect/mysql-test/connect/t/json.test
+++ b/storage/connect/mysql-test/connect/t/json.test
@@ -3,11 +3,11 @@
let $MYSQLD_DATADIR= `select @@datadir`;
---copy_file $MTR_SUITE_DIR/std_data/biblio.jsn $MYSQLD_DATADIR/test/biblio.jsn
---copy_file $MTR_SUITE_DIR/std_data/expense.jsn $MYSQLD_DATADIR/test/expense.jsn
---copy_file $MTR_SUITE_DIR/std_data/mulexp3.jsn $MYSQLD_DATADIR/test/mulexp3.jsn
---copy_file $MTR_SUITE_DIR/std_data/mulexp4.jsn $MYSQLD_DATADIR/test/mulexp4.jsn
---copy_file $MTR_SUITE_DIR/std_data/mulexp5.jsn $MYSQLD_DATADIR/test/mulexp5.jsn
+--copy_file $MTR_SUITE_DIR/std_data/biblio.json $MYSQLD_DATADIR/test/biblio.json
+--copy_file $MTR_SUITE_DIR/std_data/expense.json $MYSQLD_DATADIR/test/expense.json
+--copy_file $MTR_SUITE_DIR/std_data/mulexp3.json $MYSQLD_DATADIR/test/mulexp3.json
+--copy_file $MTR_SUITE_DIR/std_data/mulexp4.json $MYSQLD_DATADIR/test/mulexp4.json
+--copy_file $MTR_SUITE_DIR/std_data/mulexp5.json $MYSQLD_DATADIR/test/mulexp5.json
--echo #
--echo # Testing doc samples
@@ -23,7 +23,7 @@ CREATE TABLE t1
TRANSLATOR CHAR(80),
PUBLISHER CHAR(32),
DATEPUB int(4)
-) ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.jsn';
+) ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
SELECT * FROM t1;
DROP TABLE t1;
@@ -44,7 +44,7 @@ CREATE TABLE t1
Location CHAR(16) FIELD_FORMAT='PUBLISHER:PLACE',
Year int(4) FIELD_FORMAT='DATEPUB'
)
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
SELECT * FROM t1;
DROP TABLE t1;
@@ -65,7 +65,7 @@ CREATE TABLE t1
Location CHAR(16) FIELD_FORMAT='PUBLISHER:PLACE',
Year int(4) FIELD_FORMAT='DATEPUB'
)
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
SELECT * FROM t1;
DROP TABLE t1;
@@ -86,7 +86,7 @@ CREATE TABLE t1
Location CHAR(16) FIELD_FORMAT='PUBLISHER:PLACE',
Year int(4) FIELD_FORMAT='DATEPUB'
)
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
SELECT * FROM t1;
UPDATE t1 SET AuthorFN = 'Philippe' WHERE AuthorLN = 'Knab';
SELECT * FROM t1 WHERE ISBN = '9782212090819';
@@ -97,7 +97,7 @@ SELECT * FROM t1 WHERE ISBN = '9782212090819';
CREATE TABLE t2 (
FIRSTNAME CHAR(32),
LASTNAME CHAR(32))
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.jsn' OPTION_LIST='Object=[2]:AUTHOR';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json' OPTION_LIST='Object=[2]:AUTHOR';
SELECT * FROM t2;
INSERT INTO t2 VALUES('Charles','Dickens');
SELECT * FROM t1;
@@ -111,7 +111,7 @@ CREATE TABLE t1
(
line char(255)
)
-ENGINE=CONNECT TABLE_TYPE=DOS FILE_NAME='biblio.jsn';
+ENGINE=CONNECT TABLE_TYPE=DOS FILE_NAME='biblio.json';
SELECT * FROM t1;
DROP TABLE t1;
@@ -123,20 +123,37 @@ WHO CHAR(12),
WEEK INT(2) FIELD_FORMAT='WEEK:[X]:NUMBER',
WHAT CHAR(32) FIELD_FORMAT='WEEK::EXPENSE:["+"]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK::EXPENSE:[+]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.json';
SELECT * FROM t1;
DROP TABLE t1;
--echo #
---echo # Cannot be fully expanded
+--echo # Now it can be fully expanded
--echo #
CREATE TABLE t1 (
WHO CHAR(12),
WEEK INT(2) FIELD_FORMAT='WEEK:[X]:NUMBER',
WHAT CHAR(32) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
---error ER_GET_ERRMSG
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.json';
+#--error ER_GET_ERRMSG
+SELECT * FROM t1;
+DROP TABLE t1;
+
+--echo #
+--echo # A table showing many calculated results
+--echo #
+CREATE TABLE t1 (
+WHO CHAR(12) NOT NULL,
+WEEKS CHAR(12) NOT NULL FIELD_FORMAT='WEEK:[", "]:NUMBER',
+SUMS CHAR(64) NOT NULL FIELD_FORMAT='WEEK:["+"]:EXPENSE:[+]:AMOUNT',
+SUM DOUBLE(8,2) NOT NULL FIELD_FORMAT='WEEK:[+]:EXPENSE:[+]:AMOUNT',
+AVGS CHAR(64) NOT NULL FIELD_FORMAT='WEEK:["+"]:EXPENSE:[!]:AMOUNT',
+SUMAVG DOUBLE(8,2) NOT NULL FIELD_FORMAT='WEEK:[+]:EXPENSE:[!]:AMOUNT',
+AVGSUM DOUBLE(8,2) NOT NULL FIELD_FORMAT='WEEK:[!]:EXPENSE:[+]:AMOUNT',
+AVGAVG DOUBLE(8,2) NOT NULL FIELD_FORMAT='WEEK:[!]:EXPENSE:[!]:AMOUNT',
+AVERAGE DOUBLE(8,2) NOT NULL FIELD_FORMAT='WEEK:[!]:EXPENSE:[X]:AMOUNT')
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.json';
SELECT * FROM t1;
DROP TABLE t1;
@@ -148,7 +165,7 @@ WHO CHAR(12),
WEEK INT(2) FIELD_FORMAT='WEEK:[1]:NUMBER',
WHAT CHAR(32) FIELD_FORMAT='WEEK:[1]:EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[1]:EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.json';
SELECT * FROM t2;
CREATE TABLE t3 (
@@ -156,7 +173,7 @@ WHO CHAR(12),
WEEK INT(2) FIELD_FORMAT='WEEK:[2]:NUMBER',
WHAT CHAR(32) FIELD_FORMAT='WEEK:[2]:EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[2]:EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.json';
SELECT * FROM t3;
CREATE TABLE t4 (
@@ -164,7 +181,7 @@ WHO CHAR(12),
WEEK INT(2) FIELD_FORMAT='WEEK:[3]:NUMBER',
WHAT CHAR(32) FIELD_FORMAT='WEEK:[3]:EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[3]:EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.json';
SELECT * FROM t4;
--echo #
@@ -187,7 +204,7 @@ WHO CHAR(12),
WEEK INT(2),
WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp3.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp3.json';
SELECT * FROM t2;
CREATE TABLE t3 (
@@ -195,7 +212,7 @@ WHO CHAR(12),
WEEK INT(2),
WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp4.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp4.json';
SELECT * FROM t3;
CREATE TABLE t4 (
@@ -203,7 +220,7 @@ WHO CHAR(12),
WEEK INT(2),
WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp5.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp5.json';
SELECT * FROM t4;
--echo #
@@ -214,7 +231,7 @@ WHO CHAR(12),
WEEK INT(2),
WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp*.jsn' MULTIPLE=1;
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp*.json' MULTIPLE=1;
SELECT * FROM t1 ORDER BY WHO, WEEK, WHAT, AMOUNT;
DROP TABLE t1;
@@ -226,7 +243,7 @@ WHO CHAR(12),
WEEK INT(2),
WHAT CHAR(32) FIELD_FORMAT='EXPENSE:[X]:WHAT',
AMOUNT DOUBLE(8,2) FIELD_FORMAT='EXPENSE:[X]:AMOUNT')
-ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp%s.jsn';
+ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='mulexp%s.json';
ALTER TABLE t1
PARTITION BY LIST COLUMNS(WEEK) (
PARTITION `3` VALUES IN(3),
@@ -240,8 +257,8 @@ DROP TABLE t1, t2, t3, t4;
#
# Clean up
#
---remove_file $MYSQLD_DATADIR/test/biblio.jsn
---remove_file $MYSQLD_DATADIR/test/expense.jsn
---remove_file $MYSQLD_DATADIR/test/mulexp3.jsn
---remove_file $MYSQLD_DATADIR/test/mulexp4.jsn
---remove_file $MYSQLD_DATADIR/test/mulexp5.jsn
+--remove_file $MYSQLD_DATADIR/test/biblio.json
+--remove_file $MYSQLD_DATADIR/test/expense.json
+--remove_file $MYSQLD_DATADIR/test/mulexp3.json
+--remove_file $MYSQLD_DATADIR/test/mulexp4.json
+--remove_file $MYSQLD_DATADIR/test/mulexp5.json
diff --git a/storage/connect/mysql-test/connect/t/json_udf.inc b/storage/connect/mysql-test/connect/t/json_udf.inc
new file mode 100644
index 00000000000..8566b4141c1
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/json_udf.inc
@@ -0,0 +1,36 @@
+--disable_query_log
+#
+# Check if server has support for loading plugins
+#
+if (`SELECT @@have_dynamic_loading != 'YES'`) {
+ --skip UDF requires dynamic loading
+}
+if (!$HA_CONNECT_SO) {
+ --skip Needs a dynamically built ha_connect.so
+}
+
+let $is_win = `select convert(@@version_compile_os using latin1) IN ("Win32","Win64","Windows")`;
+
+if ($is_win)
+{
+--eval CREATE FUNCTION Json_Array RETURNS STRING SONAME 'ha_connect.dll';
+--eval CREATE FUNCTION Json_Array_Add RETURNS STRING SONAME 'ha_connect.dll';
+--eval CREATE FUNCTION Json_Object RETURNS STRING SONAME 'ha_connect.dll';
+--eval CREATE FUNCTION Json_Object_Nonull RETURNS STRING SONAME 'ha_connect.dll';
+--eval CREATE FUNCTION Json_Value returns STRING SONAME 'ha_connect.dll';
+--eval CREATE AGGREGATE FUNCTION Json_Array_Grp RETURNS STRING SONAME 'ha_connect.dll';
+--eval CREATE AGGREGATE FUNCTION Json_Object_Grp RETURNS STRING SONAME 'ha_connect.dll';
+}
+
+if (!$is_win)
+{
+--eval CREATE FUNCTION Json_Array RETURNS STRING SONAME 'ha_connect.so';
+--eval CREATE FUNCTION Json_Array_Add RETURNS STRING SONAME 'ha_connect.so';
+--eval CREATE FUNCTION Json_Object RETURNS STRING SONAME 'ha_connect.so';
+--eval CREATE FUNCTION Json_Object_Nonull RETURNS STRING SONAME 'ha_connect.so';
+--eval CREATE FUNCTION Json_Value returns STRING SONAME 'ha_connect.so';
+--eval CREATE AGGREGATE FUNCTION Json_Array_Grp RETURNS STRING SONAME 'ha_connect.so';
+--eval CREATE AGGREGATE FUNCTION Json_Object_Grp RETURNS STRING SONAME 'ha_connect.so';
+}
+--enable_query_log
+
diff --git a/storage/connect/mysql-test/connect/t/json_udf.test b/storage/connect/mysql-test/connect/t/json_udf.test
new file mode 100644
index 00000000000..c5510bf9cc0
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/json_udf.test
@@ -0,0 +1,93 @@
+--source json_udf.inc
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+--copy_file $MTR_SUITE_DIR/std_data/biblio.json $MYSQLD_DATADIR/test/biblio.json
+--copy_file $MTR_SUITE_DIR/std_data/employee.dat $MYSQLD_DATADIR/test/employee.dat
+
+--echo #
+--echo # Test UDF's with constant arguments
+--echo #
+SELECT Json_Array();
+SELECT Json_Object(56,3.1416,'foo',NULL);
+SELECT Json_Object(56 qty,3.1416 price,'foo' truc, NULL garanty);
+SELECT Json_Array(56,3.1416,'My name is "Foo"',NULL);
+--error ER_CANT_INITIALIZE_UDF
+SELECT Json_Array_Add(Json_Array(56,3.1416,'foo',NULL)) Array;
+SELECT Json_Array_Add(Json_Array(56,3.1416,'foo',NULL),'One more') Array;
+SELECT Json_Array_Add(Json_Value('one value'),'One more');
+--error ER_CANT_INITIALIZE_UDF
+SELECT Json_Array_Add('one value','One more');
+SELECT Json_Array_Add('one value' json_,'One more');
+--error ER_CANT_INITIALIZE_UDF
+SELECT Json_Value(56,3.1416,'foo',NULL);
+SELECT Json_Value(3.1416);
+SELECT Json_Value('foo');
+SELECT Json_Value(NULL);
+SELECT Json_Value();
+SELECT Json_Object();
+SELECT Json_Object(Json_Array(56,3.1416,'foo'),NULL);
+SELECT Json_Array(Json_Array(56,3.1416,'foo'),NULL);
+SELECT Json_Array(Json_Object(56 "qty",3.1416 "price",'foo'),NULL);
+
+--echo #
+--echo # Test UDF's with column arguments
+--echo #
+CREATE TABLE t1
+(
+ ISBN CHAR(15),
+ LANG CHAR(2),
+ SUBJECT CHAR(32),
+ AUTHOR CHAR(64),
+ TITLE CHAR(32),
+ TRANSLATION CHAR(32),
+ TRANSLATOR CHAR(80),
+ PUBLISHER CHAR(32),
+ DATEPUB int(4)
+) ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='biblio.json';
+
+SELECT Json_Array(AUTHOR, TITLE, DATEPUB) FROM t1;
+SELECT Json_Object(AUTHOR, TITLE, DATEPUB) FROM t1;
+--error ER_CANT_INITIALIZE_UDF
+SELECT Json_Array_Grp(TITLE, DATEPUB) FROM t1;
+SELECT Json_Array_Grp(TITLE) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (
+ SERIALNO CHAR(5) NOT NULL,
+ NAME VARCHAR(12) NOT NULL FLAG=6,
+ SEX SMALLINT(1) NOT NULL,
+ TITLE VARCHAR(15) NOT NULL FLAG=20,
+ MANAGER CHAR(5) DEFAULT NULL,
+ DEPARTMENT CHAr(4) NOT NULL FLAG=41,
+ SECRETARY CHAR(5) DEFAULT NULL FLAG=46,
+ SALARY DOUBLE(8,2) NOT NULL FLAG=52
+) ENGINE=CONNECT TABLE_TYPE=FIX BLOCK_SIZE=8 FILE_NAME='employee.dat' ENDING=1;
+
+SELECT Json_Object(SERIALNO, NAME, TITLE, SALARY) FROM t1 WHERE NAME = 'MERCHANT';
+SELECT DEPARTMENT, Json_Array_Grp(NAME) FROM t1 GROUP BY DEPARTMENT;
+set connect_json_grp_size=30;
+SELECT Json_Array(DEPARTMENT, Json_Array_Grp(NAME)) FROM t1 GROUP BY DEPARTMENT;
+SELECT Json_Object(DEPARTMENT, Json_Array_Grp(NAME) json_NAMES) FROM t1 GROUP BY DEPARTMENT;
+SELECT Json_Object(DEPARTMENT, Json_Array_Grp(Json_Object(SERIALNO, NAME, TITLE, SALARY)) json_EMPLOYES) FROM t1 GROUP BY DEPARTMENT;
+SELECT Json_Object(DEPARTMENT, TITLE, Json_Array_Grp(Json_Object(SERIALNO, NAME, SALARY)) json_EMPLOYES) FROM t1 GROUP BY DEPARTMENT, TITLE;
+--error ER_CANT_INITIALIZE_UDF
+SELECT Json_Object_Grp(SALARY) FROM t1;
+SELECT Json_Object_Grp(SALARY, NAME) FROM t1;
+SELECT Json_Object(DEPARTMENT, Json_Object_Grp(SALARY, NAME) "Json_SALARIES") FROM t1 GROUP BY DEPARTMENT;
+SELECT Json_Array_Grp(NAME) from t1;
+DROP TABLE t1;
+
+DROP FUNCTION Json_Array;
+DROP FUNCTION Json_Array_Add;
+DROP FUNCTION Json_Object;
+DROP FUNCTION Json_Object_Nonull;
+DROP FUNCTION Json_Value;
+DROP FUNCTION Json_Array_Grp;
+DROP FUNCTION Json_Object_Grp;
+
+#
+# Clean up
+#
+--remove_file $MYSQLD_DATADIR/test/biblio.json
+--remove_file $MYSQLD_DATADIR/test/employee.dat
diff --git a/storage/connect/myutil.cpp b/storage/connect/myutil.cpp
index 0d9a1e2fe16..fe504bbe422 100644
--- a/storage/connect/myutil.cpp
+++ b/storage/connect/myutil.cpp
@@ -26,14 +26,16 @@
#include "myutil.h"
#define DLL_EXPORT // Items are exported from this DLL
-extern "C" int xconv;
+//extern "C" int xconv;
+TYPCONV GetTypeConv(void);
/************************************************************************/
/* Convert from MySQL type name to PlugDB type number */
/************************************************************************/
int MYSQLtoPLG(char *typname, char *var)
{
- int type;
+ int type;
+ TYPCONV xconv = GetTypeConv();
if (!stricmp(typname, "int") || !stricmp(typname, "mediumint") ||
!stricmp(typname, "integer"))
@@ -57,13 +59,13 @@ int MYSQLtoPLG(char *typname, char *var)
type = TYPE_TINY;
else if (!stricmp(typname, "text") && var) {
switch (xconv) {
- case 1:
+ case TPC_YES:
type = TYPE_STRING;
*var = 'X';
break;
- case 2:
+ case TPC_SKIP:
*var = 'K';
- default:
+ default: // TPC_NO
type = TYPE_ERROR;
} // endswitch xconv
@@ -88,7 +90,7 @@ int MYSQLtoPLG(char *typname, char *var)
} else if (type == TYPE_STRING && !stricmp(typname, "varchar"))
// This is to make the difference between CHAR and VARCHAR
*var = 'V';
- else if (type == TYPE_ERROR && xconv == 2)
+ else if (type == TYPE_ERROR && xconv == TPC_SKIP)
*var = 'K';
else
*var = 0;
@@ -174,7 +176,7 @@ const char *PLGtoMYSQLtype(int type, bool dbf, char v)
/************************************************************************/
int MYSQLtoPLG(int mytype, char *var)
{
- int type;
+ int type, xconv = GetTypeConv();
switch (mytype) {
case MYSQL_TYPE_SHORT:
@@ -221,7 +223,7 @@ int MYSQLtoPLG(int mytype, char *var)
case MYSQL_TYPE_LONG_BLOB:
if (var) {
switch (xconv) {
- case 1:
+ case TPC_YES:
if (*var != 'B') {
// This is a TEXT column
type = TYPE_STRING;
@@ -230,9 +232,9 @@ int MYSQLtoPLG(int mytype, char *var)
type = TYPE_ERROR;
break;
- case 2:
+ case TPC_SKIP:
*var = 'K'; // Skip
- default:
+ default: // TPC_NO
type = TYPE_ERROR;
} // endswitch xconv
diff --git a/storage/connect/odbccat.h b/storage/connect/odbccat.h
index 8642d915211..1b5febadd3a 100644
--- a/storage/connect/odbccat.h
+++ b/storage/connect/odbccat.h
@@ -2,6 +2,14 @@
#define DEFAULT_LOGIN_TIMEOUT -1 // means do not set
#define DEFAULT_QUERY_TIMEOUT -1 // means do not set
+typedef struct odbc_parms {
+ char *User; // User connect info
+ char *Pwd; // Password connect info
+ int Cto; // Connect timeout
+ int Qto; // Query timeout
+ bool UseCnc; // Use SQLConnect (!SQLDriverConnect)
+ } ODBCPARM, *POPARM;
+
/***********************************************************************/
/* ODBC catalog function prototypes. */
/***********************************************************************/
@@ -10,8 +18,8 @@ char *ODBCCheckConnection(PGLOBAL g, char *dsn, int cop);
#endif // PROMPT_OK
PQRYRES ODBCDataSources(PGLOBAL g, int maxres, bool info);
PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
- char *colpat, int maxres, int cto, int qto, bool info);
-PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src, int cto, int qto);
+ char *colpat, int maxres, bool info, POPARM sop);
+PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src, POPARM sop);
PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat,
- int maxres, int cto, int qto, bool info);
+ int maxres, bool info, POPARM sop);
PQRYRES ODBCDrivers(PGLOBAL g, int maxres, bool info);
diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp
index 3e616ec8f04..ea20672eb29 100644
--- a/storage/connect/odbconn.cpp
+++ b/storage/connect/odbconn.cpp
@@ -37,8 +37,8 @@
#include "xobject.h"
//#include "kindex.h"
#include "xtable.h"
-#include "tabodbc.h"
#include "odbccat.h"
+#include "tabodbc.h"
#include "plgcnx.h" // For DB types
#include "resource.h"
#include "valblk.h"
@@ -53,6 +53,8 @@
extern "C" HINSTANCE s_hModule; // Saved module handle
#endif // WIN32
+int GetConvSize();
+
/***********************************************************************/
/* Some macro's (should be defined elsewhere to be more accessible) */
/***********************************************************************/
@@ -100,7 +102,12 @@ static int GetSQLCType(int type)
case TYPE_BIGINT: tp = SQL_C_SBIGINT; break;
case TYPE_DOUBLE: tp = SQL_C_DOUBLE; break;
case TYPE_TINY : tp = SQL_C_TINYINT; break;
+//#if (ODBCVER >= 0x0300)
+// case TYPE_DECIM: tp = SQL_C_NUMERIC; break; (CRASH!!!)
+//#else
case TYPE_DECIM: tp = SQL_C_CHAR; break;
+//#endif
+
} // endswitch type
return tp;
@@ -122,7 +129,7 @@ int TranslateSQLType(int stp, int prec, int& len, char& v)
case SQL_LONGVARCHAR: // (-1)
v = 'V';
type = TYPE_STRING;
- len = MY_MIN(abs(len), 256);
+ len = MY_MIN(abs(len), GetConvSize());
break;
case SQL_NUMERIC: // 2
case SQL_DECIMAL: // 3
@@ -291,7 +298,7 @@ static void ResetNullValues(CATPARM *cap)
/* of an ODBC table that will be retrieved by GetData commands. */
/***********************************************************************/
PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
- char *colpat, int maxres, int cto, int qto, bool info)
+ char *colpat, int maxres, bool info, POPARM sop)
{
int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING,
TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT,
@@ -310,10 +317,8 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
/************************************************************************/
if (!info) {
ocp = new(g) ODBConn(g, NULL);
- ocp->SetLoginTimeout((DWORD)cto);
- ocp->SetQueryTimeout((DWORD)qto);
- if (ocp->Open(dsn, 10) < 1) // openReadOnly + noODBCdialog
+ if (ocp->Open(dsn, sop, 10) < 1) // openReadOnly + noODBCdialog
return NULL;
if (table && !strchr(table, '%')) {
@@ -342,7 +347,7 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
} // endif ocp
if (trace)
- htrc("ODBCColumns: max=%d len=%d,%d,%d\n",
+ htrc("ODBCColumns: max=%d len=%d,%d,%d,%d\n",
maxres, length[0], length[1], length[2], length[3]);
/************************************************************************/
@@ -388,12 +393,13 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
/* ODBCSrcCols: constructs the result blocks containing the */
/* description of all the columns of a Srcdef option. */
/**************************************************************************/
-PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src, int cto, int qto)
+PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src, POPARM sop)
{
ODBConn *ocp = new(g) ODBConn(g, NULL);
- ocp->SetLoginTimeout((DWORD)cto);
- ocp->SetQueryTimeout((DWORD)qto);
+ if (ocp->Open(dsn, sop, 10) < 1) // openReadOnly + noOdbcDialog
+ return NULL;
+
return ocp->GetMetaData(g, dsn, src);
} // end of ODBCSrcCols
@@ -574,7 +580,7 @@ PQRYRES ODBCDataSources(PGLOBAL g, int maxres, bool info)
/* an ODBC database that will be retrieved by GetData commands. */
/**************************************************************************/
PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat,
- int maxres, int cto, int qto, bool info)
+ int maxres, bool info, POPARM sop)
{
int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING,
TYPE_STRING, TYPE_STRING};
@@ -594,10 +600,8 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat,
/* Open the connection with the ODBC data source. */
/**********************************************************************/
ocp = new(g) ODBConn(g, NULL);
- ocp->SetLoginTimeout((DWORD)cto);
- ocp->SetQueryTimeout((DWORD)qto);
- if (ocp->Open(dsn, 2) < 1) // 2 is openReadOnly
+ if (ocp->Open(dsn, sop, 2) < 1) // 2 is openReadOnly
return NULL;
if (!maxres)
@@ -924,12 +928,15 @@ ODBConn::ODBConn(PGLOBAL g, TDBODBC *tdbp)
m_RowsetSize = (DWORD)((tdbp) ? tdbp->Rows : 10);
m_Catver = (tdbp) ? tdbp->Catver : 0;
m_Rows = 0;
+ m_Fetch = 0;
m_Connect = NULL;
+ m_User = NULL;
+ m_Pwd = NULL;
m_Updatable = true;
m_Transact = false;
m_Scrollable = (tdbp) ? tdbp->Scrollable : false;
- m_First = true;
m_Full = false;
+ m_UseCnc = false;
m_IDQuoteChar[0] = '"';
m_IDQuoteChar[1] = 0;
//*m_ErrMsg = '\0';
@@ -982,7 +989,7 @@ void ODBConn::ThrowDBX(RETCODE rc, PSZ msg, HSTMT hstmt)
void ODBConn::ThrowDBX(PSZ msg)
{
- DBX* xp = new(m_G) DBX(0, msg);
+ DBX* xp = new(m_G) DBX(0, "Error");
xp->m_ErrMsg[0] = msg;
throw xp;
@@ -1061,7 +1068,7 @@ void ODBConn::OnSetOptions(HSTMT hstmt)
/***********************************************************************/
/* Open: connect to a data source. */
/***********************************************************************/
-int ODBConn::Open(PSZ ConnectString, DWORD options)
+int ODBConn::Open(PSZ ConnectString, POPARM sop, DWORD options)
{
PGLOBAL& g = m_G;
//ASSERT_VALID(this);
@@ -1070,6 +1077,11 @@ int ODBConn::Open(PSZ ConnectString, DWORD options)
m_Updatable = !(options & openReadOnly);
m_Connect = ConnectString;
+ m_User = sop->User;
+ m_Pwd = sop->Pwd;
+ m_LoginTimeout = sop->Cto;
+ m_QueryTimeout = sop->Qto;
+ m_UseCnc = sop->UseCnc;
// Allocate the HDBC and make connection
try {
@@ -1078,18 +1090,21 @@ int ODBConn::Open(PSZ ConnectString, DWORD options)
AllocConnect(options);
/*ver = GetStringInfo(SQL_ODBC_VER);*/
- if (Connect(options)) {
- strcpy(g->Message, MSG(CONNECT_CANCEL));
- return 0;
- } // endif
+ if (!m_UseCnc) {
+ if (DriverConnect(options)) {
+ strcpy(g->Message, MSG(CONNECT_CANCEL));
+ return 0;
+ } // endif
+
+ } else // Connect using SQLConnect
+ Connect();
/*ver = GetStringInfo(SQL_DRIVER_ODBC_VER);*/
// Verify support for required functionality and cache info
// VerifyConnect(); Deprecated
GetConnectInfo();
} catch(DBX *xp) {
-// strcpy(g->Message, xp->m_ErrMsg[0]);
- strcpy(g->Message, xp->GetErrorMessage(0));
+ sprintf(g->Message, "%s: %s", xp->m_Msg, xp->GetErrorMessage(0));
Close();
// Free();
return -1;
@@ -1164,9 +1179,26 @@ void ODBConn::AllocConnect(DWORD Options)
} // end of AllocConnect
/***********************************************************************/
+/* Connect to data source using SQLConnect. */
+/***********************************************************************/
+void ODBConn::Connect(void)
+ {
+ SQLRETURN rc;
+ SQLSMALLINT ul = (m_User ? SQL_NTS : 0);
+ SQLSMALLINT pl = (m_Pwd ? SQL_NTS : 0);
+
+ rc = SQLConnect(m_hdbc, (SQLCHAR*)m_Connect, SQL_NTS,
+ (SQLCHAR*)m_User, ul, (SQLCHAR*)m_Pwd, pl);
+
+ if (!Check(rc))
+ ThrowDBX(rc, "SQLConnect");
+
+ } // end of Connect
+
+/***********************************************************************/
/* Connect to data source using SQLDriverConnect. */
/***********************************************************************/
-bool ODBConn::Connect(DWORD Options)
+bool ODBConn::DriverConnect(DWORD Options)
{
RETCODE rc;
SWORD nResult;
@@ -1213,7 +1245,7 @@ bool ODBConn::Connect(DWORD Options)
// All done
return false;
- } // end of Connect
+ } // end of DriverConnect
void ODBConn::VerifyConnect()
{
@@ -1328,7 +1360,7 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols)
rc = SQLFreeStmt(m_hstmt, SQL_CLOSE);
if (!Check(rc))
- ThrowDBX(rc, "SQLFreeStmt");
+ ThrowDBX(rc, "SQLFreeStmt", m_hstmt);
m_hstmt = NULL;
} // endif m_hstmt
@@ -1343,7 +1375,7 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols)
(void*)SQL_SCROLLABLE, 0);
if (!Check(rc))
- ThrowDBX(rc, "SQLSetStmtAttr");
+ ThrowDBX(rc, "Scrollable", hstmt);
} // endif m_Scrollable
@@ -1394,7 +1426,7 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols)
for (n = 0, colp = tocols; colp; colp = (PODBCCOL)colp->GetNext())
if (!colp->IsSpecial())
- n++;
+ n++;
// n can be 0 for query such as Select count(*) from table
if (n && n != (UWORD)ncol)
@@ -1430,7 +1462,7 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols)
for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++)
htrc(x->m_ErrMsg[i]);
- strcpy(m_G->Message, x->GetErrorMessage(0));
+ sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
if (b)
SQLCancel(hstmt);
@@ -1493,7 +1525,7 @@ int ODBConn::GetResultSize(char *sql, ODBCCOL *colp)
/***********************************************************************/
/* Fetch next row. */
/***********************************************************************/
-int ODBConn::Fetch()
+int ODBConn::Fetch(int pos)
{
ASSERT(m_hstmt);
int irc;
@@ -1503,7 +1535,9 @@ int ODBConn::Fetch()
try {
// do {
- if (m_RowsetSize) {
+ if (pos) {
+ rc = SQLExtendedFetch(m_hstmt, SQL_FETCH_ABSOLUTE, pos, &crow, NULL);
+ } else if (m_RowsetSize) {
rc = SQLExtendedFetch(m_hstmt, SQL_FETCH_NEXT, 1, &crow, NULL);
} else {
rc = SQLFetch(m_hstmt);
@@ -1516,29 +1550,22 @@ int ODBConn::Fetch()
m_hstmt, m_RowsetSize, rc);
if (!Check(rc))
- ThrowDBX(rc, "Fetch", m_hstmt);
+ ThrowDBX(rc, "Fetching", m_hstmt);
- irc = (rc == SQL_NO_DATA_FOUND) ? 0 : (int)crow;
-
- if (m_First) {
- // First fetch. Check whether the full table was read
- if ((m_Full = irc < (signed)m_RowsetSize)) {
- m_Tdb->Memory = 0; // Not needed anymore
- m_Rows = irc; // Table size
- } // endif m_Full
-
- m_First = false;
- } // endif m_First
-
- if (m_Tdb->Memory == 1)
- m_Rows += irc;
+ if (rc == SQL_NO_DATA_FOUND) {
+ m_Full = (m_Fetch == 1);
+ irc = 0;
+ } else
+ irc = (int)crow;
+ m_Fetch++;
+ m_Rows += irc;
} catch(DBX *x) {
if (trace)
for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++)
htrc(x->m_ErrMsg[i]);
- strcpy(g->Message, x->GetErrorMessage(0));
+ sprintf(g->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
irc = -1;
} // end try/catch
@@ -1574,7 +1601,7 @@ int ODBConn::PrepareSQL(char *sql)
for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++)
htrc(x->m_ErrMsg[i]);
- strcpy(g->Message, x->GetErrorMessage(0));
+ sprintf(g->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
} // end try/catch
} // endif Mode
@@ -1620,7 +1647,7 @@ int ODBConn::PrepareSQL(char *sql)
for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++)
htrc(x->m_ErrMsg[i]);
- strcpy(g->Message, x->GetErrorMessage(0));
+ sprintf(g->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
if (b)
SQLCancel(hstmt);
@@ -1672,7 +1699,7 @@ int ODBConn::ExecuteSQL(void)
} // endif ncol
} catch(DBX *x) {
- strcpy(m_G->Message, x->GetErrorMessage(0));
+ sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
SQLCancel(m_hstmt);
rc = SQLFreeStmt(m_hstmt, SQL_DROP);
m_hstmt = NULL;
@@ -1709,9 +1736,11 @@ bool ODBConn::BindParam(ODBCCOL *colp)
ThrowDBX(rc, "SQLDescribeParam", m_hstmt);
} catch(DBX *x) {
- strcpy(m_G->Message, x->GetErrorMessage(0));
+ sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
colsize = colp->GetPrecision();
sqlt = GetSQLType(buftype);
+ dec = IsTypeChar(buftype) ? 0 : colp->GetScale();
+ nul = SQL_NULLABLE_UNKNOWN;
} // end try/catch
buf = colp->GetBuffer(0);
@@ -1815,7 +1844,7 @@ bool ODBConn::ExecSQLcommand(char *sql)
for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++)
htrc(x->m_ErrMsg[i]);
- sprintf(g->Message, "Remote: %s", x->GetErrorMessage(0));
+ sprintf(g->Message, "Remote %s: %s", x->m_Msg, x->GetErrorMessage(0));
if (b)
SQLCancel(hstmt);
@@ -1865,9 +1894,6 @@ PQRYRES ODBConn::GetMetaData(PGLOBAL g, char *dsn, char *src)
RETCODE rc;
HSTMT hstmt;
- if (Open(dsn, 10) < 1) // openReadOnly + noOdbcDialog
- return NULL;
-
try {
rc = SQLAllocStmt(m_hdbc, &hstmt);
@@ -1903,7 +1929,7 @@ PQRYRES ODBConn::GetMetaData(PGLOBAL g, char *dsn, char *src)
} // endfor i
} catch(DBX *x) {
- strcpy(g->Message, x->GetErrorMessage(0));
+ sprintf(g->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
goto err;
} // end try/catch
@@ -1954,7 +1980,7 @@ PQRYRES ODBConn::GetMetaData(PGLOBAL g, char *dsn, char *src)
} // endfor i
} catch(DBX *x) {
- strcpy(g->Message, x->GetErrorMessage(0));
+ sprintf(g->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
qrp = NULL;
} // end try/catch
@@ -2006,7 +2032,7 @@ bool ODBConn::GetDataSources(PQRYRES qrp)
} // endfor i
} catch(DBX *x) {
- strcpy(m_G->Message, x->GetErrorMessage(0));
+ sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
rv = true;
} // end try/catch
@@ -2057,7 +2083,7 @@ bool ODBConn::GetDrivers(PQRYRES qrp)
} // endfor n
} catch(DBX *x) {
- strcpy(m_G->Message, x->GetErrorMessage(0));
+ sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
rv = true;
} // end try/catch
@@ -2375,7 +2401,7 @@ int ODBConn::GetCatInfo(CATPARM *cap)
for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++)
htrc(x->m_ErrMsg[i]);
- strcpy(g->Message, x->GetErrorMessage(0));
+ sprintf(g->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
irc = -1;
} // end try/catch
@@ -2479,7 +2505,7 @@ int ODBConn::Rewind(char *sql, ODBCCOL *tocols)
rbuf = (int)crow;
} catch(DBX *x) {
- strcpy(m_G->Message, x->GetErrorMessage(0));
+ sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
rbuf = -1;
} // end try/catch
diff --git a/storage/connect/odbconn.h b/storage/connect/odbconn.h
index dfdb9fe7f56..41cc2439354 100644
--- a/storage/connect/odbconn.h
+++ b/storage/connect/odbconn.h
@@ -119,7 +119,7 @@ class ODBConn : public BLOCK {
noOdbcDialog = 0x0008, // Don't display ODBC Connect dialog
forceOdbcDialog = 0x0010}; // Always display ODBC connect dialog
- int Open(PSZ ConnectString, DWORD Options = 0);
+ int Open(PSZ ConnectString, POPARM sop, DWORD Options = 0);
int Rewind(char *sql, ODBCCOL *tocols);
void Close(void);
PQRYRES AllocateResult(PGLOBAL g);
@@ -135,11 +135,13 @@ class ODBConn : public BLOCK {
public:
// Operations
- void SetLoginTimeout(DWORD sec) {m_LoginTimeout = sec;}
- void SetQueryTimeout(DWORD sec) {m_QueryTimeout = sec;}
+//void SetLoginTimeout(DWORD sec) {m_LoginTimeout = sec;}
+//void SetQueryTimeout(DWORD sec) {m_QueryTimeout = sec;}
+//void SetUserName(PSZ user) {m_User = user;}
+//void SetUserPwd(PSZ pwd) {m_Pwd = pwd;}
int GetResultSize(char *sql, ODBCCOL *colp);
int ExecDirectSQL(char *sql, ODBCCOL *tocols);
- int Fetch(void);
+ int Fetch(int pos = 0);
int PrepareSQL(char *sql);
int ExecuteSQL(void);
bool BindParam(ODBCCOL *colp);
@@ -155,7 +157,7 @@ class ODBConn : public BLOCK {
// Implementation
public:
-// virtual ~ODBConn();
+//virtual ~ODBConn();
// ODBC operations
protected:
@@ -163,7 +165,8 @@ class ODBConn : public BLOCK {
void ThrowDBX(RETCODE rc, PSZ msg, HSTMT hstmt = SQL_NULL_HSTMT);
void ThrowDBX(PSZ msg);
void AllocConnect(DWORD dwOptions);
- bool Connect(DWORD Options);
+ void Connect(void);
+ bool DriverConnect(DWORD Options);
void VerifyConnect(void);
void GetConnectInfo(void);
void Free(void);
@@ -185,11 +188,14 @@ class ODBConn : public BLOCK {
DWORD m_RowsetSize;
char m_IDQuoteChar[2];
PSZ m_Connect;
+ PSZ m_User;
+ PSZ m_Pwd;
int m_Catver;
int m_Rows;
+ int m_Fetch;
bool m_Updatable;
bool m_Transact;
bool m_Scrollable;
- bool m_First;
+ bool m_UseCnc;
bool m_Full;
}; // end of ODBConn class definition
diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp
index d8009bcc71f..d5429e8a344 100644
--- a/storage/connect/plgdbutl.cpp
+++ b/storage/connect/plgdbutl.cpp
@@ -311,7 +311,7 @@ PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids,
else
crp->Kdata = NULL;
- if (g->Trace)
+ if (trace)
htrc("Column(%d) %s type=%d len=%d value=%p\n",
crp->Ncol, crp->Name, crp->Type, crp->Length, crp->Kdata);
diff --git a/storage/connect/plugutil.c b/storage/connect/plugutil.c
index c77975e5e30..18b48b8eccc 100644
--- a/storage/connect/plugutil.c
+++ b/storage/connect/plugutil.c
@@ -144,12 +144,12 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize)
return NULL;
} else {
g->Sarea_Size = worksize;
- g->Trace = 0;
g->Createas = 0;
g->Alchecked = 0;
g->Mrr = 0;
g->Activityp = g->ActivityStart = NULL;
g->Xchk = NULL;
+ g->N = 0;
strcpy(g->Message, "");
/*******************************************************************/
diff --git a/storage/connect/tabdos.h b/storage/connect/tabdos.h
index 156d46b9791..b7150294e9b 100644
--- a/storage/connect/tabdos.h
+++ b/storage/connect/tabdos.h
@@ -222,6 +222,7 @@ class DllExport DOSCOL : public COLBLK {
virtual PVBLK GetDval(void) {return Dval;}
// Methods
+ using COLBLK::Print;
virtual bool VarSize(void);
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
virtual void ReadColumn(PGLOBAL g);
diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp
index a3c56965794..ccc21960bfd 100644
--- a/storage/connect/tabjson.cpp
+++ b/storage/connect/tabjson.cpp
@@ -1,5 +1,5 @@
/************* tabjson C++ Program Source Code File (.CPP) *************/
-/* PROGRAM NAME: tabxjson Version 1.0 */
+/* PROGRAM NAME: tabjson Version 1.0 */
/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */
/* This program are the JSON class DB execution routines. */
/***********************************************************************/
@@ -117,14 +117,15 @@ TDBJSN::TDBJSN(PJDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp)
Jmode = tdp->Jmode;
Xcol = tdp->Xcol;
Fpos = -1;
- Spos = N = 0;
+//Spos = 0;
+ N = 0;
Limit = tdp->Limit;
+ NextSame = 0;
+ SameRow = 0;
+ Xval = -1;
Pretty = tdp->Pretty;
Strict = tdp->Strict;
- NextSame = false;
Comma = false;
- SameRow = 0;
- Xval = -1;
} // end of TDBJSN standard constructor
TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp)
@@ -134,15 +135,15 @@ TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp)
Jmode = tdbp->Jmode;
Xcol = tdbp->Xcol;
Fpos = tdbp->Fpos;
- Spos = tdbp->Spos;
+//Spos = tdbp->Spos;
N = tdbp->N;
Limit = tdbp->Limit;
- Pretty = tdbp->Pretty;
- Strict = tdbp->Strict;
NextSame = tdbp->NextSame;
- Comma = tdbp->Comma;
SameRow = tdbp->SameRow;
Xval = tdbp->Xval;
+ Pretty = tdbp->Pretty;
+ Strict = tdbp->Strict;
+ Comma = tdbp->Comma;
} // end of TDBJSN copy constructor
// Used for update
@@ -221,14 +222,9 @@ bool TDBJSN::OpenDB(PGLOBAL g)
/*******************************************************************/
/* Table already open replace it at its beginning. */
/*******************************************************************/
- for (PJCOL cp = (PJCOL)Columns; cp; cp = (PJCOL)cp->GetNext()) {
- cp->Nx = 0;
- cp->Arp = NULL;
- } // endfor cp
-
Fpos= -1;
- Spos = 0;
- NextSame = false;
+// Spos = 0;
+ NextSame = 0;
SameRow = 0;
} else {
/*******************************************************************/
@@ -292,7 +288,8 @@ int TDBJSN::ReadDB(PGLOBAL g)
N++;
if (NextSame) {
- SameRow++;
+ SameRow = NextSame;
+ NextSame = 0;
return RC_OK;
} else if ((rc = TDBDOS::ReadDB(g)) == RC_OK)
if (!IsRead() && ((rc = ReadBuffer(g)) != RC_OK)) {
@@ -333,21 +330,20 @@ int TDBJSN::ReadDB(PGLOBAL g)
} // end of PrepareWriting
-/* ----------------------------- JSNCOL ------------------------------- */
+/* ---------------------------- JSONCOL ------------------------------ */
/***********************************************************************/
-/* JSNCOL public constructor. */
+/* JSONCOL public constructor. */
/***********************************************************************/
JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
: DOSCOL(g, cdp, tdbp, cprec, i, "DOS")
{
Tjp = (TDBJSN *)(tdbp->GetOrig() ? tdbp->GetOrig() : tdbp);
- Arp = NULL;
Jpath = cdp->GetFmt();
MulVal = NULL;
Nodes = NULL;
- Nod = Nx =0;
- Ival = -1;
+ Nod = 0;
+ Xnod = -1;
Xpd = false;
Parsed = false;
} // end of JSONCOL constructor
@@ -359,13 +355,11 @@ JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
JSONCOL::JSONCOL(JSONCOL *col1, PTDB tdbp) : DOSCOL(col1, tdbp)
{
Tjp = col1->Tjp;
- Arp = col1->Arp;
Jpath = col1->Jpath;
MulVal = col1->MulVal;
Nodes = col1->Nodes;
Nod = col1->Nod;
- Ival = col1->Ival;
- Nx = col1->Nx;
+ Xnod = col1->Xnod;
Xpd = col1->Xpd;
Parsed = col1->Parsed;
} // end of JSONCOL copy constructor
@@ -387,17 +381,16 @@ bool JSONCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
} // end of SetBuffer
/***********************************************************************/
-/* Analyse array processing options. */
+/* Check whether this object is expanded. */
/***********************************************************************/
bool JSONCOL::CheckExpand(PGLOBAL g, int i, PSZ nm, bool b)
{
- if (Tjp->Xcol && nm && !strcmp(nm, Tjp->Xcol) &&
- (Tjp->Xval < 0 || Tjp->Xval == i)) {
+ if ((Tjp->Xcol && nm && !strcmp(nm, Tjp->Xcol) &&
+ (Tjp->Xval < 0 || Tjp->Xval == i)) || Xpd) {
Xpd = true; // Expandable object
- Nodes[i].Op = OP_XX;
- Tjp->Xval = i;
+ Nodes[i].Op = OP_EXP;
} else if (b) {
- strcpy(g->Message, "Cannot expand more than one array");
+ strcpy(g->Message, "Cannot expand more than one branch");
return true;
} // endif Xcol
@@ -434,7 +427,7 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
// Default specifications
if (CheckExpand(g, i, nm, false))
return true;
- else if (jnp->Op != OP_XX)
+ else if (jnp->Op != OP_EXP)
if (!Value->IsTypeNum()) {
jnp->CncVal = AllocateValue(g, (void*)", ", TYPE_STRING);
jnp->Op = OP_CNC;
@@ -456,13 +449,13 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
case '*': jnp->Op = OP_MULT; break;
case '>': jnp->Op = OP_MAX; break;
case '<': jnp->Op = OP_MIN; break;
- case '#': jnp->Op = OP_NUM; break;
case '!': jnp->Op = OP_SEP; break; // Average
+ case '#': jnp->Op = OP_NUM; break;
case 'x':
case 'X': // Expand this array
if (!Tjp->Xcol && nm) {
Xpd = true;
- jnp->Op = OP_XX;
+ jnp->Op = OP_EXP;
Tjp->Xval = i;
Tjp->Xcol = nm;
} else if (CheckExpand(g, i, nm, true))
@@ -490,6 +483,38 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
return true;
} // endif's
+ // For calculated arrays, a local Value must be used
+ switch (jnp->Op) {
+ case OP_NUM:
+ jnp->Valp = AllocateValue(g, TYPE_INT);
+ break;
+ case OP_ADD:
+ case OP_MULT:
+ case OP_SEP:
+ if (!IsTypeChar(Buf_Type))
+ jnp->Valp = AllocateValue(g, Buf_Type, 0, GetPrecision());
+ else
+ jnp->Valp = AllocateValue(g, TYPE_DOUBLE, 0, 2);
+
+ break;
+ case OP_MIN:
+ case OP_MAX:
+ jnp->Valp = AllocateValue(g, Buf_Type, Long, GetPrecision());
+ break;
+ case OP_CNC:
+ if (IsTypeChar(Buf_Type))
+ jnp->Valp = AllocateValue(g, TYPE_STRING, Long, GetPrecision());
+ else
+ jnp->Valp = AllocateValue(g, TYPE_STRING, 512);
+
+ break;
+ default:
+ break;
+ } // endswitch Op
+
+ if (jnp->Valp)
+ MulVal = AllocateValue(g, jnp->Valp);
+
return false;
} // end of SetArrayOptions
@@ -533,6 +558,9 @@ bool JSONCOL::ParseJpath(PGLOBAL g)
if (SetArrayOptions(g, p, i, Nodes[i-1].Key))
return true;
+ } else if (*p == '*') {
+ // Return JSON
+ Nodes[i].Op = OP_XX;
} else {
Nodes[i].Key = p;
Nodes[i].Op = OP_EXIST;
@@ -546,42 +574,50 @@ bool JSONCOL::ParseJpath(PGLOBAL g)
} // end of ParseJpath
/***********************************************************************/
+/* MakeJson: Serialize the json item and set value to it. */
+/***********************************************************************/
+PVAL JSONCOL::MakeJson(PGLOBAL g, PJSON jsp)
+ {
+ if (Value->IsTypeNum()) {
+ strcpy(g->Message, "Cannot make Json for a numeric column");
+ Value->Reset();
+ } else
+ Value->SetValue_psz(Serialize(g, jsp, NULL, 0));
+
+ return Value;
+ } // end of MakeJson
+
+/***********************************************************************/
/* SetValue: Set a value from a JVALUE contains. */
/***********************************************************************/
void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n)
{
if (val) {
- if (Nodes[n].Op == OP_NUM)
- vp->SetValue(1);
- else {
- again:
- switch (val->GetValType()) {
- case TYPE_STRG:
- case TYPE_INTG:
- case TYPE_DBL:
- vp->SetValue_pval(val->GetValue());
- break;
- case TYPE_BOOL:
- if (vp->IsTypeNum())
- vp->SetValue(val->GetInteger() ? 1 : 0);
- else
- vp->SetValue_psz((PSZ)(val->GetInteger() ? "true" : "false"));
-
+ switch (val->GetValType()) {
+ case TYPE_STRG:
+ case TYPE_INTG:
+ case TYPE_DBL:
+ vp->SetValue_pval(val->GetValue());
+ break;
+ case TYPE_BOOL:
+ if (vp->IsTypeNum())
+ vp->SetValue(val->GetInteger() ? 1 : 0);
+ else
+ vp->SetValue_psz((PSZ)(val->GetInteger() ? "true" : "false"));
+
+ break;
+ case TYPE_JAR:
+ SetJsonValue(g, vp, val->GetArray()->GetValue(0), n);
+ break;
+ case TYPE_JOB:
+// if (!vp->IsTypeNum() || !Strict) {
+ vp->SetValue_psz(val->GetObject()->GetText(g, NULL));
break;
- case TYPE_JAR:
- val = val->GetArray()->GetValue(0);
- goto again;
- case TYPE_JOB:
- if (!vp->IsTypeNum()) {
- vp->SetValue_psz(val->GetObject()->GetText(g));
- break;
- } // endif Type
+// } // endif Type
- default:
- vp->Reset();
- } // endswitch Type
-
- } // endelse
+ default:
+ vp->Reset();
+ } // endswitch Type
} else
vp->Reset();
@@ -589,16 +625,210 @@ void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n)
} // end of SetJsonValue
/***********************************************************************/
+/* ReadColumn: */
+/***********************************************************************/
+void JSONCOL::ReadColumn(PGLOBAL g)
+ {
+ if (!Tjp->SameRow || Xnod >= Tjp->SameRow)
+ Value->SetValue_pval(GetColumnValue(g, Tjp->Row, 0));
+
+ } // end of ReadColumn
+
+/***********************************************************************/
+/* GetColumnValue: */
+/***********************************************************************/
+PVAL JSONCOL::GetColumnValue(PGLOBAL g, PJSON row, int i)
+ {
+ int n = Nod - 1;
+ bool expd = false;
+ PJAR arp;
+ PJVAL val = NULL;
+
+ for (; i < Nod && row; i++) {
+ if (Nodes[i].Op == OP_NUM) {
+ Value->SetValue(row->GetType() == TYPE_JAR ? row->size() : 1);
+ return(Value);
+ } else if (Nodes[i].Op == OP_XX) {
+ return MakeJson(g, row);
+ } else switch (row->GetType()) {
+ case TYPE_JOB:
+ if (!Nodes[i].Key) {
+ // Expected Array was not there
+ if (i < Nod-1)
+ continue;
+ else
+ val = new(g) JVALUE(row);
+
+ } else
+ val = ((PJOB)row)->GetValue(Nodes[i].Key);
+
+ break;
+ case TYPE_JAR:
+ arp = (PJAR)row;
+
+ if (!Nodes[i].Key) {
+ if (Nodes[i].Op != OP_NULL) {
+ if (Nodes[i].Rank) {
+ val = arp->GetValue(Nodes[i].Rank - 1);
+ } else if (Nodes[i].Op == OP_EXP) {
+ return ExpandArray(g, arp, i);
+ } else
+ return CalculateArray(g, arp, i);
+
+ } else
+ val = NULL;
+
+ } else if (i < Nod-1) {
+ strcpy(g->Message, "Unexpected array");
+ val = NULL; // Not an expected array
+ } else
+ val = arp->GetValue(0);
+
+ break;
+ case TYPE_JVAL:
+ val = (PJVAL)row;
+ break;
+ default:
+ sprintf(g->Message, "Invalid row JSON type %d", row->GetType());
+ val = NULL;
+ } // endswitch Type
+
+ if (i < Nod-1)
+ row = (val) ? val->GetJson() : NULL;
+
+ } // endfor i
+
+ SetJsonValue(g, Value, val, n);
+ return Value;
+ } // end of GetColumnValue
+
+/***********************************************************************/
+/* ExpandArray: */
+/***********************************************************************/
+PVAL JSONCOL::ExpandArray(PGLOBAL g, PJAR arp, int n)
+ {
+ int ars;
+ PJVAL jvp;
+ JVALUE jval;
+
+ ars = MY_MIN(Tjp->Limit, arp->size());
+
+ if (!(jvp = arp->GetValue(Nodes[n].Nx))) {
+ strcpy(g->Message, "Logical error expanding array");
+ longjmp(g->jumper[g->jump_level], 666);
+ } // endif jvp
+
+ if (n < Nod - 1 && jvp->GetJson()) {
+ jval.SetValue(GetColumnValue(g, jvp->GetJson(), n + 1));
+ jvp = &jval;
+ } // endif n
+
+ if (n >= Tjp->NextSame) {
+ if (++Nodes[n].Nx == ars) {
+ Nodes[n].Nx = 0;
+ Xnod = 0;
+ } else
+ Xnod = n;
+
+ Tjp->NextSame = Xnod;
+ } // endif NextSame
+
+ SetJsonValue(g, Value, jvp, n);
+ return Value;
+ } // end of ExpandArray
+
+/***********************************************************************/
+/* CalculateArray: */
+/***********************************************************************/
+PVAL JSONCOL::CalculateArray(PGLOBAL g, PJAR arp, int n)
+ {
+ int i, ars, nv = 0, nextsame = Tjp->NextSame;
+ bool err;
+ OPVAL op = Nodes[n].Op;
+ PVAL val[2], vp = Nodes[n].Valp;
+ PJVAL jvrp, jvp;
+ JVALUE jval;
+
+ vp->Reset();
+ ars = MY_MIN(Tjp->Limit, arp->size());
+
+ for (i = 0; i < ars; i++) {
+ jvrp = arp->GetValue(i);
+
+ do {
+ if (n < Nod - 1 && jvrp->GetJson()) {
+ Tjp->NextSame = nextsame;
+ jval.SetValue(GetColumnValue(g, jvrp->GetJson(), n + 1));
+ jvp = &jval;
+ } else
+ jvp = jvrp;
+
+ if (!nv++) {
+ SetJsonValue(g, vp, jvp, n);
+ continue;
+ } else
+ SetJsonValue(g, MulVal, jvp, n);
+
+ if (!MulVal->IsZero()) {
+ switch (op) {
+ case OP_CNC:
+ if (Nodes[n].CncVal) {
+ val[0] = Nodes[n].CncVal;
+ err = vp->Compute(g, val, 1, op);
+ } // endif CncVal
+
+ val[0] = MulVal;
+ err = vp->Compute(g, val, 1, op);
+ break;
+// case OP_NUM:
+ case OP_SEP:
+ val[0] = Nodes[n].Valp;
+ val[1] = MulVal;
+ err = vp->Compute(g, val, 2, OP_ADD);
+ break;
+ default:
+ val[0] = Nodes[n].Valp;
+ val[1] = MulVal;
+ err = vp->Compute(g, val, 2, op);
+ } // endswitch Op
+
+ if (err)
+ vp->Reset();
+
+ } // endif Zero
+
+ } while (Tjp->NextSame > nextsame);
+
+ } // endfor i
+
+ if (op == OP_SEP) {
+ // Calculate average
+ MulVal->SetValue(nv);
+ val[0] = vp;
+ val[1] = MulVal;
+
+ if (vp->Compute(g, val, 2, OP_DIV))
+ vp->Reset();
+
+ } // endif Op
+
+ Tjp->NextSame = nextsame;
+ return vp;
+ } // end of CalculateArray
+
+/***********************************************************************/
/* GetRow: Get the object containing this column. */
/***********************************************************************/
-PJSON JSONCOL::GetRow(PGLOBAL g, int mode)
+PJSON JSONCOL::GetRow(PGLOBAL g)
{
PJVAL val;
PJAR arp;
PJSON nwr, row = Tjp->Row;
for (int i = 0; i < Nod-1 && row; i++) {
- switch (row->GetType()) {
+ if (Nodes[i+1].Op == OP_XX)
+ break;
+ else switch (row->GetType()) {
case TYPE_JOB:
if (!Nodes[i].Key)
// Expected Array was not there
@@ -609,21 +839,13 @@ PJSON JSONCOL::GetRow(PGLOBAL g, int mode)
case TYPE_JAR:
if (!Nodes[i].Key) {
if (Nodes[i].Op != OP_NULL) {
- Ival = i;
arp = (PJAR)row;
- if (mode < 2) // First pass
- Arp = arp;
-
- if (Nodes[i].Op != OP_XX) {
- if (Nodes[i].Rank)
- val = arp->GetValue(Nodes[i].Rank - 1);
- else
- val = arp->GetValue(arp == Arp ? Nx : 0);
+ if (Nodes[i].Rank)
+ val = arp->GetValue(Nodes[i].Rank - 1);
+ else
+ val = arp->GetValue(Nodes[i].Nx);
- } else
- val = arp->GetValue(Tjp->SameRow);
-
} else
val = NULL;
@@ -643,15 +865,16 @@ PJSON JSONCOL::GetRow(PGLOBAL g, int mode)
if (val) {
row = val->GetJson();
- } else if (mode == 1) { // mode write
+ } else {
// Construct missing objects
for (i++; row && i < Nod; i++) {
- if (!Nodes[i].Key) {
+ if (Nodes[i].Op == OP_XX)
+ break;
+ else if (!Nodes[i].Key)
// Construct intermediate array
nwr = new(g) JARRAY;
- } else {
+ else
nwr = new(g) JOBJECT;
- } // endif Nodes
if (row->GetType() == TYPE_JOB) {
((PJOB)row)->SetValue(g, new(g) JVALUE(nwr), Nodes[i-1].Key);
@@ -667,8 +890,7 @@ PJSON JSONCOL::GetRow(PGLOBAL g, int mode)
} // endfor i
break;
- } else
- row = NULL;
+ } // endelse
} // endfor i
@@ -676,131 +898,6 @@ PJSON JSONCOL::GetRow(PGLOBAL g, int mode)
} // end of GetRow
/***********************************************************************/
-/* ReadColumn: */
-/***********************************************************************/
-void JSONCOL::ReadColumn(PGLOBAL g)
- {
- int mode = 0, n = Nod - 1;
- PJSON row;
- PJVAL val = NULL;
-
- evenmore:
- row = GetRow(g, mode);
-
- more:
- if (row) switch (row->GetType()) {
- case TYPE_JOB:
- if (Nodes[n].Key)
- val = row->GetValue(Nodes[n].Key);
- else
- val = new(g) JVALUE(row);
-
- break;
- case TYPE_JAR:
- // Multiple column ?
- if (Nodes[n].Op != OP_NULL) {
- Arp = (PJAR)row;
- val = Arp->GetValue(Nodes[n].Rank > 0 ?
- Nodes[n].Rank - 1 :
- Nodes[n].Op == OP_XX ? Tjp->SameRow : Nx);
- Ival = n;
- } else
- val = NULL;
-
- break;
- case TYPE_JVAL:
- val = (PJVAL)row;
- break;
- default:
- sprintf(g->Message, "Wrong return value type %d", row->GetType());
- Value->Reset();
- return;
- } // endswitch Type
-
- if (!Nx /*|| (Xpd)*/)
- SetJsonValue(g, Value, val, n);
-
- if (Arp) {
- // Multiple column
- int ars = (Nodes[Ival].Rank > 0) ? 1 : MY_MIN(Tjp->Limit, Arp->size());
-
- if (Nodes[Ival].Op == OP_XX) {
- if (ars > Tjp->SameRow + 1)
- Tjp->NextSame = true; // More to come
- else {
- Tjp->NextSame = false;
- Arp = NULL;
- } // endelse
-
- } else {
- if (Nx && val) {
- SetJsonValue(g, MulVal, val, Ival);
-
- if (!MulVal->IsZero()) {
- PVAL val[2];
- bool err;
-
- switch (Nodes[Ival].Op) {
- case OP_CNC:
- if (Nodes[Ival].CncVal) {
- val[0] = Nodes[Ival].CncVal;
- err = Value->Compute(g, val, 1, Nodes[Ival].Op);
- } // endif CncVal
-
- val[0] = MulVal;
- err = Value->Compute(g, val, 1, Nodes[Ival].Op);
- break;
- case OP_NUM:
- case OP_SEP:
- val[0] = Value;
- val[1] = MulVal;
- err = Value->Compute(g, val, 2, OP_ADD);
- break;
- default:
- val[0] = Value;
- val[1] = MulVal;
- err = Value->Compute(g, val, 2, Nodes[Ival].Op);
- } // endswitch Op
-
- if (err)
- Value->Reset();
-
- } // endif Zero
-
- } // endif Nx
-
- if (ars > ++Nx) {
- if (Ival != n) {
- mode = 2;
- goto evenmore;
- } else
- goto more;
-
- } else {
- if (Nodes[Ival].Op == OP_SEP) {
- // Calculate average
- PVAL val[2];
-
- MulVal->SetValue(ars);
- val[0] = Value;
- val[1] = MulVal;
-
- if (Value->Compute(g, val, 2, OP_DIV))
- Value->Reset();
-
- } // endif Op
-
- Arp = NULL;
- Nx = 0;
- } // endif ars
-
- } // endif Op
-
- } // endif Arp
-
- } // end of ReadColumn
-
-/***********************************************************************/
/* WriteColumn: */
/***********************************************************************/
void JSONCOL::WriteColumn(PGLOBAL g)
@@ -817,10 +914,11 @@ void JSONCOL::WriteColumn(PGLOBAL g)
if (Value->IsNull() && Tjp->Mode == MODE_INSERT)
return;
+ char *s;
PJOB objp = NULL;
PJAR arp = NULL;
PJVAL jvp = NULL;
- PJSON row = GetRow(g, 1);
+ PJSON jsp, row = GetRow(g);
JTYP type = row->GetType();
switch (row->GetType()) {
@@ -832,6 +930,32 @@ void JSONCOL::WriteColumn(PGLOBAL g)
if (row) switch (Buf_Type) {
case TYPE_STRING:
+ if (Nodes[Nod-1].Op == OP_XX) {
+ s = Value->GetCharValue();
+
+ if (!(jsp = ParseJson(g, s, (int)strlen(s), 0))) {
+ strcpy(g->Message, s);
+ longjmp(g->jumper[g->jump_level], 666);
+ } // endif jsp
+
+ if (arp) {
+ if (Nod > 1 && Nodes[Nod-2].Rank)
+ arp->SetValue(g, new(g) JVALUE(jsp), Nodes[Nod-2].Rank-1);
+ else
+ arp->AddValue(g, new(g) JVALUE(jsp));
+
+ arp->InitArray(g);
+ } else if (objp) {
+ if (Nod > 1 && Nodes[Nod-2].Key)
+ objp->SetValue(g, new(g) JVALUE(jsp), Nodes[Nod-2].Key);
+
+ } else if (jvp)
+ jvp->SetValue(jsp);
+
+ break;
+ } // endif Op
+
+ // Passthru
case TYPE_DATE:
case TYPE_INT:
case TYPE_DOUBLE:
@@ -1167,6 +1291,51 @@ int TDBJSON::MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add)
} // end of MakeIndex
/***********************************************************************/
+/* Return the position in the table. */
+/***********************************************************************/
+int TDBJSON::GetRecpos(void)
+ {
+#if 0
+ union {
+ uint Rpos;
+ BYTE Spos[4];
+ };
+
+ Rpos = htonl(Fpos);
+ Spos[0] = (BYTE)NextSame;
+ return Rpos;
+#endif // 0
+ return Fpos;
+ } // end of GetRecpos
+
+/***********************************************************************/
+/* Set the position in the table. */
+/***********************************************************************/
+bool TDBJSON::SetRecpos(PGLOBAL g, int recpos)
+ {
+#if 0
+ union {
+ uint Rpos;
+ BYTE Spos[4];
+ };
+
+ Rpos = recpos;
+ NextSame = Spos[0];
+ Spos[0] = 0;
+ Fpos = (signed)ntohl(Rpos);
+
+//if (Fpos != (signed)ntohl(Rpos)) {
+// Fpos = ntohl(Rpos);
+// same = false;
+//} else
+// same = true;
+#endif // 0
+
+ Fpos = recpos - 1;
+ return false;
+ } // end of SetRecpos
+
+/***********************************************************************/
/* JSON Access Method opening routine. */
/***********************************************************************/
bool TDBJSON::OpenDB(PGLOBAL g)
@@ -1175,13 +1344,7 @@ bool TDBJSON::OpenDB(PGLOBAL g)
/*******************************************************************/
/* Table already open replace it at its beginning. */
/*******************************************************************/
- for (PJCOL cp = (PJCOL)Columns; cp; cp = (PJCOL)cp->GetNext()) {
- cp->Nx = 0;
- cp->Arp = NULL;
- } // endfor cp
-
Fpos= -1;
- Spos = 0;
NextSame = false;
SameRow = 0;
return false;
@@ -1217,7 +1380,8 @@ int TDBJSON::ReadDB(PGLOBAL g)
N++;
if (NextSame) {
- SameRow++;
+ SameRow = NextSame;
+ NextSame = false;
rc = RC_OK;
} else if (++Fpos < (signed)Doc->size()) {
Row = Doc->GetValue(Fpos);
@@ -1257,9 +1421,10 @@ int TDBJSON::WriteDB(PGLOBAL g)
return RC_FX;
} else { // if (Jmode == MODE_VALUE)
- if (Mode == MODE_INSERT)
+ if (Mode == MODE_INSERT) {
Doc->AddValue(g, (PJVAL)Row);
- else if (Doc->SetValue(g, (PJVAL)Row, Fpos))
+ Row = new(g) JVALUE;
+ } else if (Doc->SetValue(g, (PJVAL)Row, Fpos))
return RC_FX;
} // endif Jmode
diff --git a/storage/connect/tabjson.h b/storage/connect/tabjson.h
index 68f79a1526a..397c2cf5d3a 100644
--- a/storage/connect/tabjson.h
+++ b/storage/connect/tabjson.h
@@ -16,8 +16,6 @@ typedef class JSONDEF *PJDEF;
typedef class TDBJSON *PJTDB;
typedef class JSONCOL *PJCOL;
-class TDBJSN;
-
/***********************************************************************/
/* The JSON tree node. Can be an Object or an Array. */
/***********************************************************************/
@@ -25,7 +23,9 @@ typedef struct _jnode {
PSZ Key; // The key used for object
OPVAL Op; // Operator used for this node
PVAL CncVal; // To cont value used for OP_CNC
+ PVAL Valp; // The internal array VALUE
int Rank; // The rank in array
+ int Nx; // Same row number
} JNODE, *PJNODE;
/***********************************************************************/
@@ -77,7 +77,7 @@ class TDBJSN : public TDBDOS {
virtual PTDB CopyOne(PTABS t);
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual PCOL InsertSpecialColumn(PGLOBAL g, PCOL colp);
- virtual int RowNumber(PGLOBAL g, BOOL b = FALSE)
+ virtual int RowNumber(PGLOBAL g, bool b = FALSE)
{return (b) ? N : Fpos + 1;}
// Database routines
@@ -94,15 +94,15 @@ class TDBJSN : public TDBDOS {
JMODE Jmode; // MODE_OBJECT by default
char *Xcol; // Name of expandable column
int Fpos; // The current row index
- int Spos; // DELETE start index
+//int Spos; // DELETE start index
int N; // The current Rownum
int Limit; // Limit of multiple values
int Pretty; // Depends on file structure
- bool Strict; // Strict syntax checking
- bool NextSame; // Same next row
- bool Comma; // Row has final comma
+ int NextSame; // Same next row
int SameRow; // Same row nb
int Xval; // Index of expandable array
+ bool Strict; // Strict syntax checking
+ bool Comma; // Row has final comma
}; // end of class TDBJSN
/* -------------------------- JSONCOL class -------------------------- */
@@ -130,8 +130,12 @@ class JSONCOL : public DOSCOL {
protected:
bool CheckExpand(PGLOBAL g, int i, PSZ nm, bool b);
bool SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm);
- PJSON GetRow(PGLOBAL g, int mode);
+ PVAL GetColumnValue(PGLOBAL g, PJSON row, int i);
+ PVAL ExpandArray(PGLOBAL g, PJAR arp, int n);
+ PVAL CalculateArray(PGLOBAL g, PJAR arp, int n);
+ PVAL MakeJson(PGLOBAL g, PJSON jsp);
void SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n);
+ PJSON GetRow(PGLOBAL g);
// Default constructor not to be used
JSONCOL(void) {}
@@ -139,12 +143,10 @@ class JSONCOL : public DOSCOL {
// Members
TDBJSN *Tjp; // To the JSN table block
PVAL MulVal; // To value used by multiple column
- PJAR Arp; // The intermediate array
char *Jpath; // The json path
- JNODE *Nodes ; // The intermediate objects
+ JNODE *Nodes; // The intermediate objects
int Nod; // The number of intermediate objects
- int Ival; // Index of multiple values
- int Nx; // The last read sub-row
+ int Xnod; // Index of multiple values
bool Xpd; // True for expandable column
bool Parsed; // True when parsed
}; // end of class JSONCOL
@@ -172,7 +174,9 @@ class TDBJSON : public TDBJSN {
virtual int Cardinality(PGLOBAL g);
virtual int GetMaxSize(PGLOBAL g);
virtual void ResetSize(void);
- virtual int GetRecpos(void) {return Fpos;}
+ virtual int GetProgCur(void) {return N;}
+ virtual int GetRecpos(void);
+ virtual bool SetRecpos(PGLOBAL g, int recpos);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual bool PrepareWriting(PGLOBAL g) {return false;}
diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp
index 54627ba43fd..33a4dd67d38 100644
--- a/storage/connect/tabmysql.cpp
+++ b/storage/connect/tabmysql.cpp
@@ -1141,19 +1141,16 @@ int TDBMYSQL::WriteDB(PGLOBAL g)
int rc;
uint len = Query->GetLength();
char buf[64];
- bool b, oom = false;
+ bool oom = false;
// Make the Insert command value list
for (PCOL colp = Columns; colp; colp = colp->GetNext()) {
if (!colp->GetValue()->IsNull()) {
- if ((b = colp->GetResultType() == TYPE_STRING ||
- colp->GetResultType() == TYPE_DATE))
- oom |= Query->Append('\'');
-
- oom |= Query->Append(colp->GetValue()->GetCharString(buf));
-
- if (b)
- oom |= Query->Append('\'');
+ if (colp->GetResultType() == TYPE_STRING ||
+ colp->GetResultType() == TYPE_DATE)
+ oom |= Query->Append_quoted(colp->GetValue()->GetCharString(buf));
+ else
+ oom |= Query->Append(colp->GetValue()->GetCharString(buf));
} else
oom |= Query->Append("NULL");
diff --git a/storage/connect/taboccur.cpp b/storage/connect/taboccur.cpp
index 86f0bd20d47..f34d5f9bb11 100644
--- a/storage/connect/taboccur.cpp
+++ b/storage/connect/taboccur.cpp
@@ -355,7 +355,7 @@ bool TDBOCCUR::MakeColumnList(PGLOBAL g)
for (colp = Columns; colp; colp = colp->GetNext())
if (colp->GetAmType() == TYPE_AM_PRX)
- if (((PPRXCOL)colp)->Init(g))
+ if (((PPRXCOL)colp)->Init(g, NULL))
return true;
Col = (PCOL*)PlugSubAlloc(g, NULL, Mult * sizeof(PCOL));
diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp
index 2b771bcbead..3bf1238cebc 100644
--- a/storage/connect/tabodbc.cpp
+++ b/storage/connect/tabodbc.cpp
@@ -66,8 +66,8 @@
#include "plgdbsem.h"
#include "mycat.h"
#include "xtable.h"
-#include "tabodbc.h"
#include "odbccat.h"
+#include "tabodbc.h"
#include "tabmul.h"
#include "reldef.h"
#include "tabcol.h"
@@ -93,9 +93,10 @@ bool ExactInfo(void);
/***********************************************************************/
ODBCDEF::ODBCDEF(void)
{
- Connect= Tabname= Tabschema= Tabcat= Srcdef= Qchar= Qrystr= Sep= NULL;
+ Connect = Tabname = Tabschema = Username = Password = NULL;
+ Tabcat = Srcdef = Qchar = Qrystr = Sep = NULL;
Catver = Options = Cto = Qto = Quoted = Maxerr = Maxres = 0;
- Scrollable = Memory = Xsrc = false;
+ Scrollable = Memory = Xsrc = UseCnc = false;
} // end of ODBCDEF constructor
/***********************************************************************/
@@ -117,6 +118,8 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Tabschema = GetStringCatInfo(g, "Schema", Tabschema);
Tabcat = GetStringCatInfo(g, "Qualifier", NULL);
Tabcat = GetStringCatInfo(g, "Catalog", Tabcat);
+ Username = GetStringCatInfo(g, "User", NULL);
+ Password = GetStringCatInfo(g, "Password", NULL);
if ((Srcdef = GetStringCatInfo(g, "Srcdef", NULL)))
Read_Only = true;
@@ -132,8 +135,16 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
//Options = ODBConn::noOdbcDialog | ODBConn::useCursorLib;
Cto= GetIntCatInfo("ConnectTimeout", DEFAULT_LOGIN_TIMEOUT);
Qto= GetIntCatInfo("QueryTimeout", DEFAULT_QUERY_TIMEOUT);
- Scrollable = GetBoolCatInfo("Scrollable", false);
- Memory = GetBoolCatInfo("Memory", false);
+
+ if ((Scrollable = GetBoolCatInfo("Scrollable", false)) && !Elemt)
+ Elemt = 1; // Cannot merge SQLFetch and SQLExtendedFetch
+
+ UseCnc = GetBoolCatInfo("UseDSN", false);
+
+ // Memory was Boolean, it is now integer
+ if (!(Memory = GetIntCatInfo("Memory", 0)))
+ Memory = GetBoolCatInfo("Memory", false) ? 1 : 0;
+
Pseudo = 2; // FILID is Ok but not ROWID
return false;
} // end of DefineAM
@@ -190,34 +201,40 @@ TDBODBC::TDBODBC(PODEF tdp) : TDBASE(tdp)
Connect = tdp->Connect;
TableName = tdp->Tabname;
Schema = tdp->Tabschema;
+ Ops.User = tdp->Username;
+ Ops.Pwd = tdp->Password;
Catalog = tdp->Tabcat;
Srcdef = tdp->Srcdef;
Qrystr = tdp->Qrystr;
Sep = tdp->GetSep();
Options = tdp->Options;
- Cto = tdp->Cto;
- Qto = tdp->Qto;
+ Ops.Cto = tdp->Cto;
+ Ops.Qto = tdp->Qto;
Quoted = MY_MAX(0, tdp->GetQuoted());
Rows = tdp->GetElemt();
Catver = tdp->Catver;
- Memory = (tdp->Memory) ? 1 : 0;
+ Memory = tdp->Memory;
Scrollable = tdp->Scrollable;
+ Ops.UseCnc = tdp->UseCnc;
} else {
Connect = NULL;
TableName = NULL;
Schema = NULL;
+ Ops.User = NULL;
+ Ops.Pwd = NULL;
Catalog = NULL;
Srcdef = NULL;
Qrystr = NULL;
Sep = 0;
Options = 0;
- Cto = DEFAULT_LOGIN_TIMEOUT;
- Qto = DEFAULT_QUERY_TIMEOUT;
+ Ops.Cto = DEFAULT_LOGIN_TIMEOUT;
+ Ops.Qto = DEFAULT_QUERY_TIMEOUT;
Quoted = 0;
Rows = 0;
Catver = 0;
Memory = 0;
Scrollable = false;
+ Ops.UseCnc = false;
} // endif tdp
Quote = NULL;
@@ -228,11 +245,13 @@ TDBODBC::TDBODBC(PODEF tdp) : TDBASE(tdp)
DBQ = NULL;
Qrp = NULL;
Fpos = 0;
+ Curpos = 0;
AftRows = 0;
CurNum = 0;
Rbuf = 0;
BufSize = 0;
Nparm = 0;
+ Placed = false;
} // end of TDBODBC standard constructor
TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBASE(tdbp)
@@ -242,6 +261,7 @@ TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBASE(tdbp)
Connect = tdbp->Connect;
TableName = tdbp->TableName;
Schema = tdbp->Schema;
+ Ops = tdbp->Ops;
Catalog = tdbp->Catalog;
Srcdef = tdbp->Srcdef;
Qrystr = tdbp->Qrystr;
@@ -254,19 +274,17 @@ TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBASE(tdbp)
MulConn = tdbp->MulConn;
DBQ = tdbp->DBQ;
Options = tdbp->Options;
- Cto = tdbp->Cto;
- Qto = tdbp->Qto;
Quoted = tdbp->Quoted;
Rows = tdbp->Rows;
- Fpos = tdbp->Fpos;
- AftRows = tdbp->AftRows;
-//Tpos = tdbp->Tpos;
-//Spos = tdbp->Spos;
- CurNum = tdbp->CurNum;
- Rbuf = tdbp->Rbuf;
+ Fpos = 0;
+ Curpos = 0;
+ AftRows = 0;
+ CurNum = 0;
+ Rbuf = 0;
BufSize = tdbp->BufSize;
Nparm = tdbp->Nparm;
Qrp = tdbp->Qrp;
+ Placed = false;
} // end of TDBODBC copy constructor
// Method
@@ -370,7 +388,7 @@ int TDBODBC::Decode(char *txt, char *buf, size_t n)
/***********************************************************************/
char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
{
- char *colist, *tabname, *sql, buf[64];
+ char *colist, *tabname, *sql, buf[NAM_LEN * 3];
LPCSTR schmp = NULL, catp = NULL;
int len, ncol = 0;
bool first = true;
@@ -474,6 +492,9 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
if (To_CondFil)
strcat(strcat(sql, " WHERE "), To_CondFil->Body);
+
+ if (trace)
+ htrc("sql: '%s'\n", sql);
return sql;
} // end of MakeSQL
@@ -483,7 +504,7 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
/***********************************************************************/
char *TDBODBC::MakeInsert(PGLOBAL g)
{
- char *stmt, *colist, *valist;
+ char *stmt, *colist, *valist, buf[NAM_LEN * 3];
// char *tk = "`";
int len = 0;
bool b = FALSE;
@@ -510,10 +531,13 @@ char *TDBODBC::MakeInsert(PGLOBAL g)
} else
b = true;
+ // Column name can be in UTF-8 encoding
+ Decode(colp->GetName(), buf, sizeof(buf));
+
if (Quote)
- strcat(strcat(strcat(colist, Quote), colp->GetName()), Quote);
+ strcat(strcat(strcat(colist, Quote), buf), Quote);
else
- strcat(colist, colp->GetName());
+ strcat(colist, buf);
strcat(valist, "?"); // Parameter marker
} // endfor colp
@@ -558,8 +582,7 @@ bool TDBODBC::BindParameters(PGLOBAL g)
/***********************************************************************/
char *TDBODBC::MakeCommand(PGLOBAL g)
{
- char *p, name[68], *qc = Ocp->GetQuoteChar();
- char *stmt = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 64);
+ char *p, *stmt, name[68], *body = NULL, *qc = Ocp->GetQuoteChar();
char *qrystr = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 1);
bool qtd = Quoted > 0;
int i = 0, k = 0;
@@ -570,6 +593,15 @@ char *TDBODBC::MakeCommand(PGLOBAL g)
qrystr[i] = (Qrystr[i] == '`') ? *qc : tolower(Qrystr[i]);
} while (Qrystr[i++]);
+ if (To_CondFil && (p = strstr(qrystr, " where "))) {
+ p[7] = 0; // Remove where clause
+ Qrystr[(p - qrystr) + 7] = 0;
+ body = To_CondFil->Body;
+ stmt = (char*)PlugSubAlloc(g, NULL, strlen(qrystr)
+ + strlen(body) + 64);
+ } else
+ stmt = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 64);
+
// Check whether the table name is equal to a keyword
// If so, it must be quoted in the original query
strlwr(strcat(strcat(strcpy(name, " "), Name), " "));
@@ -597,6 +629,9 @@ char *TDBODBC::MakeCommand(PGLOBAL g)
stmt[i++] = (Qrystr[k] == '`') ? *qc : Qrystr[k];
} while (Qrystr[k++]);
+ if (body)
+ strcat(stmt, body);
+
} else {
sprintf(g->Message, "Cannot use this %s command",
(Mode == MODE_UPDATE) ? "UPDATE" : "DELETE");
@@ -698,10 +733,7 @@ int TDBODBC::Cardinality(PGLOBAL g)
char qry[96], tbn[64];
ODBConn *ocp = new(g) ODBConn(g, this);
- ocp->SetLoginTimeout((DWORD)Cto);
- ocp->SetQueryTimeout((DWORD)Qto);
-
- if (ocp->Open(Connect, Options) < 1)
+ if (ocp->Open(Connect, &Ops, Options) < 1)
return -1;
// Table name can be encoded in UTF-8
@@ -762,9 +794,9 @@ int TDBODBC::GetProgMax(PGLOBAL g)
/***********************************************************************/
bool TDBODBC::OpenDB(PGLOBAL g)
{
- bool rc = false;
+ bool rc = true;
- if (g->Trace)
+ if (trace)
htrc("ODBC OpenDB: tdbp=%p tdb=R%d use=%dmode=%d\n",
this, Tdb_No, Use, Mode);
@@ -788,10 +820,12 @@ bool TDBODBC::OpenDB(PGLOBAL g)
return true;
} // endif Rewind
- } // endif Memory
+ } else
+ Rbuf = Qrp->Nblin;
CurNum = 0;
Fpos = 0;
+ Curpos = 1;
return false;
} // endif use
@@ -802,14 +836,12 @@ bool TDBODBC::OpenDB(PGLOBAL g)
/* and if so to allocate just a new result set. But this only for */
/* drivers allowing concurency in getting results ??? */
/*********************************************************************/
- if (!Ocp) {
+ if (!Ocp)
Ocp = new(g) ODBConn(g, this);
- Ocp->SetLoginTimeout((DWORD)Cto);
- Ocp->SetQueryTimeout((DWORD)Qto);
- } else if (Ocp->IsOpen())
+ else if (Ocp->IsOpen())
Ocp->Close();
- if (Ocp->Open(Connect, Options) < 1)
+ if (Ocp->Open(Connect, &Ops, Options) < 1)
return true;
else if (Quoted)
Quote = Ocp->GetQuoteChar();
@@ -820,6 +852,37 @@ bool TDBODBC::OpenDB(PGLOBAL g)
/* Make the command and allocate whatever is used for getting results. */
/*********************************************************************/
if (Mode == MODE_READ || Mode == MODE_READX) {
+ if (Memory > 1 && !Srcdef) {
+ char *Sql;
+ int n;
+
+ if ((Sql = MakeSQL(g, true))) {
+ // Allocate a Count(*) column
+ Cnp = new(g) ODBCCOL;
+ Cnp->InitValue(g);
+
+ if ((n = Ocp->GetResultSize(Sql, Cnp)) < 0) {
+ strcpy(g->Message, "Cannot get result size");
+ return true;
+ } // endif n
+
+ Ocp->m_Rows = n;
+
+ if ((Qrp = Ocp->AllocateResult(g)))
+ Memory = 2; // Must be filled
+ else {
+ strcpy(g->Message, "Memory allocation failed");
+ return true;
+ } // endif n
+
+ Ocp->m_Rows = 0;
+ } else {
+ strcpy(g->Message, "MakeSQL failed");
+ return true;
+ } // endif Sql
+
+ } // endif Memory
+
if ((Query = MakeSQL(g, false))) {
for (PODBCCOL colp = (PODBCCOL)Columns; colp;
colp = (PODBCCOL)colp->GetNext())
@@ -839,12 +902,12 @@ bool TDBODBC::OpenDB(PGLOBAL g)
} // endif Query
- } else if (Mode == MODE_UPDATE || Mode == MODE_DELETE)
- Query = MakeCommand(g);
- else
+ } else if (Mode == MODE_UPDATE || Mode == MODE_DELETE) {
+ rc = false; // wait for CheckCond before calling MakeCommand(g);
+ } else
sprintf(g->Message, "Invalid mode %d", Mode);
- if (!Query || rc) {
+ if (rc) {
Ocp->Close();
return true;
} // endif rc
@@ -861,10 +924,41 @@ bool TDBODBC::OpenDB(PGLOBAL g)
/***********************************************************************/
int TDBODBC::GetRecpos(void)
{
- return Fpos; // To be really implemented
+ return Fpos;
} // end of GetRecpos
/***********************************************************************/
+/* SetRecpos: set the position of next read record. */
+/***********************************************************************/
+bool TDBODBC::SetRecpos(PGLOBAL g, int recpos)
+ {
+ if (Ocp->m_Full) {
+ Fpos = 0;
+ CurNum = recpos - 1;
+ } else if (Memory == 3) {
+ Fpos = recpos;
+ CurNum = -1;
+ } else if (Scrollable) {
+ // Is new position in the current row set?
+ if (recpos >= Curpos && recpos < Curpos + Rbuf) {
+ CurNum = recpos - Curpos;
+ Fpos = 0;
+ } else {
+ Fpos = recpos;
+ CurNum = 0;
+ } // endif recpos
+
+ } else {
+ strcpy(g->Message, "This action requires a scrollable cursor");
+ return true;
+ } // endif's
+
+ // Indicate the table position was externally set
+ Placed = true;
+ return false;
+ } // end of SetRecpos
+
+/***********************************************************************/
/* VRDNDOS: Data Base read routine for odbc access method. */
/***********************************************************************/
int TDBODBC::ReadDB(PGLOBAL g)
@@ -876,6 +970,9 @@ int TDBODBC::ReadDB(PGLOBAL g)
GetTdb_No(), Mode, To_Key_Col, To_Link, To_Kindex);
if (Mode == MODE_UPDATE || Mode == MODE_DELETE) {
+ if (!Query && !(Query = MakeCommand(g)))
+ return RC_FX;
+
// Send the UPDATE/DELETE command to the remote table
if (!Ocp->ExecSQLcommand(Query)) {
sprintf(g->Message, "%s: %d affected rows", TableName, AftRows);
@@ -900,22 +997,32 @@ int TDBODBC::ReadDB(PGLOBAL g)
/* Now start the reading process. */
/* Here is the place to fetch the line(s). */
/*********************************************************************/
- if (Memory != 3) {
- if (++CurNum >= Rbuf) {
- Rbuf = Ocp->Fetch();
- CurNum = 0;
- } // endif CurNum
+ if (Placed) {
+ if (Fpos && CurNum >= 0)
+ Rbuf = Ocp->Fetch((Curpos = Fpos));
rc = (Rbuf > 0) ? RC_OK : (Rbuf == 0) ? RC_EF : RC_FX;
- } else // Getting result from memory
- rc = (Fpos < Qrp->Nblin) ? RC_OK : RC_EF;
+ Placed = false;
+ } else {
+ if (Memory != 3) {
+ if (++CurNum >= Rbuf) {
+ Rbuf = Ocp->Fetch();
+ Curpos = Fpos + 1;
+ CurNum = 0;
+ } // endif CurNum
- if (rc == RC_OK) {
- if (Memory == 2)
- Qrp->Nblin++;
+ rc = (Rbuf > 0) ? RC_OK : (Rbuf == 0) ? RC_EF : RC_FX;
+ } else // Getting result from memory
+ rc = (Fpos < Qrp->Nblin) ? RC_OK : RC_EF;
- Fpos++; // Used for memory
- } // endif rc
+ if (rc == RC_OK) {
+ if (Memory == 2)
+ Qrp->Nblin++;
+
+ Fpos++; // Used for memory and pos
+ } // endif rc
+
+ } // endif Placed
if (trace > 1)
htrc(" Read: Rbuf=%d rc=%d\n", Rbuf, rc);
@@ -945,6 +1052,9 @@ int TDBODBC::WriteDB(PGLOBAL g)
int TDBODBC::DeleteDB(PGLOBAL g, int irc)
{
if (irc == RC_FX) {
+ if (!Query && !(Query = MakeCommand(g)))
+ return RC_FX;
+
// Send the DELETE (all) command to the remote table
if (!Ocp->ExecSQLcommand(Query)) {
sprintf(g->Message, "%s: %d affected rows", TableName, AftRows);
@@ -1158,12 +1268,12 @@ void ODBCCOL::ReadColumn(PGLOBAL g)
} // endif Buf_Type
- if (g->Trace) {
+ if (trace) {
char buf[64];
htrc("ODBC Column %s: rows=%d buf=%p type=%d value=%s\n",
Name, tdbp->Rows, Bufp, Buf_Type, Value->GetCharString(buf));
- } // endif Trace
+ } // endif trace
put:
if (tdbp->Memory != 2)
@@ -1397,7 +1507,7 @@ bool TDBXDBC::OpenDB(PGLOBAL g)
{
bool rc = false;
- if (g->Trace)
+ if (trace)
htrc("ODBC OpenDB: tdbp=%p tdb=R%d use=%dmode=%d\n",
this, Tdb_No, Use, Mode);
@@ -1415,12 +1525,10 @@ bool TDBXDBC::OpenDB(PGLOBAL g)
/*********************************************************************/
if (!Ocp) {
Ocp = new(g) ODBConn(g, this);
- Ocp->SetLoginTimeout((DWORD)Cto);
- Ocp->SetQueryTimeout((DWORD)Qto);
} else if (Ocp->IsOpen())
Ocp->Close();
- if (Ocp->Open(Connect, Options) < 1)
+ if (Ocp->Open(Connect, &Ops, Options) < 1)
return true;
Use = USE_OPEN; // Do it now in case we are recursively called
@@ -1554,8 +1662,11 @@ TDBOTB::TDBOTB(PODEF tdp) : TDBDRV(tdp)
Dsn = tdp->GetConnect();
Schema = tdp->GetTabschema();
Tab = tdp->GetTabname();
- Cto = tdp->Cto;
- Qto = tdp->Qto;
+ Ops.User = tdp->Username;
+ Ops.Pwd = tdp->Password;
+ Ops.Cto = tdp->Cto;
+ Ops.Qto = tdp->Qto;
+ Ops.UseCnc = tdp->UseCnc;
} // end of TDBOTB constructor
/***********************************************************************/
@@ -1563,7 +1674,7 @@ TDBOTB::TDBOTB(PODEF tdp) : TDBDRV(tdp)
/***********************************************************************/
PQRYRES TDBOTB::GetResult(PGLOBAL g)
{
- return ODBCTables(g, Dsn, Schema, Tab, Maxres, Cto, Qto, false);
+ return ODBCTables(g, Dsn, Schema, Tab, Maxres, false, &Ops);
} // end of GetResult
/* ---------------------------TDBOCL class --------------------------- */
@@ -1573,7 +1684,7 @@ PQRYRES TDBOTB::GetResult(PGLOBAL g)
/***********************************************************************/
PQRYRES TDBOCL::GetResult(PGLOBAL g)
{
- return ODBCColumns(g, Dsn, Schema, Tab, NULL, Maxres, Cto, Qto, false);
+ return ODBCColumns(g, Dsn, Schema, Tab, NULL, Maxres, false, &Ops);
} // end of GetResult
/* ------------------------ End of Tabodbc --------------------------- */
diff --git a/storage/connect/tabodbc.h b/storage/connect/tabodbc.h
index d8644c8b6de..b8c9d85aae5 100644
--- a/storage/connect/tabodbc.h
+++ b/storage/connect/tabodbc.h
@@ -50,6 +50,8 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
PSZ Connect; /* ODBC connection string */
PSZ Tabname; /* External table name */
PSZ Tabschema; /* External table schema */
+ PSZ Username; /* User connect name */
+ PSZ Password; /* Password connect info */
PSZ Tabcat; /* External table catalog */
PSZ Srcdef; /* The source table SQL definition */
PSZ Qchar; /* Identifier quoting character */
@@ -62,9 +64,10 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
int Quoted; /* Identifier quoting level */
int Maxerr; /* Maxerr for an Exec table */
int Maxres; /* Maxres for a catalog table */
+ int Memory; /* Put result set in memory */
bool Scrollable; /* Use scrollable cursor */
- bool Memory; /* Put result set in memory */
bool Xsrc; /* Execution type */
+ bool UseCnc; /* Use SQLConnect (!SQLDriverConnect) */
}; // end of ODBCDEF
#if !defined(NODBC)
@@ -90,6 +93,7 @@ class TDBODBC : public TDBASE {
// Methods
virtual PTDB CopyOne(PTABS t);
virtual int GetRecpos(void);
+ virtual bool SetRecpos(PGLOBAL g, int recpos);
virtual PSZ GetFile(PGLOBAL g);
virtual void SetFile(PGLOBAL g, PSZ fn);
virtual void ResetSize(void);
@@ -124,9 +128,12 @@ class TDBODBC : public TDBASE {
// Members
ODBConn *Ocp; // Points to an ODBC connection class
ODBCCOL *Cnp; // Points to count(*) column
+ ODBCPARM Ops; // Additional parameters
char *Connect; // Points to connection string
char *TableName; // Points to ODBC table name
char *Schema; // Points to ODBC table Schema
+ char *User; // User connect info
+ char *Pwd; // Password connect info
char *Catalog; // Points to ODBC table Catalog
char *Srcdef; // The source table SQL definition
char *Query; // Points to SQL statement
@@ -142,6 +149,7 @@ class TDBODBC : public TDBASE {
int Qto; // Query timeout
int Quoted; // The identifier quoting level
int Fpos; // Position of last read record
+ int Curpos; // Cursor position of last fetch
int AftRows; // The number of affected rows
int Rows; // Rowset size
int Catver; // Catalog ODBC version
@@ -151,6 +159,8 @@ class TDBODBC : public TDBASE {
int Nparm; // The number of statement parameters
int Memory; // 0: No 1: Alloc 2: Put 3: Get
bool Scrollable; // Use scrollable cursor
+ bool Placed; // True for position reading
+ bool UseCnc; // Use SQLConnect (!SQLDriverConnect)
PQRYRES Qrp; // Points to storage result
}; // end of class TDBODBC
@@ -316,8 +326,7 @@ class TDBOTB : public TDBDRV {
char *Dsn; // Points to connection string
char *Schema; // Points to schema name or NULL
char *Tab; // Points to ODBC table name or pattern
- int Cto; // Connect timeout
- int Qto; // Query timeout
+ ODBCPARM Ops; // Additional parameters
}; // end of class TDBOTB
/***********************************************************************/
diff --git a/storage/connect/tabpivot.cpp b/storage/connect/tabpivot.cpp
index 94e9d7187f0..2b0c43dac9f 100644
--- a/storage/connect/tabpivot.cpp
+++ b/storage/connect/tabpivot.cpp
@@ -558,7 +558,7 @@ bool TDBPIVOT::MakePivotColumns(PGLOBAL g)
// Check and initialize the subtable columns
for (PCOL cp = Columns; cp; cp = cp->GetNext())
if (cp->GetAmType() == TYPE_AM_SRC) {
- if (((PSRCCOL)cp)->Init(g))
+ if (((PSRCCOL)cp)->Init(g, NULL))
return TRUE;
} else if (cp->GetAmType() == TYPE_AM_FNC)
@@ -874,9 +874,9 @@ SRCCOL::SRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int n)
/***********************************************************************/
/* Initialize the column as pointing to the source column. */
/***********************************************************************/
-bool SRCCOL::Init(PGLOBAL g)
+bool SRCCOL::Init(PGLOBAL g, PTDBASE tp)
{
- if (PRXCOL::Init(g))
+ if (PRXCOL::Init(g, tp))
return true;
AddStatus(BUF_READ); // All is done here
diff --git a/storage/connect/tabpivot.h b/storage/connect/tabpivot.h
index 25d139e895f..c397af05234 100644
--- a/storage/connect/tabpivot.h
+++ b/storage/connect/tabpivot.h
@@ -180,9 +180,10 @@ class SRCCOL : public PRXCOL {
virtual int GetAmType(void) {return TYPE_AM_SRC;}
// Methods
+ using PRXCOL::Init;
virtual void Reset(void) {}
void SetColumn(void);
- bool Init(PGLOBAL g);
+ virtual bool Init(PGLOBAL g, PTDBASE tp);
bool CompareLast(void);
protected:
diff --git a/storage/connect/tabtbl.cpp b/storage/connect/tabtbl.cpp
index 22ec3849b6f..a33d6caa83a 100644
--- a/storage/connect/tabtbl.cpp
+++ b/storage/connect/tabtbl.cpp
@@ -266,7 +266,7 @@ bool TDBTBL::InitTableList(PGLOBAL g)
// Real initialization will be done later.
for (colp = Columns; colp; colp = colp->GetNext())
if (!colp->IsSpecial())
- if (((PPRXCOL)colp)->Init(g) && !Accept)
+ if (((PPRXCOL)colp)->Init(g, NULL) && !Accept)
return TRUE;
if (Tablist)
@@ -352,7 +352,9 @@ bool TDBTBL::TestFil(PGLOBAL g, PCFIL filp, PTABLE tabp)
/***********************************************************************/
int TDBTBL::Cardinality(PGLOBAL g)
{
- if (Cardinal < 0) {
+ if (!g)
+ return 0; // Cannot make the table list
+ else if (Cardinal < 0) {
int tsz;
if (!Tablist && InitTableList(g))
@@ -468,7 +470,7 @@ bool TDBTBL::OpenDB(PGLOBAL g)
for (PCOL cp = Columns; cp; cp = cp->GetNext())
if (cp->GetAmType() == TYPE_AM_TABID)
cp->COLBLK::Reset();
- else if (((PPRXCOL)cp)->Init(g) && !Accept)
+ else if (((PPRXCOL)cp)->Init(g, NULL) && !Accept)
return TRUE;
if (trace)
@@ -523,7 +525,7 @@ int TDBTBL::ReadDB(PGLOBAL g)
if (cp->GetAmType() == TYPE_AM_TABID ||
cp->GetAmType() == TYPE_AM_SRVID)
cp->COLBLK::Reset();
- else if (((PPRXCOL)cp)->Init(g) && !Accept)
+ else if (((PPRXCOL)cp)->Init(g, NULL) && !Accept)
return RC_FX;
if (trace)
@@ -716,7 +718,7 @@ bool TDBTBM::OpenDB(PGLOBAL g)
for (PCOL cp = Columns; cp; cp = cp->GetNext())
if (cp->GetAmType() == TYPE_AM_TABID)
cp->COLBLK::Reset();
- else if (((PPRXCOL)cp)->Init(g) && !Accept)
+ else if (((PPRXCOL)cp)->Init(g, NULL) && !Accept)
return TRUE;
if (trace)
@@ -807,7 +809,7 @@ int TDBTBM::ReadNextRemote(PGLOBAL g)
for (PCOL cp = Columns; cp; cp = cp->GetNext())
if (cp->GetAmType() == TYPE_AM_TABID)
cp->COLBLK::Reset();
- else if (((PPRXCOL)cp)->Init(g) && !Accept)
+ else if (((PPRXCOL)cp)->Init(g, NULL) && !Accept)
return RC_FX;
if (trace)
diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp
index d469594916f..c114497aa69 100644
--- a/storage/connect/tabutil.cpp
+++ b/storage/connect/tabutil.cpp
@@ -1,7 +1,7 @@
/************* Tabutil cpp Declares Source Code File (.CPP) ************/
-/* Name: TABUTIL.CPP Version 1.0 */
+/* Name: TABUTIL.CPP Version 1.1 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2013 */
+/* (C) Copyright to the author Olivier BERTRAND 2013 - 2015 */
/* */
/* Utility function used by the PROXY, XCOL, OCCUR, and TBL tables. */
/***********************************************************************/
@@ -9,7 +9,8 @@
/***********************************************************************/
/* Include relevant section of system dependant header files. */
/***********************************************************************/
-#include "my_global.h"
+#define MYSQL_SERVER 1
+#include <my_global.h>
#include "sql_class.h"
#include "table.h"
#include "field.h"
@@ -54,7 +55,8 @@
#include "tabutil.h"
#include "ha_connect.h"
-extern "C" int zconv;
+//extern "C" int zconv;
+int GetConvSize(void);
/************************************************************************/
/* Used by MYSQL tables to get MySQL parameters from the calling proxy */
@@ -107,6 +109,9 @@ TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db,
} // endif is_view
} else {
+ if (thd->is_error())
+ thd->clear_error(); // Avoid stopping info commands
+
sprintf(g->Message, "Error %d opening share\n", s->error);
free_table_share(s);
return NULL;
@@ -132,6 +137,7 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
char *fld, *colname, *chset, *fmt, v;
int i, n, ncol = sizeof(buftyp) / sizeof(int);
int prec, len, type, scale;
+ int zconv = GetConvSize();
bool mysql;
TABLE_SHARE *s = NULL;
Field* *field;
@@ -669,6 +675,22 @@ PRXCOL::PRXCOL(PRXCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
} // end of PRXCOL copy constructor
/***********************************************************************/
+/* Convert an UTF-8 name to latin characters. */
+/***********************************************************************/
+char *PRXCOL::Decode(PGLOBAL g, const char *cnm)
+ {
+ char *buf= (char*)PlugSubAlloc(g, NULL, strlen(cnm) + 1);
+ uint dummy_errors;
+ uint32 len= copy_and_convert(buf, strlen(cnm) + 1,
+ &my_charset_latin1,
+ cnm, strlen(cnm),
+ &my_charset_utf8_general_ci,
+ &dummy_errors);
+ buf[len]= '\0';
+ return buf;
+ } // end of Decode
+
+/***********************************************************************/
/* PRXCOL initialization routine. */
/* Look for the matching column in the object table. */
/***********************************************************************/
@@ -683,6 +705,9 @@ bool PRXCOL::Init(PGLOBAL g, PTDBASE tp)
if (Colp) {
MODE mode = To_Tdb->GetMode();
+ // Needed for MYSQL subtables
+ ((XCOLBLK*)Colp)->Name = Decode(g, Colp->GetName());
+
// May not have been done elsewhere
Colp->InitValue(g);
To_Val = Colp->GetValue();
diff --git a/storage/connect/tabutil.h b/storage/connect/tabutil.h
index 606e532d526..c5935d72184 100644
--- a/storage/connect/tabutil.h
+++ b/storage/connect/tabutil.h
@@ -108,15 +108,18 @@ class DllExport PRXCOL : public COLBLK {
virtual int GetAmType(void) {return TYPE_AM_PRX;}
// Methods
+ using COLBLK::Init;
virtual void Reset(void);
virtual bool IsSpecial(void) {return Pseudo;}
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
{return false;}
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
- virtual bool Init(PGLOBAL g, PTDBASE tp = NULL);
+ virtual bool Init(PGLOBAL g, PTDBASE tp);
protected:
+ char *Decode(PGLOBAL g, const char *cnm);
+
// Default constructor not to be used
PRXCOL(void) {}
@@ -144,4 +147,8 @@ class TDBTBC : public TDBCAT {
PSZ Tab; // Table name
}; // end of class TDBMCL
+class XCOLBLK : public COLBLK {
+ friend class PRXCOL;
+}; // end of class XCOLBLK
+
#endif // TABUTIL
diff --git a/storage/connect/tabxcl.cpp b/storage/connect/tabxcl.cpp
index 57f0e1e03b9..0de01927c5a 100644
--- a/storage/connect/tabxcl.cpp
+++ b/storage/connect/tabxcl.cpp
@@ -183,7 +183,7 @@ bool TDBXCL::OpenDB(PGLOBAL g)
/*********************************************************************/
for (PCOL cp = Columns; cp; cp = cp->GetNext())
if (!cp->IsSpecial())
- if (((PPRXCOL)cp)->Init(g))
+ if (((PPRXCOL)cp)->Init(g, NULL))
return TRUE;
/*********************************************************************/
diff --git a/storage/connect/tabxcl.h b/storage/connect/tabxcl.h
index 7e11600c090..ed15a67b629 100644
--- a/storage/connect/tabxcl.h
+++ b/storage/connect/tabxcl.h
@@ -88,6 +88,7 @@ class XCLCOL : public PRXCOL {
XCLCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i);
// Methods
+ using PRXCOL::Init;
virtual void Reset(void) {} // Evaluated only by TDBXCL
virtual void ReadColumn(PGLOBAL g);
virtual bool Init(PGLOBAL g, PTDBASE tp = NULL);
diff --git a/storage/connect/valblk.h b/storage/connect/valblk.h
index 654db0b57b7..5a98257f98f 100644
--- a/storage/connect/valblk.h
+++ b/storage/connect/valblk.h
@@ -163,6 +163,7 @@ class TYPBLK : public VALBLK {
virtual void Reset(int n) {Typp[n] = 0;}
// Methods
+ using VALBLK::SetValue;
virtual void SetValue(PSZ sp, int n);
virtual void SetValue(char *sp, uint len, int n);
virtual void SetValue(short sval, int n)
@@ -233,6 +234,7 @@ class CHRBLK : public VALBLK {
virtual bool IsCi(void) {return Ci;}
// Methods
+ using VALBLK::SetValue;
virtual void SetValue(PSZ sp, int n);
virtual void SetValue(char *sp, uint len, int n);
virtual void SetValue(PVAL valp, int n);
@@ -286,6 +288,7 @@ class STRBLK : public VALBLK {
virtual void Reset(int n) {Strp[n] = NULL;}
// Methods
+ using VALBLK::SetValue;
virtual void SetValue(PSZ sp, int n);
virtual void SetValue(char *sp, uint len, int n);
virtual void SetValue(PVAL valp, int n);
@@ -322,6 +325,7 @@ class DATBLK : public TYPBLK<int> {
virtual char *GetCharString(char *p, int n);
// Methods
+ using TYPBLK<int>::SetValue;
virtual void SetValue(PSZ sp, int n);
protected:
@@ -345,6 +349,8 @@ class PTRBLK : public STRBLK {
// Implementation
// Methods
+ using STRBLK::SetValue;
+ using STRBLK::CompVal;
virtual void SetValue(PSZ p, int n) {Strp[n] = p;}
virtual int CompVal(int i1, int i2);
diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp
index 1cc40473433..e012e12d00b 100644
--- a/storage/connect/value.cpp
+++ b/storage/connect/value.cpp
@@ -436,6 +436,9 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
bool un = (uns < 0) ? false : (uns > 0) ? true : valp->IsUnsigned();
PVAL vp;
+ if (!valp)
+ return NULL;
+
if (newtype == TYPE_VOID) // Means allocate a value of the same type
newtype = valp->GetType();
@@ -443,8 +446,8 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
case TYPE_STRING:
p = (PSZ)PlugSubAlloc(g, NULL, 1 + valp->GetValLen());
- if ((sp = valp->GetCharString(p)) != p)
- strcpy (p, sp);
+ if ((sp = valp->GetCharString(p)) != p && sp)
+ strcpy(p, sp);
vp = new(g) TYPVAL<PSZ>(g, p, valp->GetValLen(), valp->GetValPrec());
break;
@@ -1216,12 +1219,12 @@ TYPVAL<PSZ>::TYPVAL(PSZ s) : VALUE(TYPE_STRING)
TYPVAL<PSZ>::TYPVAL(PGLOBAL g, PSZ s, int n, int c)
: VALUE(TYPE_STRING)
{
- Len = (g) ? n : strlen(s);
+ Len = (g) ? n : (s) ? strlen(s) : 0;
if (!s) {
if (g) {
if ((Strp = (char *)PlgDBSubAlloc(g, NULL, Len + 1)))
- Strp[Len] = '\0';
+ memset(Strp, 0, Len + 1);
else
Len = 0;
diff --git a/storage/connect/xindex.h b/storage/connect/xindex.h
index c702baeec83..6e40e9b160e 100644
--- a/storage/connect/xindex.h
+++ b/storage/connect/xindex.h
@@ -391,6 +391,7 @@ class DllExport XHUGE : public XLOAD {
XHUGE(void) : XLOAD() {}
// Methods
+ using XLOAD::Close;
virtual bool Open(PGLOBAL g, char *filename, int id, MODE mode);
virtual bool Seek(PGLOBAL g, int low, int high, int origin);
virtual bool Read(PGLOBAL g, void *buf, int n, int size);
diff --git a/storage/connect/xobject.cpp b/storage/connect/xobject.cpp
index 4ddd4f5b30f..817acb561fe 100644
--- a/storage/connect/xobject.cpp
+++ b/storage/connect/xobject.cpp
@@ -347,6 +347,31 @@ bool STRING::Append(char c)
} // end of Append
/***********************************************************************/
+/* Append a quoted PSZ to a STRING. */
+/***********************************************************************/
+bool STRING::Append_quoted(PSZ s)
+{
+ bool b = Append('\'');
+
+ if (s) for (char *p = s; !b && *p; p++)
+ switch (*p) {
+ case '\'':
+ case '\\':
+ case '\t':
+ case '\n':
+ case '\r':
+ case '\b':
+ case '\f': b |= Append('\\');
+ // passthru
+ default:
+ b |= Append(*p);
+ break;
+ } // endswitch *p
+
+ return (b |= Append('\''));
+} // end of Append_quoted
+
+/***********************************************************************/
/* Resize to given length but only when last suballocated. */
/* New size should be greater than string length. */
/***********************************************************************/
diff --git a/storage/connect/xobject.h b/storage/connect/xobject.h
index bb7b0150ed8..3660ee86918 100644
--- a/storage/connect/xobject.h
+++ b/storage/connect/xobject.h
@@ -138,6 +138,7 @@ class DllExport STRING : public BLOCK {
bool Append(STRING &str);
bool Append(char c);
bool Resize(uint n);
+ bool Append_quoted(PSZ s);
inline void Trim(void) {(void)Resize(Length + 1);}
inline void Chop(void) {if (Length) Strp[--Length] = 0;}
inline void RepLast(char c) {if (Length) Strp[Length-1] = c;}
diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc
index 8670048e9a2..fc620245770 100644
--- a/storage/federated/ha_federated.cc
+++ b/storage/federated/ha_federated.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2004, 2013, Oracle and/or its affiliates.
+/* Copyright (c) 2004, 2014, Oracle and/or its affiliates.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1665,9 +1665,9 @@ int ha_federated::close(void)
DBUG_ENTER("ha_federated::close");
free_result();
-
+
delete_dynamic(&results);
-
+
/* Disconnect from mysql */
mysql_close(mysql);
mysql= NULL;
diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc
index 92539ce1524..fa613ef03ef 100644
--- a/storage/innobase/btr/btr0btr.cc
+++ b/storage/innobase/btr/btr0btr.cc
@@ -3184,6 +3184,12 @@ func_start:
/* 2. Allocate a new page to the index */
new_block = btr_page_alloc(cursor->index, hint_page_no, direction,
btr_page_get_level(page, mtr), mtr, mtr);
+
+ /* Play safe, if new page is not allocated */
+ if (!new_block) {
+ return(rec);
+ }
+
new_page = buf_block_get_frame(new_block);
new_page_zip = buf_block_get_page_zip(new_block);
btr_page_create(new_block, new_page_zip, cursor->index,
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index 3992eda6e1c..1a4eb347cd2 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -2372,15 +2372,15 @@ btr_cur_pess_upd_restore_supremum(
Check if the total length of the modified blob for the row is within 10%
of the total redo log size. This constraint on the blob length is to
avoid overwriting the redo logs beyond the last checkpoint lsn.
-@return DB_SUCCESS or DB_TOO_BIG_RECORD. */
+@return DB_SUCCESS or DB_TOO_BIG_FOR_REDO. */
static
dberr_t
btr_check_blob_limit(const big_rec_t* big_rec_vec)
{
const ib_uint64_t redo_size = srv_n_log_files * srv_log_file_size
* UNIV_PAGE_SIZE;
- const ulint redo_10p = redo_size / 10;
- ulint total_blob_len = 0;
+ const ib_uint64_t redo_10p = redo_size / 10;
+ ib_uint64_t total_blob_len = 0;
dberr_t err = DB_SUCCESS;
/* Calculate the total number of bytes for blob data */
@@ -2390,11 +2390,11 @@ btr_check_blob_limit(const big_rec_t* big_rec_vec)
if (total_blob_len > redo_10p) {
ib_logf(IB_LOG_LEVEL_ERROR, "The total blob data"
- " length (" ULINTPF ") is greater than"
+ " length (" UINT64PF ") is greater than"
" 10%% of the total redo log size (" UINT64PF
"). Please increase total redo log size.",
total_blob_len, redo_size);
- err = DB_TOO_BIG_RECORD;
+ err = DB_TOO_BIG_FOR_REDO;
}
return(err);
@@ -4457,7 +4457,7 @@ Stores the fields in big_rec_vec to the tablespace and puts pointers to
them in rec. The extern flags in rec will have to be set beforehand.
The fields are stored on pages allocated from leaf node
file segment of the index tree.
-@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
+@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE or DB_TOO_BIG_FOR_REDO */
UNIV_INTERN
dberr_t
btr_store_big_rec_extern_fields(
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index 31a493855ad..c0308868a67 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -2437,10 +2437,10 @@ too_big:
dict_mem_index_free(new_index);
dict_mem_index_free(index);
return(DB_TOO_BIG_RECORD);
- } else {
-
+ } else if (current_thd != NULL) {
+ /* Avoid the warning to be printed
+ during recovery. */
ib_warn_row_too_big(table);
-
}
}
diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc
index 58781fce1d4..f0ea15d9513 100644
--- a/storage/innobase/dict/dict0mem.cc
+++ b/storage/innobase/dict/dict0mem.cc
@@ -319,6 +319,9 @@ dict_mem_table_col_rename_low(
ut_ad(from_len <= NAME_LEN);
ut_ad(to_len <= NAME_LEN);
+ char from[NAME_LEN];
+ strncpy(from, s, NAME_LEN);
+
if (from_len == to_len) {
/* The easy case: simply replace the column name in
table->col_names. */
@@ -386,14 +389,53 @@ dict_mem_table_col_rename_low(
foreign = *it;
- for (unsigned f = 0; f < foreign->n_fields; f++) {
- /* These can point straight to
- table->col_names, because the foreign key
- constraints will be freed at the same time
- when the table object is freed. */
- foreign->foreign_col_names[f]
- = dict_index_get_nth_field(
- foreign->foreign_index, f)->name;
+ if (foreign->foreign_index == NULL) {
+ /* We may go here when we set foreign_key_checks to 0,
+ and then try to rename a column and modify the
+ corresponding foreign key constraint. The index
+ would have been dropped, we have to find an equivalent
+ one */
+ for (unsigned f = 0; f < foreign->n_fields; f++) {
+ if (strcmp(foreign->foreign_col_names[f], from)
+ == 0) {
+
+ char** rc = const_cast<char**>(
+ foreign->foreign_col_names
+ + f);
+
+ if (to_len <= strlen(*rc)) {
+ memcpy(*rc, to, to_len + 1);
+ } else {
+ *rc = static_cast<char*>(
+ mem_heap_dup(
+ foreign->heap,
+ to,
+ to_len + 1));
+ }
+ }
+ }
+
+ dict_index_t* new_index = dict_foreign_find_index(
+ foreign->foreign_table, NULL,
+ foreign->foreign_col_names,
+ foreign->n_fields, NULL, true, false);
+ /* There must be an equivalent index in this case. */
+ ut_ad(new_index != NULL);
+
+ foreign->foreign_index = new_index;
+
+ } else {
+
+ for (unsigned f = 0; f < foreign->n_fields; f++) {
+ /* These can point straight to
+ table->col_names, because the foreign key
+ constraints will be freed at the same time
+ when the table object is freed. */
+ foreign->foreign_col_names[f]
+ = dict_index_get_nth_field(
+ foreign->foreign_index,
+ f)->name;
+ }
}
}
@@ -403,6 +445,8 @@ dict_mem_table_col_rename_low(
foreign = *it;
+ ut_ad(foreign->referenced_index != NULL);
+
for (unsigned f = 0; f < foreign->n_fields; f++) {
/* foreign->referenced_col_names[] need to be
copies, because the constraint may become
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index a5327d9f2aa..750cb50a105 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -5176,6 +5176,9 @@ retry:
success = TRUE;
}
+ DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
+ success = FALSE; errno = 28; os_has_said_disk_full = TRUE;);
+
mutex_enter(&fil_system->mutex);
if (success) {
@@ -5219,6 +5222,11 @@ retry:
offset, page_size * n_pages,
node, NULL, 0, FALSE, 0, 0, 0, 0, false);
#endif /* UNIV_HOTBACKUP */
+
+
+ DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
+ success = FALSE; errno = 28; os_has_said_disk_full = TRUE;);
+
if (success) {
os_has_said_disk_full = FALSE;
} else {
diff --git a/storage/innobase/fts/fts0ast.cc b/storage/innobase/fts/fts0ast.cc
index dd48ffee14d..030b972440f 100644
--- a/storage/innobase/fts/fts0ast.cc
+++ b/storage/innobase/fts/fts0ast.cc
@@ -694,3 +694,51 @@ fts_ast_string_print(
printf("\n");
}
+
+#ifdef UNIV_DEBUG
+const char*
+fts_ast_oper_name_get(fts_ast_oper_t oper)
+{
+ switch(oper) {
+ case FTS_NONE:
+ return("FTS_NONE");
+ case FTS_IGNORE:
+ return("FTS_IGNORE");
+ case FTS_EXIST:
+ return("FTS_EXIST");
+ case FTS_NEGATE:
+ return("FTS_NEGATE");
+ case FTS_INCR_RATING:
+ return("FTS_INCR_RATING");
+ case FTS_DECR_RATING:
+ return("FTS_DECR_RATING");
+ case FTS_DISTANCE:
+ return("FTS_DISTANCE");
+ case FTS_IGNORE_SKIP:
+ return("FTS_IGNORE_SKIP");
+ case FTS_EXIST_SKIP:
+ return("FTS_EXIST_SKIP");
+ }
+ ut_ad(0);
+}
+
+const char*
+fts_ast_node_type_get(fts_ast_type_t type)
+{
+ switch (type) {
+ case FTS_AST_OPER:
+ return("FTS_AST_OPER");
+ case FTS_AST_NUMB:
+ return("FTS_AST_NUMB");
+ case FTS_AST_TERM:
+ return("FTS_AST_TERM");
+ case FTS_AST_TEXT:
+ return("FTS_AST_TEXT");
+ case FTS_AST_LIST:
+ return("FTS_AST_LIST");
+ case FTS_AST_SUBEXP_LIST:
+ return("FTS_AST_SUBEXP_LIST");
+ }
+ ut_ad(0);
+}
+#endif /* UNIV_DEBUG */
diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc
index 2e2bd061d07..5891b53a6e2 100644
--- a/storage/innobase/fts/fts0opt.cc
+++ b/storage/innobase/fts/fts0opt.cc
@@ -2577,8 +2577,6 @@ fts_optimize_add_table(
return;
}
- ut_ad(table->cached && table->fts != NULL);
-
/* Make sure table with FTS index cannot be evicted */
if (table->can_be_evicted) {
dict_table_move_from_lru_to_non_lru(table);
diff --git a/storage/innobase/fts/fts0que.cc b/storage/innobase/fts/fts0que.cc
index 8f4813e4b3f..9f03cd6a451 100644
--- a/storage/innobase/fts/fts0que.cc
+++ b/storage/innobase/fts/fts0que.cc
@@ -1534,7 +1534,8 @@ fts_merge_doc_ids(
{
const ib_rbt_node_t* node;
- ut_a(!rbt_empty(doc_ids));
+ DBUG_ENTER("fts_merge_doc_ids");
+
ut_a(!query->intersection);
/* To process FTS_EXIST operation (intersection), we need
@@ -1559,7 +1560,7 @@ fts_merge_doc_ids(
query, ranking->doc_id, ranking->rank);
if (query->error != DB_SUCCESS) {
- return(query->error);
+ DBUG_RETURN(query->error);
}
/* Merge words. Don't need to take operator into account. */
@@ -1578,7 +1579,7 @@ fts_merge_doc_ids(
query->intersection = NULL;
}
- return(DB_SUCCESS);
+ DBUG_RETURN(DB_SUCCESS);
}
/*****************************************************************//**
@@ -2839,11 +2840,11 @@ fts_query_visitor(
fts_query_t* query = static_cast<fts_query_t*>(arg);
ut_a(node);
+ DBUG_ENTER("fts_query_visitor");
+ DBUG_PRINT("fts", ("nodetype: %s", fts_ast_node_type_get(node->type)));
token.f_n_char = 0;
-
query->oper = oper;
-
query->cur_node = node;
switch (node->type) {
@@ -2905,7 +2906,7 @@ fts_query_visitor(
query->multi_exist = true;
}
- return(query->error);
+ DBUG_RETURN(query->error);
}
/*****************************************************************//**
@@ -2929,6 +2930,8 @@ fts_ast_visit_sub_exp(
bool will_be_ignored = false;
bool multi_exist;
+ DBUG_ENTER("fts_ast_visit_sub_exp");
+
ut_a(node->type == FTS_AST_SUBEXP_LIST);
cur_oper = query->oper;
@@ -2957,14 +2960,14 @@ fts_ast_visit_sub_exp(
/* Merge the sub-expression result with the parent result set. */
subexpr_doc_ids = query->doc_ids;
query->doc_ids = parent_doc_ids;
- if (error == DB_SUCCESS && !rbt_empty(subexpr_doc_ids)) {
+ if (error == DB_SUCCESS) {
error = fts_merge_doc_ids(query, subexpr_doc_ids);
}
/* Free current result set. Result already merged into parent. */
fts_query_free_doc_ids(query, subexpr_doc_ids);
- return(error);
+ DBUG_RETURN(error);
}
#if 0
@@ -3440,8 +3443,10 @@ fts_retrieve_ranking(
ib_rbt_bound_t parent;
fts_ranking_t new_ranking;
+ DBUG_ENTER("fts_retrieve_ranking");
+
if (!result || !result->rankings_by_id) {
- return(0);
+ DBUG_RETURN(0);
}
new_ranking.doc_id = doc_id;
@@ -3452,10 +3457,10 @@ fts_retrieve_ranking(
ranking = rbt_value(fts_ranking_t, parent.last);
- return(ranking->rank);
+ DBUG_RETURN(ranking->rank);
}
- return(0);
+ DBUG_RETURN(0);
}
/*****************************************************************//**
@@ -3472,6 +3477,8 @@ fts_query_prepare_result(
const ib_rbt_node_t* node;
bool result_is_null = false;
+ DBUG_ENTER("fts_query_prepare_result");
+
if (result == NULL) {
result = static_cast<fts_result_t*>(ut_malloc(sizeof(*result)));
@@ -3520,7 +3527,7 @@ fts_query_prepare_result(
if (query->total_size > fts_result_cache_limit) {
query->error = DB_FTS_EXCEED_RESULT_CACHE_LIMIT;
fts_query_free_result(result);
- return(NULL);
+ DBUG_RETURN(NULL);
}
}
@@ -3543,7 +3550,7 @@ fts_query_prepare_result(
ranking->rank * word_freq->idf * word_freq->idf);
}
- return(result);
+ DBUG_RETURN(result);
}
ut_a(rbt_size(query->doc_ids) > 0);
@@ -3570,7 +3577,7 @@ fts_query_prepare_result(
if (query->total_size > fts_result_cache_limit) {
query->error = DB_FTS_EXCEED_RESULT_CACHE_LIMIT;
fts_query_free_result(result);
- return(NULL);
+ DBUG_RETURN(NULL);
}
}
}
@@ -3582,7 +3589,7 @@ fts_query_prepare_result(
query->doc_ids = NULL;
}
- return(result);
+ DBUG_RETURN(result);
}
/*****************************************************************//**
@@ -3594,6 +3601,8 @@ fts_query_get_result(
fts_query_t* query, /*!< in: query instance */
fts_result_t* result) /*!< in: result */
{
+ DBUG_ENTER("fts_query_get_result");
+
if (rbt_size(query->doc_ids) > 0 || query->flags == FTS_OPT_RANKING) {
/* Copy the doc ids to the result. */
result = fts_query_prepare_result(query, result);
@@ -3603,7 +3612,7 @@ fts_query_get_result(
memset(result, 0, sizeof(*result));
}
- return(result);
+ DBUG_RETURN(result);
}
/*****************************************************************//**
@@ -3681,6 +3690,7 @@ fts_query_parse(
int error;
fts_ast_state_t state;
bool mode = query->boolean_mode;
+ DBUG_ENTER("fts_query_parse");
memset(&state, 0x0, sizeof(state));
@@ -3699,7 +3709,7 @@ fts_query_parse(
query->root = state.root;
}
- return(state.root);
+ DBUG_RETURN(state.root);
}
/*******************************************************************//**
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index bd81ae2bb26..df443f94d75 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -1751,6 +1751,15 @@ convert_error_code_to_mysql(
return(HA_ERR_TO_BIG_ROW);
}
+
+ case DB_TOO_BIG_FOR_REDO:
+ my_printf_error(ER_TOO_BIG_ROWSIZE, "%s" , MYF(0),
+ "The size of BLOB/TEXT data inserted"
+ " in one transaction is greater than"
+ " 10% of redo log size. Increase the"
+ " redo log size using innodb_log_file_size.");
+ return(HA_ERR_TO_BIG_ROW);
+
case DB_TOO_BIG_INDEX_COL:
my_error(ER_INDEX_COLUMN_TOO_LONG, MYF(0),
DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags));
@@ -7534,12 +7543,15 @@ ha_innobase::innobase_lock_autoinc(void)
break;
case AUTOINC_NEW_STYLE_LOCKING:
- /* For simple (single/multi) row INSERTs, we fallback to the
- old style only if another transaction has already acquired
- the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT
- etc. type of statement. */
+ /* For simple (single/multi) row INSERTs/REPLACEs and RBR
+ events, we fallback to the old style only if another
+ transaction has already acquired the AUTOINC lock on
+ behalf of a LOAD FILE or INSERT ... SELECT etc. type of
+ statement. */
if (thd_sql_command(user_thd) == SQLCOM_INSERT
- || thd_sql_command(user_thd) == SQLCOM_REPLACE) {
+ || thd_sql_command(user_thd) == SQLCOM_REPLACE
+ || thd_sql_command(user_thd) == SQLCOM_END // RBR event
+ ) {
dict_table_t* ib_table = prebuilt->table;
/* Acquire the AUTOINC mutex. */
@@ -7548,9 +7560,11 @@ ha_innobase::innobase_lock_autoinc(void)
/* We need to check that another transaction isn't
already holding the AUTOINC lock on the table. */
if (ib_table->n_waiting_or_granted_auto_inc_locks) {
- /* Release the mutex to avoid deadlocks. */
+ /* Release the mutex to avoid deadlocks and
+ fall back to old style locking. */
dict_table_autoinc_unlock(ib_table);
} else {
+ /* Do not fall back to old style locking. */
break;
}
}
@@ -15518,10 +15532,8 @@ ha_innobase::cmp_ref(
len1 = innobase_read_from_2_little_endian(ref1);
len2 = innobase_read_from_2_little_endian(ref2);
- ref1 += 2;
- ref2 += 2;
result = ((Field_blob*) field)->cmp(
- ref1, len1, ref2, len2);
+ ref1 + 2, len1, ref2 + 2, len2);
} else {
result = field->key_cmp(ref1, ref2);
}
@@ -19932,6 +19944,7 @@ innobase_convert_to_system_charset(
/**********************************************************************
Issue a warning that the row is too big. */
+UNIV_INTERN
void
ib_warn_row_too_big(const dict_table_t* table)
{
@@ -19945,6 +19958,10 @@ ib_warn_row_too_big(const dict_table_t* table)
THD* thd = current_thd;
+ if (thd == NULL) {
+ return;
+ }
+
push_warning_printf(
thd, Sql_condition::WARN_LEVEL_WARN, HA_ERR_TO_BIG_ROW,
"Row size too large (> %lu). Changing some columns to TEXT"
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 7cc16197f57..94f17e75358 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -4482,11 +4482,15 @@ err_exit:
rename_foreign:
trx->op_info = "renaming column in SYS_FOREIGN_COLS";
+ std::list<dict_foreign_t*> fk_evict;
+ bool foreign_modified;
+
for (dict_foreign_set::const_iterator it = user_table->foreign_set.begin();
it != user_table->foreign_set.end();
++it) {
dict_foreign_t* foreign = *it;
+ foreign_modified = false;
for (unsigned i = 0; i < foreign->n_fields; i++) {
if (strcmp(foreign->foreign_col_names[i], from)) {
@@ -4514,6 +4518,11 @@ rename_foreign:
if (error != DB_SUCCESS) {
goto err_exit;
}
+ foreign_modified = true;
+ }
+
+ if (foreign_modified) {
+ fk_evict.push_back(foreign);
}
}
@@ -4522,7 +4531,9 @@ rename_foreign:
it != user_table->referenced_set.end();
++it) {
+ foreign_modified = false;
dict_foreign_t* foreign = *it;
+
for (unsigned i = 0; i < foreign->n_fields; i++) {
if (strcmp(foreign->referenced_col_names[i], from)) {
continue;
@@ -4549,7 +4560,17 @@ rename_foreign:
if (error != DB_SUCCESS) {
goto err_exit;
}
+ foreign_modified = true;
}
+
+ if (foreign_modified) {
+ fk_evict.push_back(foreign);
+ }
+ }
+
+ if (new_clustered) {
+ std::for_each(fk_evict.begin(), fk_evict.end(),
+ dict_foreign_remove_from_cache);
}
trx->op_info = "";
diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc
index 2082c0d194b..5fd0fdcb10a 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.cc
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc
@@ -2837,6 +2837,14 @@ ibuf_contract_in_background(
mutex_exit(&ibuf_mutex);
}
+#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
+ if (ibuf_debug) {
+ return(0);
+ }
+#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
+
+
+
while (sum_pages < n_pages) {
ulint n_bytes;
@@ -3885,7 +3893,7 @@ check_watch:
{
buf_page_t* bpage;
buf_pool_t* buf_pool = buf_pool_get(space, page_no);
- bpage = buf_page_hash_get(buf_pool, space, page_no);
+ bpage = buf_page_get_also_watch(buf_pool, space, page_no);
if (UNIV_LIKELY_NULL(bpage)) {
/* A buffer pool watch has been set or the
diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
index 0f2f9083675..1c84e68167e 100644
--- a/storage/innobase/include/buf0buf.h
+++ b/storage/innobase/include/buf0buf.h
@@ -1274,7 +1274,7 @@ page_hash lock is acquired in the specified lock mode. Otherwise,
mode value is ignored. It is up to the caller to release the
lock. If the block is found and the lock is NULL then the page_hash
lock is released by this function.
-@return block, NULL if not found */
+@return block, NULL if not found, or watch sentinel (if watch is true) */
UNIV_INLINE
buf_page_t*
buf_page_hash_get_locked(
@@ -1290,9 +1290,11 @@ buf_page_hash_get_locked(
found. NULL otherwise. If NULL
is passed then the hash_lock
is released by this function */
- ulint lock_mode); /*!< in: RW_LOCK_EX or
+ ulint lock_mode, /*!< in: RW_LOCK_EX or
RW_LOCK_SHARED. Ignored if
lock == NULL */
+ bool watch = false); /*!< in: if true, return watch
+ sentinel also. */
/******************************************************************//**
Returns the control block of a file page, NULL if not found.
If the block is found and lock is not NULL then the appropriate
@@ -1332,6 +1334,8 @@ buf_page_hash_get_low() function.
buf_page_hash_get_locked(b, s, o, l, RW_LOCK_EX)
#define buf_page_hash_get(b, s, o) \
buf_page_hash_get_locked(b, s, o, NULL, 0)
+#define buf_page_get_also_watch(b, s, o) \
+ buf_page_hash_get_locked(b, s, o, NULL, 0, true)
#define buf_block_hash_get_s_locked(b, s, o, l) \
buf_block_hash_get_locked(b, s, o, l, RW_LOCK_SHARED)
diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic
index 51d77272ef9..9bbafbc1efb 100644
--- a/storage/innobase/include/buf0buf.ic
+++ b/storage/innobase/include/buf0buf.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -1172,7 +1172,7 @@ page_hash lock is acquired in the specified lock mode. Otherwise,
mode value is ignored. It is up to the caller to release the
lock. If the block is found and the lock is NULL then the page_hash
lock is released by this function.
-@return block, NULL if not found */
+@return block, NULL if not found, or watch sentinel (if watch is true) */
UNIV_INLINE
buf_page_t*
buf_page_hash_get_locked(
@@ -1188,9 +1188,11 @@ buf_page_hash_get_locked(
found. NULL otherwise. If NULL
is passed then the hash_lock
is released by this function */
- ulint lock_mode) /*!< in: RW_LOCK_EX or
+ ulint lock_mode, /*!< in: RW_LOCK_EX or
RW_LOCK_SHARED. Ignored if
lock == NULL */
+ bool watch) /*!< in: if true, return watch
+ sentinel also. */
{
buf_page_t* bpage = NULL;
ulint fold;
@@ -1221,7 +1223,9 @@ buf_page_hash_get_locked(
bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
if (!bpage || buf_pool_watch_is_sentinel(buf_pool, bpage)) {
- bpage = NULL;
+ if (!watch) {
+ bpage = NULL;
+ }
goto unlock_and_exit;
}
diff --git a/storage/innobase/include/db0err.h b/storage/innobase/include/db0err.h
index 71916cb33f2..1e87ce3fdb8 100644
--- a/storage/innobase/include/db0err.h
+++ b/storage/innobase/include/db0err.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -130,7 +130,8 @@ enum dberr_t {
DB_TEMP_FILE_WRITE_FAILURE, /*!< Temp file write failure */
DB_FTS_TOO_MANY_WORDS_IN_PHRASE,
/*< Too many words in a phrase */
-
+ DB_TOO_BIG_FOR_REDO, /* Record length greater than 10%
+ of redo log */
/* The following are partial failure codes */
DB_FAIL = 1000,
DB_OVERFLOW,
diff --git a/storage/innobase/include/fts0ast.h b/storage/innobase/include/fts0ast.h
index 50ee587e282..b2380f78b39 100644
--- a/storage/innobase/include/fts0ast.h
+++ b/storage/innobase/include/fts0ast.h
@@ -329,4 +329,11 @@ struct fts_ast_state_t {
tokenization */
};
+#ifdef UNIV_DEBUG
+const char*
+fts_ast_oper_name_get(fts_ast_oper_t oper);
+const char*
+fts_ast_node_type_get(fts_ast_type_t type);
+#endif /* UNIV_DEBUG */
+
#endif /* INNOBASE_FSTS0AST_H */
diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h
index 212df1a1283..4d523cf1289 100644
--- a/storage/innobase/include/ha_prototypes.h
+++ b/storage/innobase/include/ha_prototypes.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2006, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2006, 2014, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
diff --git a/storage/innobase/include/lock0priv.h b/storage/innobase/include/lock0priv.h
index 9f7ab9f76b6..16423e6a282 100644
--- a/storage/innobase/include/lock0priv.h
+++ b/storage/innobase/include/lock0priv.h
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2007, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2015, MariaDB Corporation
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -72,6 +73,12 @@ struct lock_t {
hash_node_t hash; /*!< hash chain node for a record
lock */
dict_index_t* index; /*!< index for a record lock */
+
+ /* Statistics for how long lock has been held and time
+ how long this lock had to be waited before it was granted */
+ time_t requested_time; /*!< Lock request time */
+ ulint wait_time; /*!< Time waited this lock or 0 */
+
union {
lock_table_t tab_lock;/*!< table lock */
lock_rec_t rec_lock;/*!< record lock */
diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h
index 73daea32d72..99490fa044e 100644
--- a/storage/innobase/include/os0file.h
+++ b/storage/innobase/include/os0file.h
@@ -1,6 +1,6 @@
/***********************************************************************
-Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2015, MariaDB Corporation.
diff --git a/storage/innobase/include/row0merge.h b/storage/innobase/include/row0merge.h
index 31a9ac6f45e..4084a9abefc 100644
--- a/storage/innobase/include/row0merge.h
+++ b/storage/innobase/include/row0merge.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2005, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2005, 2014, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
diff --git a/storage/innobase/include/sync0rw.ic b/storage/innobase/include/sync0rw.ic
index afd25f3a071..8c4e938002a 100644
--- a/storage/innobase/include/sync0rw.ic
+++ b/storage/innobase/include/sync0rw.ic
@@ -392,6 +392,7 @@ rw_lock_x_lock_func_nowait(
ulint line) /*!< in: line where requested */
{
ibool success;
+ ibool local_recursive= lock->recursive;
#ifdef INNODB_RW_LOCKS_USE_ATOMICS
success = os_compare_and_swap_lint(&lock->lock_word, X_LOCK_DECR, 0);
@@ -406,10 +407,14 @@ rw_lock_x_lock_func_nowait(
mutex_exit(&(lock->mutex));
#endif
+ /* Note: recursive must be loaded before writer_thread see
+ comment for rw_lock_set_writer_id_and_recursion_flag().
+ To achieve this we load it before os_compare_and_swap_lint(),
+ which implies full memory barrier in current implementation. */
if (success) {
rw_lock_set_writer_id_and_recursion_flag(lock, TRUE);
- } else if (lock->recursive
+ } else if (local_recursive
&& os_thread_eq(lock->writer_thread,
os_thread_get_curr_id())) {
/* Relock: this lock_word modification is safe since no other
diff --git a/storage/innobase/include/trx0roll.h b/storage/innobase/include/trx0roll.h
index 9d020a10725..d5ab83d7767 100644
--- a/storage/innobase/include/trx0roll.h
+++ b/storage/innobase/include/trx0roll.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -32,6 +32,8 @@ Created 3/26/1996 Heikki Tuuri
#include "mtr0mtr.h"
#include "trx0sys.h"
+extern bool trx_rollback_or_clean_is_active;
+
/*******************************************************************//**
Determines if this transaction is rolling back an incomplete transaction
in crash recovery.
diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h
index 7c92445b796..6cb082edc67 100644
--- a/storage/innobase/include/trx0trx.h
+++ b/storage/innobase/include/trx0trx.h
@@ -1009,6 +1009,20 @@ struct trx_t{
/*------------------------------*/
char detailed_error[256]; /*!< detailed error message for last
error, or empty. */
+ /* Lock wait statistics */
+ ulint n_rec_lock_waits;
+ /*!< Number of record lock waits,
+ might not be exactly correct. */
+ ulint n_table_lock_waits;
+ /*!< Number of table lock waits,
+ might not be exactly correct. */
+ ulint total_rec_lock_wait_time;
+ /*!< Total rec lock wait time up
+ to this moment. */
+ ulint total_table_lock_wait_time;
+ /*!< Total table lock wait time
+ up to this moment. */
+
#ifdef WITH_WSREP
os_event_t wsrep_event; /* event waited for in srv_conc_slot */
#endif /* WITH_WSREP */
diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i
index 89c62a14958..8be8f4eed79 100644
--- a/storage/innobase/include/univ.i
+++ b/storage/innobase/include/univ.i
@@ -45,7 +45,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_MAJOR 5
#define INNODB_VERSION_MINOR 6
-#define INNODB_VERSION_BUGFIX 22
+#define INNODB_VERSION_BUGFIX 23
/* The following is the InnoDB version as shown in
SELECT plugin_version FROM information_schema.plugins;
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index 60ea773c971..6142f96cf7d 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2014, 2015, MariaDB Corporation
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -2041,6 +2042,9 @@ lock_rec_create(
/* Set the bit corresponding to rec */
lock_rec_set_nth_bit(lock, heap_no);
+ lock->requested_time = ut_time();
+ lock->wait_time = 0;
+
index->table->n_rec_locks++;
ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted);
@@ -2273,6 +2277,8 @@ lock_rec_enqueue_waiting(
MONITOR_INC(MONITOR_LOCKREC_WAIT);
+ trx->n_rec_lock_waits++;
+
return(DB_LOCK_WAIT);
}
@@ -2305,7 +2311,8 @@ lock_rec_add_to_queue(
ut_ad(lock_mutex_own());
ut_ad(caller_owns_trx_mutex == trx_mutex_own(trx));
- ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index));
+ ut_ad(dict_index_is_clust(index)
+ || dict_index_get_online_status(index) != ONLINE_INDEX_CREATION);
#ifdef UNIV_DEBUG
switch (type_mode & LOCK_MODE_MASK) {
case LOCK_X:
@@ -2745,6 +2752,17 @@ lock_grant(
}
}
+ /* Cumulate total lock wait time for statistics */
+ if (lock_get_type_low(lock) & LOCK_TABLE) {
+ lock->trx->total_table_lock_wait_time +=
+ (ulint)difftime(ut_time(), lock->trx->lock.wait_started);
+ } else {
+ lock->trx->total_rec_lock_wait_time +=
+ (ulint)difftime(ut_time(), lock->trx->lock.wait_started);
+ }
+
+ lock->wait_time = (ulint)difftime(ut_time(), lock->requested_time);
+
trx_mutex_exit(lock->trx);
}
@@ -4582,6 +4600,8 @@ lock_table_create(
lock->type_mode = type_mode | LOCK_TABLE;
lock->trx = trx;
+ lock->requested_time = ut_time();
+ lock->wait_time = 0;
lock->un_member.tab_lock.table = table;
@@ -4887,6 +4907,7 @@ lock_table_enqueue_waiting(
trx->lock.wait_started = ut_time();
trx->lock.was_chosen_as_deadlock_victim = FALSE;
+ trx->n_table_lock_waits++;
ut_a(que_thr_stop(thr));
@@ -5597,6 +5618,10 @@ lock_table_print(
fputs(" waiting", file);
}
+ fprintf(file, " lock hold time %lu wait time before grant %lu ",
+ (ulint)difftime(ut_time(), lock->requested_time),
+ lock->wait_time);
+
putc('\n', file);
}
@@ -5628,7 +5653,14 @@ lock_rec_print(
fprintf(file, "RECORD LOCKS space id %lu page no %lu n bits %lu ",
(ulong) space, (ulong) page_no,
(ulong) lock_rec_get_n_bits(lock));
+
dict_index_name_print(file, lock->trx, lock->index);
+
+ /* Print number of table locks */
+ fprintf(file, " trx table locks %lu total table locks %lu ",
+ ib_vector_size(lock->trx->lock.table_locks),
+ UT_LIST_GET_LEN(lock->index->table->locks));
+
fprintf(file, " trx id " TRX_ID_FMT, lock->trx->id);
if (lock_get_mode(lock) == LOCK_S) {
@@ -5657,6 +5689,10 @@ lock_rec_print(
mtr_start(&mtr);
+ fprintf(file, " lock hold time %lu wait time before grant %lu ",
+ (ulint)difftime(ut_time(), lock->requested_time),
+ lock->wait_time);
+
putc('\n', file);
block = buf_page_try_get(space, page_no, &mtr);
@@ -5915,6 +5951,14 @@ loop:
trx->read_view->up_limit_id);
}
+ /* Total trx lock waits and times */
+ fprintf(file, "Trx #rec lock waits %lu #table lock waits %lu\n",
+ trx->n_rec_lock_waits, trx->n_table_lock_waits);
+ fprintf(file, "Trx total rec lock wait time %lu SEC\n",
+ trx->total_rec_lock_wait_time);
+ fprintf(file, "Trx total table lock wait time %lu SEC\n",
+ trx->total_table_lock_wait_time);
+
if (trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
fprintf(file,
diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc
index 779ad112b05..12c05e16b6b 100644
--- a/storage/innobase/log/log0log.cc
+++ b/storage/innobase/log/log0log.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Google Inc.
Copyright (c) 2013, SkySQL Ab. All Rights Reserved.
@@ -49,7 +49,7 @@ Created 12/9/1995 Heikki Tuuri
#include "srv0start.h"
#include "trx0sys.h"
#include "trx0trx.h"
-#include "ha_prototypes.h"
+#include "trx0roll.h"
#include "srv0mon.h"
/*
@@ -3304,6 +3304,12 @@ logs_empty_and_mark_files_at_shutdown(void)
ib_logf(IB_LOG_LEVEL_INFO, "Starting shutdown...");
+ while (srv_fast_shutdown == 0 && trx_rollback_or_clean_is_active) {
+ /* we should wait until rollback after recovery end
+ for slow shutdown */
+ os_thread_sleep(100000);
+ }
+
/* Wait until the master thread and all other operations are idle: our
algorithm only works if the server is idle at shutdown */
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index adea9a0ce27..d0f2cd360f9 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -3511,6 +3511,7 @@ recv_recovery_rollback_active(void)
/* Rollback the uncommitted transactions which have no user
session */
+ trx_rollback_or_clean_is_active = true;
os_thread_create(trx_rollback_or_clean_all_recovered, 0, 0);
}
}
diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc
index 694038c8e37..d49f5f9900d 100644
--- a/storage/innobase/os/os0file.cc
+++ b/storage/innobase/os/os0file.cc
@@ -1,6 +1,6 @@
/***********************************************************************
-Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2015, MariaDB Corporation.
@@ -2974,11 +2974,17 @@ try_again:
if ((ulint) ret == n) {
return(TRUE);
+ } else if (ret == -1) {
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Error in system call pread(). The operating"
+ " system error number is %lu.",(ulint) errno);
+ } else {
+ /* Partial read occured */
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Tried to read " ULINTPF " bytes at offset "
+ UINT64PF ". Was only able to read %ld.",
+ n, offset, (lint) ret);
}
-
- ib_logf(IB_LOG_LEVEL_ERROR,
- "Tried to read " ULINTPF " bytes at offset " UINT64PF ". "
- "Was only able to read %ld.", n, offset, (lint) ret);
#endif /* __WIN__ */
#ifdef __WIN__
error_handling:
@@ -3101,6 +3107,16 @@ try_again:
if ((ulint) ret == n) {
return(TRUE);
+ } else if (ret == -1) {
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Error in system call pread(). The operating"
+ " system error number is %lu.",(ulint) errno);
+ } else {
+ /* Partial read occured */
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Tried to read " ULINTPF " bytes at offset "
+ UINT64PF ". Was only able to read %ld.",
+ n, offset, (lint) ret);
}
#endif /* __WIN__ */
#ifdef __WIN__
@@ -3321,18 +3337,26 @@ retry:
if (!os_has_said_disk_full) {
ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: Write to file %s failed"
- " at offset " UINT64PF ".\n"
- "InnoDB: %lu bytes should have been written,"
- " only %ld were written.\n"
- "InnoDB: Operating system error number %lu.\n"
- "InnoDB: Check that your OS and file system"
- " support files of this size.\n"
- "InnoDB: Check also that the disk is not full"
- " or a disk quota exceeded.\n",
- name, offset, n, (lint) ret,
- (ulint) errno);
+ if(ret == -1) {
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Failure of system call pwrite(). Operating"
+ " system error number is %lu.",
+ (ulint) errno);
+ } else {
+ fprintf(stderr,
+ " InnoDB: Error: Write to file %s failed"
+ " at offset " UINT64PF ".\n"
+ "InnoDB: %lu bytes should have been written,"
+ " only %ld were written.\n"
+ "InnoDB: Operating system error number %lu.\n"
+ "InnoDB: Check that your OS and file system"
+ " support files of this size.\n"
+ "InnoDB: Check also that the disk is not full"
+ " or a disk quota exceeded.\n",
+ name, offset, n, (lint) ret,
+ (ulint) errno);
+ }
+
if (strerror(errno) != NULL) {
fprintf(stderr,
"InnoDB: Error number %d means '%s'.\n",
@@ -5057,7 +5081,7 @@ os_aio_func(
mode = mode & (~OS_AIO_SIMULATED_WAKE_LATER);
DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
- mode = OS_AIO_SYNC;);
+ mode = OS_AIO_SYNC; os_has_said_disk_full = TRUE;);
if (mode == OS_AIO_SYNC
#ifdef WIN_ASYNC_IO
@@ -5088,13 +5112,9 @@ os_aio_func(
ut_a(type == OS_FILE_WRITE);
ret = os_file_write_func(name, file, buf, offset, n);
- }
- if (type == OS_FILE_WRITE) {
DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
- os_has_said_disk_full = FALSE;
- ret = 0;
- errno = 28;);
+ os_has_said_disk_full = TRUE; ret = 0; errno = 28;);
}
return ret;
@@ -6052,6 +6072,11 @@ consecutive_loop:
ret = os_file_write(
aio_slot->name, aio_slot->file, combined_buf,
aio_slot->offset, total_len);
+
+ DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
+ os_has_said_disk_full = TRUE;
+ ret = 0;
+ errno = 28;);
} else {
ret = os_file_read(
aio_slot->file, combined_buf,
@@ -6059,13 +6084,6 @@ consecutive_loop:
aio_slot->page_compression);
}
- if (aio_slot->type == OS_FILE_WRITE) {
- DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
- os_has_said_disk_full = FALSE;
- ret = 0;
- errno = 28;);
- }
-
srv_set_io_thread_op_info(global_segment, "file i/o done");
if (aio_slot->type == OS_FILE_READ && n_consecutive > 1) {
diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc
index 3ff71d5c59e..8346208ab78 100644
--- a/storage/innobase/rem/rem0rec.cc
+++ b/storage/innobase/rem/rem0rec.cc
@@ -845,7 +845,8 @@ rec_get_converted_size_comp_prefix_low(
}
ut_ad(len <= col->len || col->mtype == DATA_BLOB
- || (col->len == 0 && col->mtype == DATA_VARCHAR));
+ || col->mtype == DATA_VARMYSQL
+ || (col->len == 0 && col->mtype == DATA_VARCHAR));
fixed_len = field->fixed_len;
if (temp && fixed_len
@@ -1274,6 +1275,7 @@ rec_convert_dtuple_to_rec_comp(
} else {
ut_ad(len <= dtype_get_len(type)
|| dtype_get_mtype(type) == DATA_BLOB
+ || dtype_get_mtype(type) == DATA_VARMYSQL
|| !strcmp(index->name,
FTS_INDEX_TABLE_IND_NAME));
if (len < 128
diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc
index eb032246416..b3817e86080 100644
--- a/storage/innobase/row/row0ftsort.cc
+++ b/storage/innobase/row/row0ftsort.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2010, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2010, 2014, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index c79bd6c62ec..57be662425f 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2005, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2005, 2014, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index 43446112bca..3dd65c540c3 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2000, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2000, 2015, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -611,6 +611,7 @@ handle_new_error:
case DB_DUPLICATE_KEY:
case DB_FOREIGN_DUPLICATE_KEY:
case DB_TOO_BIG_RECORD:
+ case DB_TOO_BIG_FOR_REDO:
case DB_UNDO_RECORD_TOO_BIG:
case DB_ROW_IS_REFERENCED:
case DB_NO_REFERENCED_ROW:
@@ -4414,7 +4415,7 @@ row_drop_table_for_mysql(
case DB_OUT_OF_FILE_SPACE:
err = DB_MUST_GET_MORE_FILE_SPACE;
-
+ trx->error_state = err;
row_mysql_handle_errors(&err, trx, NULL, NULL);
/* raise error */
diff --git a/storage/innobase/row/row0quiesce.cc b/storage/innobase/row/row0quiesce.cc
index 1d67d5a9717..ecd6f47947b 100644
--- a/storage/innobase/row/row0quiesce.cc
+++ b/storage/innobase/row/row0quiesce.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2012, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2012, 2014, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -680,7 +680,6 @@ row_quiesce_set_state(
switch (state) {
case QUIESCE_START:
- ut_a(table->quiesce == QUIESCE_NONE);
break;
case QUIESCE_COMPLETE:
diff --git a/storage/innobase/srv/srv0mon.cc b/storage/innobase/srv/srv0mon.cc
index cb7c1ae6367..39481a90c00 100644
--- a/storage/innobase/srv/srv0mon.cc
+++ b/storage/innobase/srv/srv0mon.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2010, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2010, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
Copyright (c) 2013, 2014, MariaDB Corporation
@@ -1046,7 +1046,8 @@ static monitor_info_t innodb_counter_info[] =
{"adaptive_hash_searches_btree", "adaptive_hash_index",
"Number of searches using B-tree on an index search",
- MONITOR_NONE,
+ static_cast<monitor_type_t>(
+ MONITOR_EXISTING | MONITOR_DEFAULT_ON),
MONITOR_DEFAULT_START, MONITOR_OVLD_ADAPTIVE_HASH_SEARCH_BTREE},
{"adaptive_hash_pages_added", "adaptive_hash_index",
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
index 77b5e218723..ee88c1f9e33 100644
--- a/storage/innobase/srv/srv0srv.cc
+++ b/storage/innobase/srv/srv0srv.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2015, MariaDB Corporation. All Rights Reserved.
@@ -2798,7 +2798,9 @@ srv_do_purge(
*n_total_purged += n_pages_purged;
- } while (!srv_purge_should_exit(n_pages_purged) && n_pages_purged > 0);
+ } while (!srv_purge_should_exit(n_pages_purged)
+ && n_pages_purged > 0
+ && purge_sys->state == PURGE_STATE_RUN);
return(rseg_history_len);
}
diff --git a/storage/innobase/sync/sync0rw.cc b/storage/innobase/sync/sync0rw.cc
index 8e5faed08dd..8919716ff9c 100644
--- a/storage/innobase/sync/sync0rw.cc
+++ b/storage/innobase/sync/sync0rw.cc
@@ -552,6 +552,8 @@ rw_lock_x_lock_low(
const char* file_name,/*!< in: file name where lock requested */
ulint line) /*!< in: line where requested */
{
+ ibool local_recursive= lock->recursive;
+
if (rw_lock_lock_word_decr(lock, X_LOCK_DECR)) {
/* lock->recursive also tells us if the writer_thread
@@ -573,12 +575,12 @@ rw_lock_x_lock_low(
} else {
os_thread_id_t thread_id = os_thread_get_curr_id();
- if (!pass) {
- os_rmb;
- }
-
- /* Decrement failed: relock or failed lock */
- if (!pass && lock->recursive
+ /* Decrement failed: relock or failed lock
+ Note: recursive must be loaded before writer_thread see
+ comment for rw_lock_set_writer_id_and_recursion_flag().
+ To achieve this we load it before rw_lock_lock_word_decr(),
+ which implies full memory barrier in current implementation. */
+ if (!pass && local_recursive
&& os_thread_eq(lock->writer_thread, thread_id)) {
/* Relock */
if (lock->lock_word == 0) {
diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc
index a64367c4ba7..bc11f1d76bd 100644
--- a/storage/innobase/trx/trx0roll.cc
+++ b/storage/innobase/trx/trx0roll.cc
@@ -50,6 +50,9 @@ Created 3/26/1996 Heikki Tuuri
rollback */
#define TRX_ROLL_TRUNC_THRESHOLD 1
+/** true if trx_rollback_or_clean_all_recovered() thread is active */
+bool trx_rollback_or_clean_is_active;
+
/** In crash recovery, the current trx to be rolled back; NULL otherwise */
static const trx_t* trx_roll_crash_recv_trx = NULL;
@@ -805,6 +808,8 @@ DECLARE_THREAD(trx_rollback_or_clean_all_recovered)(
trx_rollback_or_clean_recovered(TRUE);
+ trx_rollback_or_clean_is_active = false;
+
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit and not use return() to exit. */
diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc
index b273b5a117e..68446cc85ef 100644
--- a/storage/innobase/ut/ut0ut.cc
+++ b/storage/innobase/ut/ut0ut.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -822,6 +822,8 @@ ut_strerr(
return("Temp file write failure");
case DB_FTS_TOO_MANY_WORDS_IN_PHRASE:
return("Too many words in a FTS phrase or proximity search");
+ case DB_TOO_BIG_FOR_REDO:
+ return("BLOB record length is greater than 10%% of redo log");
/* do not add default: in order to produce a warning if new code
is added to the enum but not added here */
diff --git a/storage/mroonga/CMakeLists.txt b/storage/mroonga/CMakeLists.txt
index 0ca1dd4638b..09cc8273e1d 100644
--- a/storage/mroonga/CMakeLists.txt
+++ b/storage/mroonga/CMakeLists.txt
@@ -1,6 +1,6 @@
# -*- indent-tabs-mode: nil -*-
#
-# Copyright(C) 2012-2014 Kouhei Sutou <kou@clear-code.com>
+# Copyright(C) 2012-2015 Kouhei Sutou <kou@clear-code.com>
# Copyright(C) 2013 Kentoku SHIBA
#
# This library is free software; you can redistribute it and/or
@@ -46,6 +46,11 @@ if(MRN_BUNDLED)
endif()
endif()
+IF(HAVE_WVLA)
+ SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wno-vla")
+ SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wno-vla")
+ENDIF()
+
set(MRN_BUNDLED_GROONGA_RELATIVE_DIR "vendor/groonga")
set(MRN_BUNDLED_GROONGA_DIR
"${CMAKE_CURRENT_SOURCE_DIR}/${MRN_BUNDLED_GROONGA_RELATIVE_DIR}")
@@ -75,6 +80,28 @@ file(READ ${MRN_SOURCE_DIR}/version_in_hex MRN_VERSION_IN_HEX)
file(READ ${MRN_SOURCE_DIR}/plugin_version MRN_PLUGIN_VERSION)
if(MRN_GROONGA_BUNDLED)
+ option(MRN_GROONGA_EMBED
+ "Embed libgroonga"
+ ON)
+ if(MRN_GROONGA_EMBED)
+ set(GRN_EMBED ON)
+ endif()
+
+ set(MRN_BUNDLED_GROONGA_NORMALIZER_MYSQL_DIR
+ "${MRN_BUNDLED_GROONGA_DIR}/vendor/plugins/groonga-normalizer-mysql")
+ option(MRN_GROONGA_NORMALIZER_MYSQL_EMBED
+ "Embed groonga-normalizer-mysql Groonga plugin"
+ ON)
+ if(EXISTS ${MRN_BUNDLED_GROONGA_NORMALIZER_MYSQL_DIR})
+ set(GROONGA_NORMALIZER_MYSQL_FOUND ON)
+ else()
+ set(GROONGA_NORMALIZER_MYSQL_FOUND OFF)
+ set(MRN_GROONGA_NORMALIZER_MYSQL_EMBED OFF)
+ endif()
+ if(MRN_GROONGA_NORMALIZER_MYSQL_EMBED)
+ set(GROONGA_NORMALIZER_MYSQL_EMBED ON)
+ endif()
+
add_subdirectory("${MRN_BUNDLED_GROONGA_RELATIVE_DIR}")
else()
file(READ ${MRN_SOURCE_DIR}/required_groonga_version REQUIRED_GROONGA_VERSION)
@@ -98,15 +125,21 @@ set(MRN_C_COMPILE_FLAGS "")
set(MRN_CXX_COMPILE_FLAGS "")
macro(mrn_check_cflag flag)
- check_c_compiler_flag(${flag} "HAVE_C_${flag}")
- if(HAVE_C_${flag})
+ string(REGEX REPLACE "[-=]" "_" temporary_variable_name ${flag})
+ string(TOUPPER "${temporary_variable_name}" temporary_variable_name)
+ set(temporary_variable_name "CFLAG${temporary_variable_name}")
+ check_c_compiler_flag(${flag} ${temporary_variable_name})
+ if(${temporary_variable_name})
set(MRN_C_COMPILE_FLAGS "${MRN_C_COMPILE_FLAGS} ${flag}")
endif()
endmacro()
macro(mrn_check_cxxflag flag)
- check_cxx_compiler_flag(${flag} "HAVE_CXX_${flag}")
- if(HAVE_CXX_${flag})
+ string(REGEX REPLACE "[-=]" "_" temporary_variable_name ${flag})
+ string(TOUPPER "${temporary_variable_name}" temporary_variable_name)
+ set(temporary_variable_name "CXXFLAG${temporary_variable_name}")
+ check_cxx_compiler_flag(${flag} ${temporary_variable_name})
+ if(${temporary_variable_name})
set(MRN_CXX_COMPILE_FLAGS "${MRN_CXX_COMPILE_FLAGS} ${flag}")
endif()
endmacro()
@@ -122,7 +155,7 @@ else()
set(MRN_RELATIVE_DIR_PREFIX "")
endif()
-read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/sources.am MROONGA_SOURCES)
+read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/sources.am MRN_SOURCES)
read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/lib/libmrn_no_mysql_sources.am
LIBMRN_NO_MYSQL_SOURCES)
string(REGEX REPLACE "([^;]+)" "${MRN_RELATIVE_DIR_PREFIX}lib/\\1"
@@ -157,11 +190,18 @@ else()
set(MYSQL_REGEX_INCLUDE_DIR "${MYSQL_SOURCE_DIR}/regex")
endif()
+if(EXISTS "${MYSQL_SOURCE_DIR}/extra/rapidjson")
+ set(MYSQL_RAPIDJSON_INCLUDE_DIR "${MYSQL_SOURCE_DIR}/extra/rapidjson/include")
+else()
+ set(MYSQL_RAPIDJSON_INCLUDE_DIR)
+endif()
+
set(MYSQL_INCLUDE_DIRS
"${MYSQL_BUILD_DIR}/include"
"${MYSQL_SOURCE_DIR}/sql"
"${MYSQL_SOURCE_DIR}/include"
"${MYSQL_REGEX_INCLUDE_DIR}"
+ "${MYSQL_RAPIDJSON_INCLUDE_DIR}"
"${MYSQL_SOURCE_DIR}")
if(MRN_BUNDLED)
@@ -190,6 +230,12 @@ else()
set_mysql_config_value("--version" MYSQL_VERSION)
endif()
+if(${MYSQL_VERSION} VERSION_LESS "5.5.0")
+ message(FATAL_ERROR
+ "Mroonga doesn't support MySQL < 5.5.0: <${MYSQL_VERSION}>")
+ return()
+endif()
+
if(${MYSQL_VERSION} VERSION_GREATER "10.0.0" AND
${MYSQL_VERSION} VERSION_LESS "10.0.9")
message(FATAL_ERROR
@@ -201,10 +247,14 @@ if(MRN_GROONGA_BUNDLED)
set(GROONGA_INCLUDE_DIRS "${MRN_BUNDLED_GROONGA_DIR}/include")
set(GROONGA_LIBRARY_DIRS "${MRN_BUNDLED_GROONGA_DIR}/lib")
set(GROONGA_LIBRARIES "libgroonga")
- if(EXISTS "${MRN_BUNDLED_GROONGA_DIR}/vendor/plugins/groonga-normalizer-mysql")
- set(GROONGA_NORMALIZER_MYSQL_FOUND TRUE)
- else()
- set(GROONGA_NORMALIZER_MYSQL_FOUND FALSE)
+
+ set(MRN_LIBRARY_DIRS ${GROONGA_LIBRARY_DIRS})
+ set(MRN_LIBRARIES ${GROONGA_LIBRARIES})
+ if(MRN_GROONGA_NORMALIZER_MYSQL_EMBED)
+ set(MRN_LIBRARY_DIRS
+ ${MRN_LIBRARY_DIRS}
+ "${MRN_BUNDLED_GROONGA_NORMALIZER_MYSQL_DIR}/normalizers")
+ set(MRN_LIBRARIES ${MRN_LIBRARIES} mysql_normalizer)
endif()
else()
include(FindPkgConfig)
@@ -213,12 +263,6 @@ else()
"groonga-normalizer-mysql >= ${REQUIRED_GROONGA_NORMALIZER_MYSQL_VERSION}")
endif()
-if(GROONGA_NORMALIZER_MYSQL_FOUND AND MRN_GROONGA_BUNDLED)
- read_file_list(${MRN_BUNDLED_GROONGA_DIR}/vendor/plugins/groonga-normalizer-mysql/normalizers/mysql_sources.am MRN_GRN_NORMALIZER_MYSQL_SOURCES)
- string(REGEX REPLACE "([^;]+)" "${MRN_BUNDLED_GROONGA_DIR}/vendor/plugins/groonga-normalizer-mysql/normalizers/\\1"
- MRN_GRN_NORMALIZER_MYSQL_SOURCES "${MRN_GRN_NORMALIZER_MYSQL_SOURCES}")
-endif()
-
include_directories(
"${PROJECT_BINARY_DIR}"
"${PROJECT_SOURCE_DIR}"
@@ -235,57 +279,50 @@ else()
"${MYSQL_SERVICES_LIB_DIR}")
endif()
link_directories(
- ${GROONGA_LIBRARY_DIRS}
+ ${MRN_LIBRARY_DIRS}
${MYSQL_LIBRARY_DIRS})
+set(MRN_ALL_SOURCES
+ ${MRN_SOURCES}
+ ${MRN_UDF_SOURCES}
+ ${LIBMRN_NO_MYSQL_SOURCES}
+ ${LIBMRN_NEED_MYSQL_SOURCES})
+
if(MRN_BUNDLED)
- if(GROONGA_NORMALIZER_MYSQL_FOUND AND MRN_GROONGA_BUNDLED)
- set(sources "${MROONGA_SOURCES};${MRN_UDF_SOURCES};${MRN_GRN_NORMALIZER_MYSQL_SOURCES};${LIBMRN_NEED_MYSQL_SOURCES};${LIBMRN_NO_MYSQL_SOURCES}")
- else()
- set(sources "${MROONGA_SOURCES};${MRN_UDF_SOURCES};${LIBMRN_NEED_MYSQL_SOURCES};${LIBMRN_NO_MYSQL_SOURCES}")
- endif()
- mysql_add_plugin(mroonga ${sources} STORAGE_ENGINE MODULE_ONLY LINK_LIBRARIES ${GROONGA_LIBRARIES}
- DISABLED)
- else()
+ mysql_add_plugin(mroonga
+ ${MRN_ALL_SOURCES}
+ STORAGE_ENGINE MODULE_ONLY DISABLED # see MDEV-7246
+ LINK_LIBRARIES ${MRN_LIBRARIES})
else()
- add_library(mroonga MODULE
- ${MROONGA_SOURCES}
- ${MRN_UDF_SOURCES}
- ${LIBMRN_NO_MYSQL_SOURCES}
- ${LIBMRN_NEED_MYSQL_SOURCES})
+ add_library(mroonga MODULE ${MRN_ALL_SOURCES})
set(MYSQL_LIBRARIES "mysqlservices")
target_link_libraries(mroonga ${GROONGA_LIBRARIES} ${MYSQL_LIBRARIES})
option(WITH_DEBUG "Enable debug options" OFF)
if(WITH_DEBUG)
- set_property(TARGET mroonga APPEND PROPERTY
- COMPILE_DEFINITIONS "SAFE_MUTEX")
+ add_definitions("-DSAFE_MUTEX")
if(CMAKE_COMPILER_IS_GNUCXX)
set(MRN_C_COMPILE_FLAGS "${MRN_C_COMPILE_FLAGS} -g3 -O0")
set(MRN_CXX_COMPILE_FLAGS "${MRN_CXX_COMPILE_FLAGS} -g3 -O0")
endif()
else()
- set_property(TARGET mroonga APPEND PROPERTY
- COMPILE_DEFINITIONS "DBUG_OFF")
+ add_definitions("-DDBUG_OFF")
endif()
option(WITH_DEBUG_FULL "Enable full debug options" OFF)
if(WITH_DEBUG_FULL)
- set_property(TARGET mroonga APPEND PROPERTY
- COMPILE_DEFINITIONS "SAFE_MUTEX" "SAFEMALLOC")
+ add_definitions("-DSAFE_MUTEX" "SAFEMALLOC")
endif()
option(DISABLE_FAST_MUTEXES "Force disabling fast mutex" OFF)
if(DISABLE_FAST_MUTEXES)
- set_property(TARGET mroonga APPEND PROPERTY
- COMPILE_DEFINITIONS "FORCE_FAST_MUTEX_DISABLED=1")
+ add_definitions("-DFORCE_FAST_MUTEX_DISABLED=1")
endif()
option(WITH_FAST_MUTEXES "Enable fast mutex" OFF)
if(WITH_FAST_MUTEXES)
- set_property(TARGET mroonga APPEND PROPERTY
- COMPILE_DEFINITIONS "MY_PTHREAD_FASTMUTEX")
+ add_definitions("-DMY_PTHREAD_FASTMUTEX")
endif()
if(CMAKE_COMPILER_IS_GNUCXX)
@@ -299,16 +336,15 @@ else()
mrn_check_cxxflag("-fno-rtti")
mrn_check_cxxflag("-felide-constructors")
endif()
- set_source_files_properties(${MROONGA_SOURCES} PROPERTIES
+ set_source_files_properties(${MRN_SOURCES} PROPERTIES
COMPILE_FLAGS "${MYSQL_CFLAGS} ${MRN_CXX_COMPILE_FLAGS}")
set_source_files_properties(${LIBMRN_NEED_MYSQL_SOURCES} PROPERTIES
COMPILE_FLAGS "${MYSQL_CFLAGS} ${MRN_CXX_COMPILE_FLAGS}")
set_source_files_properties(${MRN_UDF_SOURCES} PROPERTIES
- COMPILE_FLAGS "${MRN_C_COMPILE_FLAGS}")
+ COMPILE_FLAGS "${MRN_CXX_COMPILE_FLAGS}")
set_source_files_properties(${LIBMRN_NO_MYSQL_SOURCES} PROPERTIES
- COMPILE_FLAGS "${MRN_C_COMPILE_FLAGS}")
- set_property(TARGET mroonga APPEND PROPERTY
- COMPILE_DEFINITIONS "MYSQL_DYNAMIC_PLUGIN")
+ COMPILE_FLAGS "${MRN_CXX_COMPILE_FLAGS}")
+ add_definitions("-DMYSQL_DYNAMIC_PLUGIN")
set_target_properties(mroonga PROPERTIES
PREFIX ""
OUTPUT_NAME "ha_mroonga")
@@ -317,19 +353,16 @@ else()
endif()
if(GROONGA_NORMALIZER_MYSQL_FOUND)
- set(WITH_GROONGA_NORMALIZER_MYSQL 1)
- ADD_DEFINITIONS(-DWITH_GROONGA_NORMALIZER_MYSQL=1)
- if(MRN_GROONGA_BUNDLED)
- ADD_DEFINITIONS(-DGROONGA_NORMALIZER_MYSQL_PLUGIN_IS_BUNDLED_STATIC=1)
+ add_definitions("-DWITH_GROONGA_NORMALIZER_MYSQL=1")
+ if(MRN_GROONGA_NORMALIZER_MYSQL_EMBED)
+ add_definitions("-DMRN_GROONGA_NORMALIZER_MYSQL_EMBED")
else()
- set(GROONGA_NORMALIZER_MYSQL_PLUGIN_NAME \"normalizers/mysql\")
- set_property(TARGET mroonga APPEND PROPERTY
- COMPILE_DEFINITIONS "GROONGA_NORMALIZER_MYSQL_PLUGIN_NAME=\"normalizers/mysql\"")
+ add_definitions("-DGROONGA_NORMALIZER_MYSQL_PLUGIN_NAME=\"normalizers/mysql\"")
endif()
endif()
set(MRN_DEFAULT_PARSER "TokenBigram" CACHE STRING "The default fulltext parser")
-ADD_DEFINITIONS(-DMRN_PARSER_DEFAULT="${MRN_DEFAULT_PARSER}")
+add_definitions("-DMRN_PARSER_DEFAULT=\"${MRN_DEFAULT_PARSER}\"")
configure_file(
"${PROJECT_SOURCE_DIR}/mrn_version.h.in"
diff --git a/storage/mroonga/Makefile.am b/storage/mroonga/Makefile.am
index 32fc88ad061..733347eb2c2 100644
--- a/storage/mroonga/Makefile.am
+++ b/storage/mroonga/Makefile.am
@@ -67,8 +67,6 @@ update-latest-release: misc
misc/update-latest-release.rb \
$(PACKAGE) $(OLD_RELEASE) $(OLD_RELEASE_DATE) \
$(VERSION) $(NEW_RELEASE_DATE) \
- packages/rpm/fedora/mysql-mroonga.spec.in \
- packages/rpm/fedora/mariadb-mroonga.spec.in \
packages/rpm/centos/mariadb-mroonga.spec.in \
packages/rpm/centos/mysql55-mroonga.spec.in \
packages/rpm/centos/mysql56-community-mroonga.spec.in \
diff --git a/storage/mroonga/appveyor.yml b/storage/mroonga/appveyor.yml
new file mode 100644
index 00000000000..a048d7d02e1
--- /dev/null
+++ b/storage/mroonga/appveyor.yml
@@ -0,0 +1,51 @@
+version: "{build}"
+clone_depth: 10
+install:
+ - cd ..
+ - choco install curl 7zip.commandline
+ - curl -O http://mirror.jmu.edu/pub/mariadb/mariadb-10.0.16/source/mariadb-10.0.16.tar.gz
+ - 7z x mariadb-10.0.16.tar.gz
+ - 7z x mariadb-10.0.16.tar > nul
+ - cd mariadb-10.0.16
+ - rmdir /S /Q storage\mroonga\
+ - move ..\mroonga storage\mroonga
+ - git clone --quiet --depth 1 https://github.com/groonga/groonga.git ..\groonga
+ - rmdir /S /Q ..\groonga\test\
+ - mkdir storage\mroonga\vendor
+ - move ..\groonga storage\mroonga\vendor\groonga
+ - git clone --quiet --depth 1 https://github.com/groonga/groonga-normalizer-mysql.git storage\mroonga\vendor\groonga\vendor\plugins\groonga-normalizer-mysql
+build_script:
+ - "echo # > win\\packaging\\CMakeLists.txt"
+ - cmake . -G "Visual Studio 12 Win64"
+ -DCMAKE_BUILD_TYPE=Debug
+ -DWITHOUT_ARCHIVE=ON
+ -DWITHOUT_BLACKHOLE=ON
+ -DWITHOUT_CASSANDRA=ON
+ -DWITHOUT_CONNECT=ON
+ -DWITHOUT_CSV=ON
+ -DWITHOUT_EXAMPLE=ON
+ -DWITHOUT_FEDERATED=ON
+ -DWITHOUT_FEDERATEDX=ON
+ -DWITHOUT_HEAP=ON
+ -DWITHOUT_INNOBASE=ON
+ -DWITHOUT_MYISAM=ON
+ -DWITHOUT_MYISAMMRG=ON
+ -DWITHOUT_OQGRAPH=ON
+ -DWITHOUT_PERFSCHEMA=OFF
+ -DWITHOUT_SEQUENCE=ON
+ -DWITHOUT_SPHINX=ON
+ -DWITHOUT_SPIDER=ON
+ -DWITHOUT_TEST_SQL_DISCOVERY=ON
+ -DWITHOUT_TOKUDB=ON
+ -DWITHOUT_XTRADB=ON
+ -DWITH_UNIT_TESTS=OFF
+ - cmake --build . --config Debug
+
+notifications:
+ - provider: Email
+ to:
+ - groonga-mysql-commit@lists.sourceforge.jp
+ - kou@clear-code.com
+ on_build_status_changed: true
+
+test: off
diff --git a/storage/mroonga/configure.ac b/storage/mroonga/configure.ac
index 48312a44c8c..6d8fa0fe31d 100644
--- a/storage/mroonga/configure.ac
+++ b/storage/mroonga/configure.ac
@@ -174,6 +174,10 @@ AC_DEFUN([CONFIG_OPTION_MYSQL],[
MYSQL_INCLUDES="$MYSQL_INCLUDES -I$ac_mysql_build_dir/include"
MYSQL_INCLUDES="$MYSQL_INCLUDES -I$ac_mysql_source_dir/sql"
MYSQL_INCLUDES="$MYSQL_INCLUDES -I$ac_mysql_source_dir/include"
+ if test -d "$ac_mysql_source_dir/extra/rapidjson"; then
+ mysql_rapidjson_include_dir="$ac_mysql_source_dir/extra/rapidjson/include"
+ MYSQL_INCLUDES="$MYSQL_INCLUDES -I$mysql_rapidjson_include_dir"
+ fi
if test -d "$ac_mysql_source_dir/pcre"; then
mysql_regex_include_dir="$ac_mysql_source_dir/pcre"
else
@@ -461,7 +465,6 @@ AC_CONFIG_FILES([
packages/Makefile
packages/rpm/Makefile
packages/rpm/centos/Makefile
- packages/rpm/fedora/Makefile
packages/yum/Makefile
packages/apt/Makefile
packages/source/Makefile
@@ -486,8 +489,6 @@ AC_OUTPUT([
packages/rpm/centos/mysql55-mroonga.spec
packages/rpm/centos/mysql56-community-mroonga.spec
packages/rpm/centos/mariadb-mroonga.spec
- packages/rpm/fedora/mysql-mroonga.spec
- packages/rpm/fedora/mariadb-mroonga.spec
packages/yum/env.sh
data/install.sql
])
diff --git a/storage/mroonga/ha_mroonga.cpp b/storage/mroonga/ha_mroonga.cpp
index 8b9a08b59dc..dbc2f0ca6e3 100644
--- a/storage/mroonga/ha_mroonga.cpp
+++ b/storage/mroonga/ha_mroonga.cpp
@@ -2,7 +2,7 @@
/*
Copyright(C) 2010 Tetsuro IKEDA
Copyright(C) 2010-2013 Kentoku SHIBA
- Copyright(C) 2011-2014 Kouhei Sutou <kou@clear-code.com>
+ Copyright(C) 2011-2015 Kouhei Sutou <kou@clear-code.com>
Copyright(C) 2013 Kenji Maruyama <mmmaru777@gmail.com>
This library is free software; you can redistribute it and/or
@@ -116,23 +116,14 @@
} \
} while (0)
#else
-# if MYSQL_VERSION_ID >= 50500
-# ifdef DBUG_OFF
-# ifndef _WIN32
-extern mysql_mutex_t LOCK_open;
-# endif
-# endif
-static mysql_mutex_t *mrn_LOCK_open;
-# define mrn_open_mutex_lock(share) mysql_mutex_lock(mrn_LOCK_open)
-# define mrn_open_mutex_unlock(share) mysql_mutex_unlock(mrn_LOCK_open)
-# else
+# ifdef DBUG_OFF
# ifndef _WIN32
-extern pthread_mutex_t LOCK_open;
+extern mysql_mutex_t LOCK_open;
# endif
-static pthread_mutex_t *mrn_LOCK_open;
-# define mrn_open_mutex_lock(share)
-# define mrn_open_mutex_unlock(share)
# endif
+static mysql_mutex_t *mrn_LOCK_open;
+# define mrn_open_mutex_lock(share) mysql_mutex_lock(mrn_LOCK_open)
+# define mrn_open_mutex_unlock(share) mysql_mutex_unlock(mrn_LOCK_open)
#endif
#if MYSQL_VERSION_ID >= 50600
@@ -169,15 +160,6 @@ static pthread_mutex_t *mrn_LOCK_open;
# define MRN_ABORT_ON_WARNING(thd) thd->abort_on_warning
#endif
-#ifdef WIN32
-# ifdef MRN_TABLE_SHARE_HAVE_LOCK_SHARE
- PSI_mutex_key *mrn_table_share_lock_share;
-# endif
-# ifdef MRN_TABLE_SHARE_HAVE_LOCK_HA_DATA
- PSI_mutex_key *mrn_table_share_lock_ha_data;
-# endif
-#endif
-
#if MYSQL_VERSION_ID >= 100007 && defined(MRN_MARIADB_P)
# define MRN_THD_GET_AUTOINC(thd, off, inc) thd_get_autoinc(thd, off, inc)
# define MRN_GET_ERR_MSG(code) my_get_err_msg(code)
@@ -208,19 +190,58 @@ int grn_atoi(const char *nptr, const char *end, const char **rest);
uint grn_atoui(const char *nptr, const char *end, const char **rest);
/* global variables */
-static pthread_mutex_t mrn_log_mutex;
handlerton *mrn_hton_ptr;
HASH mrn_open_tables;
-pthread_mutex_t mrn_open_tables_mutex;
+mysql_mutex_t mrn_open_tables_mutex;
HASH mrn_long_term_share;
-pthread_mutex_t mrn_long_term_share_mutex;
+mysql_mutex_t mrn_long_term_share_mutex;
+HASH mrn_allocated_thds;
+mysql_mutex_t mrn_allocated_thds_mutex;
/* internal variables */
static grn_ctx mrn_ctx;
+static mysql_mutex_t mrn_log_mutex;
static grn_obj *mrn_db;
static grn_ctx mrn_db_manager_ctx;
+static mysql_mutex_t mrn_db_manager_mutex;
mrn::DatabaseManager *mrn_db_manager = NULL;
+#ifdef HAVE_PSI_INTERFACE
+PSI_mutex_key mrn_allocated_thds_mutex_key;
+static PSI_mutex_key mrn_open_tables_mutex_key;
+static PSI_mutex_key mrn_long_term_share_mutex_key;
+PSI_mutex_key mrn_share_mutex_key;
+PSI_mutex_key mrn_long_term_share_auto_inc_mutex_key;
+static PSI_mutex_key mrn_db_manager_mutex_key;
+static PSI_mutex_key mrn_log_mutex_key;
+
+static PSI_mutex_info mrn_mutexes[] =
+{
+ {&mrn_open_tables_mutex_key, "open_tables", PSI_FLAG_GLOBAL},
+ {&mrn_long_term_share_mutex_key, "long_term_share", PSI_FLAG_GLOBAL},
+ {&mrn_allocated_thds_mutex_key, "allocated_thds", PSI_FLAG_GLOBAL},
+ {&mrn_share_mutex_key, "share", 0},
+ {&mrn_long_term_share_auto_inc_mutex_key,
+ "long_term_share::auto_inc", 0},
+ {&mrn_log_mutex_key, "log", PSI_FLAG_GLOBAL},
+ {&mrn_db_manager_mutex_key, "DatabaseManager", PSI_FLAG_GLOBAL}
+};
+
+#ifdef WIN32
+# ifdef MRN_TABLE_SHARE_HAVE_LOCK_SHARE
+ PSI_mutex_key *mrn_table_share_lock_share;
+# endif
+# ifdef MRN_TABLE_SHARE_HAVE_LOCK_HA_DATA
+ PSI_mutex_key *mrn_table_share_lock_ha_data;
+# endif
+#endif
+
+#else
+#undef MRN_TABLE_SHARE_HAVE_LOCK_SHARE
+#undef MRN_TABLE_SHARE_HAVE_LOCK_HA_DATA
+#endif
+
+
#ifdef WIN32
static inline double round(double x)
{
@@ -506,6 +527,31 @@ static int mrn_lock_timeout = grn_get_lock_timeout();
static char *mrn_libgroonga_version = const_cast<char *>(grn_get_version());
static char *mrn_version = const_cast<char *>(MRN_VERSION);
static char *mrn_vector_column_delimiter = NULL;
+static my_bool mrn_libgroonga_support_zlib = FALSE;
+static my_bool mrn_libgroonga_support_lz4 = FALSE;
+typedef enum {
+ MRN_BOOLEAN_MODE_SYNTAX_FLAG_DEFAULT = (1 << 0),
+ MRN_BOOLEAN_MODE_SYNTAX_FLAG_SYNTAX_QUERY = (1 << 1),
+ MRN_BOOLEAN_MODE_SYNTAX_FLAG_SYNTAX_SCRIPT = (1 << 2),
+ MRN_BOOLEAN_MODE_SYNTAX_FLAG_ALLOW_COLUMN = (1 << 3),
+ MRN_BOOLEAN_MODE_SYNTAX_FLAG_ALLOW_UPDATE = (1 << 4),
+ MRN_BOOLEAN_MODE_SYNTAX_FLAG_ALLOW_LEADING_NOT = (1 << 5)
+} mrn_boolean_mode_syntax_flag;
+static const char *mrn_boolean_mode_sytnax_flag_names[] = {
+ "DEFAULT",
+ "SYNTAX_QUERY",
+ "SYNTAX_SCRIPT",
+ "ALLOW_COLUMN",
+ "ALLOW_UPDATE",
+ "ALLOW_LEADING_NOT",
+ NullS
+};
+static TYPELIB mrn_boolean_mode_syntax_flags_typelib = {
+ array_elements(mrn_boolean_mode_sytnax_flag_names) - 1,
+ "",
+ mrn_boolean_mode_sytnax_flag_names,
+ NULL
+};
typedef enum {
MRN_ACTION_ON_ERROR_ERROR,
@@ -552,9 +598,6 @@ static grn_logger mrn_logger = {
NULL
};
-/* global hashes and mutexes */
-HASH mrn_allocated_thds;
-pthread_mutex_t mrn_allocated_thds_mutex;
static uchar *mrn_allocated_thds_get_key(const uchar *record,
size_t *length,
my_bool not_used __attribute__ ((unused)))
@@ -578,13 +621,21 @@ static struct st_mysql_show_var mrn_status_variables[] =
{NullS, NullS, SHOW_LONG}
};
-static const char *mrn_log_level_type_names[] = { "NONE", "EMERG", "ALERT",
- "CRIT", "ERROR", "WARNING",
- "NOTICE", "INFO", "DEBUG",
- "DUMP", NullS };
-static TYPELIB mrn_log_level_typelib =
-{
- array_elements(mrn_log_level_type_names)-1,
+static const char *mrn_log_level_type_names[] = {
+ "NONE",
+ "EMERG",
+ "ALERT",
+ "CRIT",
+ "ERROR",
+ "WARNING",
+ "NOTICE",
+ "INFO",
+ "DEBUG",
+ "DUMP",
+ NullS
+};
+static TYPELIB mrn_log_level_typelib = {
+ array_elements(mrn_log_level_type_names) - 1,
"mrn_log_level_typelib",
mrn_log_level_type_names,
NULL
@@ -678,7 +729,7 @@ static void mrn_log_file_update(THD *thd, struct st_mysql_sys_var *var,
#ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR
char *old_log_file_name = *old_value_ptr;
*old_value_ptr = my_strdup(new_log_file_name, MYF(MY_WME));
- my_free(old_log_file_name, MYF(0));
+ my_free(old_log_file_name);
#else
*old_value_ptr = my_strdup(new_log_file_name, MYF(MY_WME));
#endif
@@ -717,7 +768,7 @@ static void mrn_default_parser_update(THD *thd, struct st_mysql_sys_var *var,
}
#ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR
- my_free(*old_value_ptr, MYF(0));
+ my_free(*old_value_ptr);
*old_value_ptr = my_strdup(new_value, MYF(MY_WME));
#else
*old_value_ptr = (char *)new_value;
@@ -771,7 +822,7 @@ static void mrn_vector_column_delimiter_update(THD *thd, struct st_mysql_sys_var
char **old_value_ptr = (char **)var_ptr;
#ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR
- my_free(*old_value_ptr, MYF(0));
+ my_free(*old_value_ptr);
*old_value_ptr = my_strdup(new_value, MYF(MY_WME));
#else
*old_value_ptr = (char *)new_value;
@@ -796,7 +847,7 @@ static void mrn_database_path_prefix_update(THD *thd,
char **old_value_ptr = (char **)var_ptr;
#ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR
if (*old_value_ptr)
- my_free(*old_value_ptr, MYF(0));
+ my_free(*old_value_ptr);
if (new_value)
*old_value_ptr = my_strdup(new_value, MYF(MY_WME));
else
@@ -876,6 +927,58 @@ static MYSQL_SYSVAR_STR(version, mrn_version,
NULL,
MRN_VERSION);
+static my_bool grn_check_zlib_support()
+{
+ bool is_zlib_support = false;
+ grn_obj grn_support_p;
+
+ GRN_BOOL_INIT(&grn_support_p, 0);
+ grn_obj_get_info(&mrn_ctx, NULL, GRN_INFO_SUPPORT_ZLIB, &grn_support_p);
+ is_zlib_support = (GRN_BOOL_VALUE(&grn_support_p));
+ grn_obj_unlink(&mrn_ctx, &grn_support_p);
+
+ return is_zlib_support;
+}
+
+static my_bool grn_check_lz4_support()
+{
+ bool is_lz4_support = false;
+ grn_obj grn_support_p;
+
+ GRN_BOOL_INIT(&grn_support_p, 0);
+ grn_obj_get_info(&mrn_ctx, NULL, GRN_INFO_SUPPORT_LZ4, &grn_support_p);
+ is_lz4_support = (GRN_BOOL_VALUE(&grn_support_p));
+ grn_obj_unlink(&mrn_ctx, &grn_support_p);
+
+ return is_lz4_support;
+}
+
+static MYSQL_SYSVAR_BOOL(libgroonga_support_zlib, mrn_libgroonga_support_zlib,
+ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
+ "The status of libgroonga supports zlib",
+ NULL,
+ NULL,
+ grn_check_zlib_support());
+
+static MYSQL_SYSVAR_BOOL(libgroonga_support_lz4, mrn_libgroonga_support_lz4,
+ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
+ "The status of libgroonga supports LZ4",
+ NULL,
+ NULL,
+ grn_check_lz4_support());
+
+static MYSQL_THDVAR_SET(boolean_mode_syntax_flags,
+ PLUGIN_VAR_RQCMDARG,
+ "The flags to custom syntax in BOOLEAN MODE. "
+ "Available flags: "
+ "DEFAULT(=SYNTAX_QUERY,ALLOW_LEADING_NOT), "
+ "SYNTAX_QUERY, SYNTAX_SCRIPT, "
+ "ALLOW_COLUMN, ALLOW_UPDATE and ALLOW_LEADING_NOT",
+ NULL,
+ NULL,
+ MRN_BOOLEAN_MODE_SYNTAX_FLAG_DEFAULT,
+ &mrn_boolean_mode_syntax_flags_typelib);
+
static struct st_mysql_sys_var *mrn_system_variables[] =
{
MYSQL_SYSVAR(log_level),
@@ -891,6 +994,9 @@ static struct st_mysql_sys_var *mrn_system_variables[] =
MYSQL_SYSVAR(libgroonga_version),
MYSQL_SYSVAR(version),
MYSQL_SYSVAR(vector_column_delimiter),
+ MYSQL_SYSVAR(libgroonga_support_zlib),
+ MYSQL_SYSVAR(libgroonga_support_lz4),
+ MYSQL_SYSVAR(boolean_mode_syntax_flags),
NULL
};
@@ -917,7 +1023,7 @@ static ST_FIELD_INFO i_s_mrn_stats_fields_info[] =
MYSQL_TYPE_LONG,
0,
0,
- "Rows written to groonga",
+ "Rows written to Groonga",
SKIP_OPEN_TABLE
},
{
@@ -926,7 +1032,7 @@ static ST_FIELD_INFO i_s_mrn_stats_fields_info[] =
MYSQL_TYPE_LONG,
0,
0,
- "Rows read from groonga",
+ "Rows read from Groonga",
SKIP_OPEN_TABLE
}
};
@@ -1191,6 +1297,65 @@ static grn_builtin_type mrn_grn_type_from_field(grn_ctx *ctx, Field *field,
return type;
}
+grn_obj_flags mrn_parse_grn_column_create_flags(THD *thd,
+ grn_ctx *ctx,
+ const char *flag_names,
+ uint flag_names_length)
+{
+ grn_obj_flags flags = 0;
+ const char *flag_names_end = flag_names + flag_names_length;
+
+ while (flag_names < flag_names_end) {
+ uint rest_length = flag_names_end - flag_names;
+
+ if (*flag_names == '|' || *flag_names == ' ') {
+ flag_names += 1;
+ continue;
+ }
+ if (rest_length >= 13 && !memcmp(flag_names, "COLUMN_SCALAR", 13)) {
+ flags |= GRN_OBJ_COLUMN_SCALAR;
+ flag_names += 13;
+ } else if (rest_length >= 13 && !memcmp(flag_names, "COLUMN_VECTOR", 13)) {
+ flags |= GRN_OBJ_COLUMN_VECTOR;
+ flag_names += 13;
+ } else if (rest_length >= 13 && !memcmp(flag_names, "COMPRESS_ZLIB", 13)) {
+ if (mrn_libgroonga_support_zlib) {
+ flags |= GRN_OBJ_COMPRESS_ZLIB;
+ } else {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_MRN_UNSUPPORTED_COLUMN_FLAG_NUM,
+ ER_MRN_UNSUPPORTED_COLUMN_FLAG_STR,
+ "COMPRESS_ZLIB");
+ }
+ flag_names += 13;
+ } else if (rest_length >= 12 && !memcmp(flag_names, "COMPRESS_LZ4", 12)) {
+ if (mrn_libgroonga_support_lz4) {
+ flags |= GRN_OBJ_COMPRESS_LZ4;
+ } else {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_MRN_UNSUPPORTED_COLUMN_FLAG_NUM,
+ ER_MRN_UNSUPPORTED_COLUMN_FLAG_STR,
+ "COMPRESS_LZ4");
+ }
+ flag_names += 12;
+ } else {
+ char invalid_flag_name[MRN_MESSAGE_BUFFER_SIZE];
+ snprintf(invalid_flag_name, MRN_MESSAGE_BUFFER_SIZE,
+ "%.*s",
+ static_cast<int>(rest_length),
+ flag_names);
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_MRN_INVALID_COLUMN_FLAG_NUM,
+ ER_MRN_INVALID_COLUMN_FLAG_STR,
+ invalid_flag_name,
+ "COLUMN_SCALAR");
+ flags |= GRN_OBJ_COLUMN_SCALAR;
+ break;
+ }
+ }
+ return flags;
+}
+
#ifdef HAVE_SPATIAL
static int mrn_set_geometry(grn_ctx *ctx, grn_obj *buf,
const char *wkb, uint wkb_size)
@@ -1275,7 +1440,7 @@ static int mrn_init(void *p)
hton = (handlerton *)p;
hton->state = SHOW_OPTION_YES;
hton->create = mrn_handler_create;
- hton->flags = HTON_NO_PARTITION;
+ hton->flags = 0;
hton->drop_database = mrn_drop_database;
hton->close_connection = mrn_close_connection;
hton->flush_logs = mrn_flush_logs;
@@ -1294,13 +1459,8 @@ static int mrn_init(void *p)
# endif
# ifndef MRN_HAVE_TDC_LOCK_TABLE_SHARE
mrn_LOCK_open =
-# if MYSQL_VERSION_ID >= 50500
(mysql_mutex_t *)GetProcAddress(current_module,
"?LOCK_open@@3Ust_mysql_mutex@@A");
-# else
- (pthread_mutex_t *)GetProcAddress(current_module,
- "?LOCK_open@@3U_RTL_CRITICAL_SECTION@@A");
-# endif
# endif
# ifdef MRN_TABLE_SHARE_HAVE_LOCK_SHARE
mrn_table_share_lock_share =
@@ -1321,7 +1481,14 @@ static int mrn_init(void *p)
# endif
#endif
- // init groonga
+#ifdef HAVE_PSI_INTERFACE
+ if (PSI_server) {
+ const char *category = "mroonga";
+ int n_mutexes = array_elements(mrn_mutexes);
+ PSI_server->register_mutex(category, mrn_mutexes, n_mutexes);
+ }
+#endif
+
if (grn_init() != GRN_SUCCESS) {
goto err_grn_init;
}
@@ -1335,7 +1502,9 @@ static int mrn_init(void *p)
if (mrn_change_encoding(ctx, system_charset_info))
goto err_mrn_change_encoding;
- if (pthread_mutex_init(&mrn_log_mutex, NULL) != 0) {
+ if (mysql_mutex_init(mrn_log_mutex_key,
+ &mrn_log_mutex,
+ MY_MUTEX_INIT_FAST) != 0) {
goto err_log_mutex_init;
}
@@ -1358,25 +1527,39 @@ static int mrn_init(void *p)
grn_ctx_init(&mrn_db_manager_ctx, 0);
grn_logger_set(&mrn_db_manager_ctx, &mrn_logger);
- mrn_db_manager = new mrn::DatabaseManager(&mrn_db_manager_ctx);
+ if (mysql_mutex_init(mrn_db_manager_mutex_key,
+ &mrn_db_manager_mutex,
+ MY_MUTEX_INIT_FAST) != 0) {
+ GRN_LOG(&mrn_db_manager_ctx, GRN_LOG_ERROR,
+ "failed to initialize mutex for database manager");
+ goto err_db_manager_mutex_init;
+ }
+ mrn_db_manager = new mrn::DatabaseManager(&mrn_db_manager_ctx,
+ &mrn_db_manager_mutex);
if (!mrn_db_manager->init()) {
goto err_db_manager_init;
}
- if ((pthread_mutex_init(&mrn_allocated_thds_mutex, NULL) != 0)) {
+ if ((mysql_mutex_init(mrn_allocated_thds_mutex_key,
+ &mrn_allocated_thds_mutex,
+ MY_MUTEX_INIT_FAST) != 0)) {
goto err_allocated_thds_mutex_init;
}
if (my_hash_init(&mrn_allocated_thds, system_charset_info, 32, 0, 0,
mrn_allocated_thds_get_key, 0, 0)) {
goto error_allocated_thds_hash_init;
}
- if ((pthread_mutex_init(&mrn_open_tables_mutex, NULL) != 0)) {
+ if ((mysql_mutex_init(mrn_open_tables_mutex_key,
+ &mrn_open_tables_mutex,
+ MY_MUTEX_INIT_FAST) != 0)) {
goto err_allocated_open_tables_mutex_init;
}
if (my_hash_init(&mrn_open_tables, system_charset_info, 32, 0, 0,
mrn_open_tables_get_key, 0, 0)) {
goto error_allocated_open_tables_hash_init;
}
- if ((pthread_mutex_init(&mrn_long_term_share_mutex, NULL) != 0)) {
+ if ((mysql_mutex_init(mrn_long_term_share_mutex_key,
+ &mrn_long_term_share_mutex,
+ MY_MUTEX_INIT_FAST) != 0)) {
goto error_allocated_long_term_share_mutex_init;
}
if (my_hash_init(&mrn_long_term_share, system_charset_info, 32, 0, 0,
@@ -1391,18 +1574,20 @@ static int mrn_init(void *p)
return 0;
error_allocated_long_term_share_hash_init:
- pthread_mutex_destroy(&mrn_long_term_share_mutex);
+ mysql_mutex_destroy(&mrn_long_term_share_mutex);
error_allocated_long_term_share_mutex_init:
my_hash_free(&mrn_open_tables);
error_allocated_open_tables_hash_init:
- pthread_mutex_destroy(&mrn_open_tables_mutex);
+ mysql_mutex_destroy(&mrn_open_tables_mutex);
err_allocated_open_tables_mutex_init:
my_hash_free(&mrn_allocated_thds);
error_allocated_thds_hash_init:
- pthread_mutex_destroy(&mrn_allocated_thds_mutex);
+ mysql_mutex_destroy(&mrn_allocated_thds_mutex);
err_allocated_thds_mutex_init:
err_db_manager_init:
delete mrn_db_manager;
+ mysql_mutex_destroy(&mrn_db_manager_mutex);
+err_db_manager_mutex_init:
grn_ctx_fin(&mrn_db_manager_ctx);
grn_obj_unlink(ctx, mrn_db);
err_db_create:
@@ -1411,7 +1596,7 @@ err_db_create:
mrn_log_file_opened = false;
}
err_log_file_open:
- pthread_mutex_destroy(&mrn_log_mutex);
+ mysql_mutex_destroy(&mrn_log_mutex);
err_log_mutex_init:
err_mrn_change_encoding:
grn_ctx_fin(ctx);
@@ -1450,12 +1635,13 @@ static int mrn_deinit(void *p)
}
my_hash_free(&mrn_long_term_share);
- pthread_mutex_destroy(&mrn_long_term_share_mutex);
+ mysql_mutex_destroy(&mrn_long_term_share_mutex);
my_hash_free(&mrn_open_tables);
- pthread_mutex_destroy(&mrn_open_tables_mutex);
+ mysql_mutex_destroy(&mrn_open_tables_mutex);
my_hash_free(&mrn_allocated_thds);
- pthread_mutex_destroy(&mrn_allocated_thds_mutex);
+ mysql_mutex_destroy(&mrn_allocated_thds_mutex);
delete mrn_db_manager;
+ mysql_mutex_destroy(&mrn_db_manager_mutex);
grn_ctx_fin(&mrn_db_manager_ctx);
grn_obj_unlink(ctx, mrn_db);
@@ -1466,7 +1652,7 @@ static int mrn_deinit(void *p)
fclose(mrn_log_file);
mrn_log_file_opened = false;
}
- pthread_mutex_destroy(&mrn_log_mutex);
+ mysql_mutex_destroy(&mrn_log_mutex);
return 0;
}
@@ -1489,6 +1675,18 @@ mrn_declare_plugin(MRN_PLUGIN_NAME)
i_s_mrn_stats
mrn_declare_plugin_end;
+static double mrn_get_score_value(grn_obj *score)
+{
+ MRN_DBUG_ENTER_FUNCTION();
+ double score_value;
+ if (score->header.domain == GRN_DB_FLOAT) {
+ score_value = GRN_FLOAT_VALUE(score);
+ } else {
+ score_value = (double)GRN_INT32_VALUE(score);
+ }
+ DBUG_RETURN(score_value);
+}
+
static void mrn_generic_ft_clear(FT_INFO *handler)
{
MRN_DBUG_ENTER_FUNCTION();
@@ -1555,7 +1753,7 @@ static float mrn_wrapper_ft_find_relevance(FT_INFO *handler, uchar *record,
GRN_BULK_REWIND(&(info->score));
grn_obj_get_value(info->ctx, info->score_column,
result_record_id, &(info->score));
- score = (float)GRN_INT32_VALUE(&(info->score));
+ score = mrn_get_score_value(&(info->score));
}
}
@@ -1593,7 +1791,7 @@ static float mrn_wrapper_ft_get_relevance(FT_INFO *handler)
GRN_BULK_REWIND(&(info->score));
grn_obj_get_value(info->ctx, info->score_column,
result_record_id, &(info->score));
- score = (float)GRN_INT32_VALUE(&(info->score));
+ score = mrn_get_score_value(&(info->score));
}
}
@@ -1640,7 +1838,7 @@ static float mrn_storage_ft_find_relevance(FT_INFO *handler, uchar *record,
GRN_BULK_REWIND(&(info->score));
grn_obj_get_value(info->ctx, info->score_column,
result_record_id, &(info->score));
- score = (float)GRN_INT32_VALUE(&(info->score));
+ score = mrn_get_score_value(&(info->score));
}
}
DBUG_PRINT("info", ("mroonga: record_id=%d score=%g",
@@ -1672,7 +1870,7 @@ static float mrn_storage_ft_get_relevance(FT_INFO *handler)
GRN_BULK_REWIND(&(info->score));
grn_obj_get_value(info->ctx, info->score_column,
result_record_id, &(info->score));
- score = (float)GRN_INT32_VALUE(&(info->score));
+ score = mrn_get_score_value(&(info->score));
}
}
DBUG_PRINT("info",
@@ -1916,7 +2114,6 @@ ha_mroonga::ha_mroonga(handlerton *hton, TABLE_SHARE *share_arg)
grn_column_ranges(NULL),
grn_index_tables(NULL),
grn_index_columns(NULL),
- grn_table_is_referenced(false),
grn_source_column_geo(NULL),
cursor_geo(NULL),
@@ -2126,7 +2323,7 @@ uint ha_mroonga::wrapper_max_supported_key_length() const
uint ha_mroonga::storage_max_supported_key_length() const
{
MRN_DBUG_ENTER_METHOD();
- DBUG_RETURN(HA_MAX_REC_LENGTH);
+ DBUG_RETURN(GRN_TABLE_MAX_KEY_SIZE);
}
uint ha_mroonga::max_supported_key_length() const
@@ -2173,7 +2370,7 @@ uint ha_mroonga::wrapper_max_supported_key_part_length() const
uint ha_mroonga::storage_max_supported_key_part_length() const
{
MRN_DBUG_ENTER_METHOD();
- DBUG_RETURN(HA_MAX_REC_LENGTH);
+ DBUG_RETURN(GRN_TABLE_MAX_KEY_SIZE);
}
uint ha_mroonga::max_supported_key_part_length() const
@@ -2467,7 +2664,7 @@ int ha_mroonga::wrapper_create(const char *name, TABLE *table,
share = NULL;
if (wrap_key_info)
{
- my_free(wrap_key_info, MYF(0));
+ my_free(wrap_key_info);
wrap_key_info = NULL;
}
base_key_info = NULL;
@@ -2486,7 +2683,7 @@ int ha_mroonga::wrapper_create(const char *name, TABLE *table,
if (wrap_key_info)
{
- my_free(wrap_key_info, MYF(0));
+ my_free(wrap_key_info);
wrap_key_info = NULL;
}
base_key_info = NULL;
@@ -2838,9 +3035,9 @@ int ha_mroonga::storage_create(const char *name, TABLE *table,
if (key_parts == 1) {
grn_obj *normalizer = NULL;
if (tmp_share->normalizer) {
- normalizer = grn_ctx_get(ctx,
- tmp_share->normalizer,
- tmp_share->normalizer_length);
+ normalizer = grn_ctx_get(ctx,
+ tmp_share->normalizer,
+ tmp_share->normalizer_length);
} else {
Field *field = &(key_info.key_part->field[0]);
if (should_normalize(field)) {
@@ -2902,12 +3099,10 @@ int ha_mroonga::storage_create(const char *name, TABLE *table,
grn_obj_flags col_flags = GRN_OBJ_PERSISTENT;
if (tmp_share->col_flags[i]) {
- // TODO: parse flags
- if (strcmp(tmp_share->col_flags[i], "COLUMN_VECTOR") == 0) {
- col_flags |= GRN_OBJ_COLUMN_VECTOR;
- } else {
- col_flags |= GRN_OBJ_COLUMN_SCALAR;
- }
+ col_flags |= mrn_parse_grn_column_create_flags(ha_thd(),
+ ctx,
+ tmp_share->col_flags[i],
+ tmp_share->col_flags_length[i]);
} else {
col_flags |= GRN_OBJ_COLUMN_SCALAR;
}
@@ -3448,7 +3643,8 @@ int ha_mroonga::storage_create_indexes(TABLE *table, const char *grn_table_name,
}
if (error) {
while (true) {
- if (index_tables[i]) {
+ if (index_tables[i] &&
+ !(tmp_share->index_table && tmp_share->index_table[i])) {
grn_obj_remove(ctx, index_tables[i]);
}
if (!i)
@@ -3574,7 +3770,7 @@ int ha_mroonga::wrapper_open(const char *name, int mode, uint test_if_locked)
MRN_SET_BASE_TABLE_KEY(this, table);
if (wrap_key_info)
{
- my_free(wrap_key_info, MYF(0));
+ my_free(wrap_key_info);
wrap_key_info = NULL;
}
base_key_info = NULL;
@@ -3598,7 +3794,7 @@ int ha_mroonga::wrapper_open(const char *name, int mode, uint test_if_locked)
MRN_SET_BASE_TABLE_KEY(this, table);
if (wrap_key_info)
{
- my_free(wrap_key_info, MYF(0));
+ my_free(wrap_key_info);
wrap_key_info = NULL;
}
base_key_info = NULL;
@@ -3626,7 +3822,7 @@ int ha_mroonga::wrapper_open(const char *name, int mode, uint test_if_locked)
wrap_handler = NULL;
if (wrap_key_info)
{
- my_free(wrap_key_info, MYF(0));
+ my_free(wrap_key_info);
wrap_key_info = NULL;
}
base_key_info = NULL;
@@ -3806,55 +4002,6 @@ int ha_mroonga::storage_open(const char *name, int mode, uint test_if_locked)
DBUG_RETURN(0);
}
-void ha_mroonga::update_grn_table_is_referenced()
-{
- MRN_DBUG_ENTER_METHOD();
-
- grn_table_is_referenced = false;
-
- grn_table_cursor *cursor;
- int flags = GRN_CURSOR_BY_ID | GRN_CURSOR_ASCENDING;;
- cursor = grn_table_cursor_open(ctx, grn_ctx_db(ctx),
- NULL, 0,
- NULL, 0,
- 0, -1, flags);
- if (cursor) {
- grn_id id;
- grn_id grn_table_id;
-
- grn_table_id = grn_obj_id(ctx, grn_table);
- while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) {
- grn_obj *object;
- grn_id range = GRN_ID_NIL;
-
- object = grn_ctx_at(ctx, id);
- if (!object) {
- ctx->rc = GRN_SUCCESS;
- continue;
- }
-
- switch (object->header.type) {
- case GRN_COLUMN_FIX_SIZE:
- case GRN_COLUMN_VAR_SIZE:
- range = grn_obj_get_range(ctx, object);
- break;
- default:
- break;
- }
- grn_obj_unlink(ctx, object);
-
- if (range == grn_table_id) {
- grn_table_is_referenced = true;
- break;
- }
- }
-
- grn_table_cursor_close(ctx, cursor);
- }
-
- DBUG_VOID_RETURN;
-}
-
int ha_mroonga::open_table(const char *name)
{
int error;
@@ -3881,8 +4028,6 @@ int ha_mroonga::open_table(const char *name)
DBUG_RETURN(error);
}
- update_grn_table_is_referenced();
-
DBUG_RETURN(0);
}
@@ -4104,7 +4249,7 @@ int ha_mroonga::wrapper_close()
wrap_handler = NULL;
if (wrap_key_info)
{
- my_free(wrap_key_info, MYF(0));
+ my_free(wrap_key_info);
wrap_key_info = NULL;
}
base_key_info = NULL;
@@ -4323,7 +4468,6 @@ int ha_mroonga::delete_table(const char *name)
}
if (!tmp_table_share)
{
- mrn::PathMapper mapper(name);
#ifdef MRN_TABLE_LIST_INIT_REQUIRE_ALIAS
table_list.init_one_table(mapper.db_name(), strlen(mapper.db_name()),
mapper.mysql_table_name(),
@@ -5090,6 +5234,7 @@ int ha_mroonga::storage_write_row(uchar *buf)
{
MRN_DBUG_ENTER_METHOD();
int error = 0;
+ bool unique_indexes_are_processed = false;
if (is_dry_write()) {
DBUG_PRINT("info", ("mroonga: dry write: ha_mroonga::%s", __FUNCTION__));
@@ -5098,7 +5243,6 @@ int ha_mroonga::storage_write_row(uchar *buf)
THD *thd = ha_thd();
int i;
- uint j;
int n_columns = table->s->fields;
if (table->next_number_field && buf == table->record[0])
@@ -5156,6 +5300,11 @@ int ha_mroonga::storage_write_row(uchar *buf)
}
}
+ if (grn_table->header.type != GRN_TABLE_NO_KEY && pkey_size == 0) {
+ my_message(ER_ERROR_ON_WRITE, "primary key is empty", MYF(0));
+ DBUG_RETURN(ER_ERROR_ON_WRITE);
+ }
+
int added;
record_id = grn_table_add(ctx, grn_table, pkey, pkey_size, &added);
if (ctx->rc) {
@@ -5179,6 +5328,7 @@ int ha_mroonga::storage_write_row(uchar *buf)
{
goto err;
}
+ unique_indexes_are_processed = true;
grn_obj colbuf;
GRN_VOID_INIT(&colbuf);
@@ -5270,13 +5420,16 @@ int ha_mroonga::storage_write_row(uchar *buf)
DBUG_RETURN(0);
err:
- for (j = 0; j < table->s->keys; j++) {
- if (j == pkey_nr) {
- continue;
- }
- KEY *key_info = &table->key_info[j];
- if (key_info->flags & HA_NOSAME) {
- grn_table_delete_by_id(ctx, grn_index_tables[j], key_id[j]);
+ if (unique_indexes_are_processed) {
+ uint j;
+ for (j = 0; j < table->s->keys; j++) {
+ if (j == pkey_nr) {
+ continue;
+ }
+ KEY *key_info = &table->key_info[j];
+ if (key_info->flags & HA_NOSAME) {
+ grn_table_delete_by_id(ctx, grn_index_tables[j], key_id[j]);
+ }
}
}
grn_table_delete_by_id(ctx, grn_table, record_id);
@@ -5363,6 +5516,7 @@ err:
int ha_mroonga::storage_write_row_unique_index(uchar *buf,
KEY *key_info,
grn_obj *index_table,
+ grn_obj *index_column,
grn_id *key_id)
{
char *ukey = NULL;
@@ -5398,7 +5552,29 @@ int ha_mroonga::storage_write_row_unique_index(uchar *buf,
if (!added) {
// duplicated error
error = HA_ERR_FOUND_DUPP_KEY;
- memcpy(dup_ref, key_id, sizeof(grn_id));
+ grn_id duplicated_record_id = GRN_ID_NIL;
+ {
+ grn_table_cursor *table_cursor;
+ table_cursor = grn_table_cursor_open(ctx, index_table,
+ ukey, ukey_size,
+ ukey, ukey_size,
+ 0, -1, 0);
+ if (table_cursor) {
+ grn_obj *index_cursor;
+ index_cursor = grn_index_cursor_open(ctx, table_cursor, index_column,
+ GRN_ID_NIL, GRN_ID_MAX, 0);
+ if (index_cursor) {
+ grn_posting *posting;
+ posting = grn_index_cursor_next(ctx, index_cursor, NULL);
+ if (posting) {
+ duplicated_record_id = posting->rid;
+ }
+ }
+ grn_obj_unlink(ctx, index_cursor);
+ }
+ grn_table_cursor_close(ctx, table_cursor);
+ }
+ memcpy(dup_ref, &duplicated_record_id, sizeof(grn_id));
if (!ignoring_duplicated_key) {
GRN_LOG(ctx, GRN_LOG_ERROR,
"duplicated id on insert: update unique index: <%.*s>",
@@ -5431,9 +5607,14 @@ int ha_mroonga::storage_write_row_unique_indexes(uchar *buf)
if (!index_table) {
continue;
}
+ grn_obj *index_column = grn_index_columns[i];
+ if (!index_column) {
+ continue;
+ }
if ((error = storage_write_row_unique_index(buf, key_info,
- index_table, &key_id[i])))
+ index_table, index_column,
+ &key_id[i])))
{
if (error == HA_ERR_FOUND_DUPP_KEY)
{
@@ -5449,7 +5630,16 @@ err:
mrn_change_encoding(ctx, NULL);
do {
i--;
+
+ if (i == table->s->primary_key) {
+ continue;
+ }
+
KEY *key_info = &table->key_info[i];
+ if (!(key_info->flags & HA_NOSAME)) {
+ continue;
+ }
+
if (key_info->flags & HA_NOSAME) {
grn_table_delete_by_id(ctx, grn_index_tables[i], key_id[i]);
}
@@ -5914,6 +6104,13 @@ int ha_mroonga::storage_update_row_unique_indexes(uchar *new_data)
continue;
}
+ grn_obj *index_column = grn_index_columns[i];
+ if (!index_column) {
+ key_id[i] = GRN_ID_NIL;
+ del_key_id[i] = GRN_ID_NIL;
+ continue;
+ }
+
if (
KEY_N_KEY_PARTS(key_info) == 1 &&
!bitmap_is_set(table->write_set,
@@ -5926,7 +6123,8 @@ int ha_mroonga::storage_update_row_unique_indexes(uchar *new_data)
}
if ((error = storage_write_row_unique_index(new_data, key_info,
- index_table, &key_id[i])))
+ index_table, index_column,
+ &key_id[i])))
{
if (error == HA_ERR_FOUND_DUPP_KEY)
{
@@ -6276,24 +6474,34 @@ int ha_mroonga::delete_row(const uchar *buf)
DBUG_RETURN(error);
}
-uint ha_mroonga::wrapper_max_supported_key_parts()
+uint ha_mroonga::wrapper_max_supported_key_parts() const
{
MRN_DBUG_ENTER_METHOD();
DBUG_RETURN(MAX_REF_PARTS);
}
-uint ha_mroonga::storage_max_supported_key_parts()
+uint ha_mroonga::storage_max_supported_key_parts() const
{
MRN_DBUG_ENTER_METHOD();
- DBUG_RETURN(1);
+ DBUG_RETURN(MAX_REF_PARTS);
}
-uint ha_mroonga::max_supported_key_parts()
+uint ha_mroonga::max_supported_key_parts() const
{
MRN_DBUG_ENTER_METHOD();
uint parts;
- if (share->wrapper_mode)
- {
+ if (!share && !analyzed_for_create &&
+ (
+ thd_sql_command(ha_thd()) == SQLCOM_CREATE_TABLE ||
+ thd_sql_command(ha_thd()) == SQLCOM_CREATE_INDEX ||
+ thd_sql_command(ha_thd()) == SQLCOM_ALTER_TABLE
+ )
+ ) {
+ create_share_for_create();
+ }
+ if (analyzed_for_create && share_for_create.wrapper_mode) {
+ parts = wrapper_max_supported_key_parts();
+ } else if (wrap_handler && share && share->wrapper_mode) {
parts = wrapper_max_supported_key_parts();
} else {
parts = storage_max_supported_key_parts();
@@ -7594,6 +7802,34 @@ bool ha_mroonga::generic_ft_init_ext_parse_pragma_w(struct st_mrn_ft_info *info,
DBUG_RETURN(n_weights > 0);
}
+grn_expr_flags ha_mroonga::expr_flags_in_boolean_mode()
+{
+ MRN_DBUG_ENTER_METHOD();
+
+ ulonglong syntax_flags = THDVAR(ha_thd(), boolean_mode_syntax_flags);
+ grn_expr_flags expression_flags = 0;
+ if (syntax_flags == MRN_BOOLEAN_MODE_SYNTAX_FLAG_DEFAULT) {
+ expression_flags = GRN_EXPR_SYNTAX_QUERY | GRN_EXPR_ALLOW_LEADING_NOT;
+ } else {
+ if (syntax_flags & MRN_BOOLEAN_MODE_SYNTAX_FLAG_SYNTAX_SCRIPT) {
+ expression_flags |= GRN_EXPR_SYNTAX_SCRIPT;
+ } else {
+ expression_flags |= GRN_EXPR_SYNTAX_QUERY;
+ }
+ if (syntax_flags & MRN_BOOLEAN_MODE_SYNTAX_FLAG_ALLOW_COLUMN) {
+ expression_flags |= GRN_EXPR_ALLOW_COLUMN;
+ }
+ if (syntax_flags & MRN_BOOLEAN_MODE_SYNTAX_FLAG_ALLOW_UPDATE) {
+ expression_flags |= GRN_EXPR_ALLOW_UPDATE;
+ }
+ if (syntax_flags & MRN_BOOLEAN_MODE_SYNTAX_FLAG_ALLOW_LEADING_NOT) {
+ expression_flags |= GRN_EXPR_ALLOW_LEADING_NOT;
+ }
+ }
+
+ DBUG_RETURN(expression_flags);
+}
+
grn_rc ha_mroonga::generic_ft_init_ext_prepare_expression_in_boolean_mode(
struct st_mrn_ft_info *info,
String *key,
@@ -7674,12 +7910,10 @@ grn_rc ha_mroonga::generic_ft_init_ext_prepare_expression_in_boolean_mode(
if (!weight_specified) {
grn_expr_append_obj(info->ctx, match_columns, index_column, GRN_OP_PUSH, 1);
}
- grn_expr_flags expression_flags =
- GRN_EXPR_SYNTAX_QUERY | GRN_EXPR_ALLOW_LEADING_NOT;
rc = grn_expr_parse(info->ctx, expression,
keyword, keyword_length,
match_columns, GRN_OP_MATCH, default_operator,
- expression_flags);
+ expr_flags_in_boolean_mode());
if (rc) {
char error_message[MRN_MESSAGE_BUFFER_SIZE];
snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
@@ -8351,7 +8585,8 @@ int ha_mroonga::drop_index(MRN_SHARE *target_share, uint key_index)
const char *table_name = target_share->index_table[key_index];
snprintf(target_name, GRN_TABLE_MAX_KEY_SIZE,
"%s.%s", table_name, key_info[key_index].name);
- grn_obj *index_column = grn_ctx_get(ctx, target_name, strlen(target_name));
+ target_name_length = strlen(target_name);
+ grn_obj *index_column = grn_ctx_get(ctx, target_name, target_name_length);
if (index_column) {
rc = grn_obj_remove(ctx, index_column);
}
@@ -8366,6 +8601,8 @@ int ha_mroonga::drop_index(MRN_SHARE *target_share, uint key_index)
target_name_length = grn_obj_name(ctx, index_table,
target_name, GRN_TABLE_MAX_KEY_SIZE);
rc = grn_obj_remove(ctx, index_table);
+ } else {
+ target_name_length = 0;
}
}
@@ -8421,6 +8658,7 @@ grn_obj *ha_mroonga::find_normalizer(KEY *key_info)
{
MRN_DBUG_ENTER_METHOD();
grn_obj *normalizer = NULL;
+ bool use_normalizer = true;
#if MYSQL_VERSION_ID >= 50500
if (key_info->comment.length > 0) {
mrn::ParametersParser parser(key_info->comment.str,
@@ -8428,11 +8666,15 @@ grn_obj *ha_mroonga::find_normalizer(KEY *key_info)
parser.parse();
const char *normalizer_name = parser["normalizer"];
if (normalizer_name) {
- normalizer = grn_ctx_get(ctx, normalizer_name, -1);
+ if (strcmp(normalizer_name, "none") == 0) {
+ use_normalizer = false;
+ } else {
+ normalizer = grn_ctx_get(ctx, normalizer_name, -1);
+ }
}
}
#endif
- if (!normalizer) {
+ if (use_normalizer && !normalizer) {
Field *field = key_info->key_part[0].field;
mrn::FieldNormalizer field_normalizer(ctx, ha_thd(), field);
normalizer = field_normalizer.find_grn_normalizer();
@@ -9438,9 +9680,9 @@ int ha_mroonga::generic_store_bulk_blob(Field *field, grn_obj *buf)
int error = 0;
String buffer;
Field_blob *blob = (Field_blob *)field;
- const char *value = blob->val_str(0, &buffer)->ptr();
+ String *value = blob->val_str(0, &buffer);
grn_obj_reinit(ctx, buf, GRN_DB_TEXT, 0);
- GRN_TEXT_SET(ctx, buf, value, blob->get_length());
+ GRN_TEXT_SET(ctx, buf, value->ptr(), value->length());
DBUG_RETURN(error);
}
@@ -9451,8 +9693,9 @@ int ha_mroonga::generic_store_bulk_geometry(Field *field, grn_obj *buf)
#ifdef HAVE_SPATIAL
String buffer;
Field_geom *geometry = (Field_geom *)field;
- const char *wkb = geometry->val_str(0, &buffer)->ptr();
- int len = geometry->get_length();
+ String *value = geometry->val_str(0, &buffer);
+ const char *wkb = value->ptr();
+ int len = value->length();
error = mrn_set_geometry(ctx, buf, wkb, len);
#endif
DBUG_RETURN(error);
@@ -9994,7 +10237,7 @@ void ha_mroonga::storage_store_field(Field *field,
}
}
-void ha_mroonga::storage_store_field_column(Field *field,
+void ha_mroonga::storage_store_field_column(Field *field, bool is_primary_key,
int nth_column, grn_id record_id)
{
MRN_DBUG_ENTER_METHOD();
@@ -10009,7 +10252,6 @@ void ha_mroonga::storage_store_field_column(Field *field,
grn_obj_reinit(ctx, value, range_id, GRN_OBJ_VECTOR);
grn_obj_get_value(ctx, column, record_id, value);
- // TODO: Check whether reference type or not
grn_obj unvectored_value;
GRN_TEXT_INIT(&unvectored_value, 0);
int n_ids = GRN_BULK_VSIZE(value) / sizeof(grn_id);
@@ -10042,7 +10284,15 @@ void ha_mroonga::storage_store_field_column(Field *field,
} else {
grn_obj_reinit(ctx, value, range_id, 0);
grn_obj_get_value(ctx, column, record_id, value);
- storage_store_field(field, GRN_BULK_HEAD(value), GRN_BULK_VSIZE(value));
+ if (is_primary_key && GRN_BULK_VSIZE(value) == 0) {
+ char key[GRN_TABLE_MAX_KEY_SIZE];
+ int key_length;
+ key_length = grn_table_get_key(ctx, grn_table, record_id,
+ &key, GRN_TABLE_MAX_KEY_SIZE);
+ storage_store_field(field, key, key_length);
+ } else {
+ storage_store_field(field, GRN_BULK_HEAD(value), GRN_BULK_VSIZE(value));
+ }
}
DBUG_VOID_RETURN;
@@ -10056,9 +10306,11 @@ void ha_mroonga::storage_store_fields(uchar *buf, grn_id record_id)
my_ptrdiff_t ptr_diff = PTR_BYTE_DIFF(buf, table->record[0]);
Field *primary_key_field = NULL;
- if (grn_table_is_referenced && table->s->primary_key != MAX_INDEXES) {
+ if (table->s->primary_key != MAX_INDEXES) {
KEY *key_info = &(table->s->key_info[table->s->primary_key]);
- primary_key_field = key_info->key_part[0].field;
+ if (KEY_N_KEY_PARTS(key_info) == 1) {
+ primary_key_field = key_info->key_part[0].field;
+ }
}
int i;
@@ -10087,13 +10339,9 @@ void ha_mroonga::storage_store_fields(uchar *buf, grn_id record_id)
} else if (primary_key_field &&
strcmp(primary_key_field->field_name, column_name) == 0) {
// for primary key column
- char key[GRN_TABLE_MAX_KEY_SIZE];
- int key_length;
- key_length = grn_table_get_key(ctx, grn_table, record_id,
- &key, GRN_TABLE_MAX_KEY_SIZE);
- storage_store_field(field, key, key_length);
+ storage_store_field_column(field, true, i, record_id);
} else {
- storage_store_field_column(field, i ,record_id);
+ storage_store_field_column(field, false, i, record_id);
}
field->move_field_offset(-ptr_diff);
}
@@ -10770,12 +11018,12 @@ int ha_mroonga::wrapper_reset()
MRN_SET_BASE_TABLE_KEY(this, table);
#ifdef MRN_HANDLER_HAVE_CHECK_IF_SUPPORTED_INPLACE_ALTER
if (alter_key_info_buffer) {
- my_free(alter_key_info_buffer, MYF(0));
+ my_free(alter_key_info_buffer);
alter_key_info_buffer = NULL;
}
#else
if (wrap_alter_key_info) {
- my_free(wrap_alter_key_info, MYF(0));
+ my_free(wrap_alter_key_info);
wrap_alter_key_info = NULL;
}
#endif
@@ -11787,7 +12035,7 @@ void ha_mroonga::update_create_info(HA_CREATE_INFO* create_info)
if (slot_data) {
slot_data->alter_create_info = create_info;
if (slot_data->alter_connect_string) {
- my_free(slot_data->alter_connect_string, MYF(0));
+ my_free(slot_data->alter_connect_string);
slot_data->alter_connect_string = NULL;
}
if (create_info->connect_string.str) {
@@ -11797,7 +12045,7 @@ void ha_mroonga::update_create_info(HA_CREATE_INFO* create_info)
MYF(MY_WME));
}
if (slot_data->alter_comment) {
- my_free(slot_data->alter_comment, MYF(0));
+ my_free(slot_data->alter_comment);
slot_data->alter_comment = NULL;
}
if (create_info->comment.str) {
@@ -12184,6 +12432,44 @@ bool ha_mroonga::auto_repair() const
DBUG_RETURN(crashed);
}
+int ha_mroonga::generic_disable_index(int i, KEY *key_info)
+{
+ MRN_DBUG_ENTER_METHOD();
+
+ int error = 0;
+ if (share->index_table[i]) {
+ char index_column_name[GRN_TABLE_MAX_KEY_SIZE];
+ snprintf(index_column_name, GRN_TABLE_MAX_KEY_SIZE - 1,
+ "%s.%s", share->index_table[i], key_info[i].name);
+ grn_obj *index_column = grn_ctx_get(ctx,
+ index_column_name,
+ strlen(index_column_name));
+ if (index_column) {
+ grn_obj_remove(ctx, index_column);
+ }
+ } else {
+ mrn::PathMapper mapper(share->table_name);
+ mrn::IndexTableName index_table_name(mapper.table_name(),
+ key_info[i].name);
+ grn_obj *index_table = grn_ctx_get(ctx,
+ index_table_name.c_str(),
+ index_table_name.length());
+ if (index_table) {
+ grn_obj_remove(ctx, index_table);
+ }
+ }
+ if (ctx->rc == GRN_SUCCESS) {
+ grn_index_tables[i] = NULL;
+ grn_index_columns[i] = NULL;
+ } else {
+ // TODO: Implement ctx->rc to error converter and use it.
+ error = ER_ERROR_ON_WRITE;
+ my_message(error, ctx->errbuf, MYF(0));
+ }
+
+ DBUG_RETURN(error);
+}
+
int ha_mroonga::wrapper_disable_indexes(uint mode)
{
int error = 0;
@@ -12212,23 +12498,16 @@ int ha_mroonga::wrapper_disable_indexes(uint mode)
}
}
KEY *key_info = table_share->key_info;
- mrn::PathMapper mapper(share->table_name);
for (i = 0; i < table_share->keys; i++) {
if (!(key_info[i].flags & HA_FULLTEXT) &&
!mrn_is_geo_key(&key_info[i])) {
continue;
}
- mrn::IndexTableName index_table_name(mapper.table_name(),
- key_info[i].name);
- grn_obj *index_table = grn_ctx_get(ctx,
- index_table_name.c_str(),
- index_table_name.length());
- if (index_table) {
- grn_obj_remove(ctx, index_table);
+ int sub_error = generic_disable_index(i, key_info);
+ if (error != 0 && sub_error != 0) {
+ error = sub_error;
}
- grn_index_tables[i] = NULL;
- grn_index_columns[i] = NULL;
}
} else {
error = HA_ERR_WRONG_COMMAND;
@@ -12239,6 +12518,7 @@ int ha_mroonga::wrapper_disable_indexes(uint mode)
int ha_mroonga::storage_disable_indexes(uint mode)
{
+ int error = 0;
MRN_DBUG_ENTER_METHOD();
if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE || mode == HA_KEY_SWITCH_ALL) {
uint i;
@@ -12252,7 +12532,6 @@ int ha_mroonga::storage_disable_indexes(uint mode)
}
}
KEY *key_info = table_share->key_info;
- mrn::PathMapper mapper(share->table_name);
for (i = 0; i < table_share->keys; i++) {
if (i == table->s->primary_key) {
continue;
@@ -12262,21 +12541,15 @@ int ha_mroonga::storage_disable_indexes(uint mode)
continue;
}
- mrn::IndexTableName index_table_name(mapper.table_name(),
- key_info[i].name);
- grn_obj *index_table = grn_ctx_get(ctx,
- index_table_name.c_str(),
- index_table_name.length());
- if (index_table) {
- grn_obj_remove(ctx, index_table);
+ int sub_error = generic_disable_index(i, key_info);
+ if (error != 0 && sub_error != 0) {
+ error = sub_error;
}
- grn_index_tables[i] = NULL;
- grn_index_columns[i] = NULL;
}
} else {
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
- DBUG_RETURN(0);
+ DBUG_RETURN(error);
}
int ha_mroonga::disable_indexes(uint mode)
@@ -12305,7 +12578,7 @@ int ha_mroonga::wrapper_enable_indexes(uint mode)
if (share->wrap_key_nr[i] < MAX_KEY) {
continue;
}
- if (!grn_index_tables[i]) {
+ if (!grn_index_columns[i]) {
break;
}
}
@@ -12334,7 +12607,7 @@ int ha_mroonga::wrapper_enable_indexes(uint mode)
}
index_tables[i] = NULL;
index_columns[i] = NULL;
- if (!grn_index_tables[i]) {
+ if (!grn_index_columns[i]) {
if (
(key_info[i].flags & HA_FULLTEXT) &&
(error = wrapper_create_index_fulltext(mapper.table_name(),
@@ -12394,7 +12667,7 @@ int ha_mroonga::storage_enable_indexes(uint mode)
if (i == table->s->primary_key) {
continue;
}
- if (!grn_index_tables[i]) {
+ if (!grn_index_columns[i]) {
break;
}
}
@@ -12420,7 +12693,7 @@ int ha_mroonga::storage_enable_indexes(uint mode)
break;
}
index_tables[i] = NULL;
- if (!grn_index_tables[i]) {
+ if (!grn_index_columns[i]) {
if ((error = storage_create_index(table, mapper.table_name(), grn_table,
share, &key_info[i], index_tables,
index_columns, i)))
@@ -12434,6 +12707,8 @@ int ha_mroonga::storage_enable_indexes(uint mode)
mrn_set_bitmap_by_key(table->read_set, &key_info[i]);
have_multiple_column_index = true;
}
+ grn_index_tables[i] = index_tables[i];
+ grn_index_columns[i] = index_columns[i];
} else {
index_columns[i] = NULL;
}
@@ -12902,6 +13177,7 @@ int ha_mroonga::storage_add_index_multiple_columns(KEY *key_info,
if ((error = storage_write_row_unique_index(table->record[0],
current_key_info,
index_tables[i],
+ index_columns[i],
&key_id)))
{
if (error == HA_ERR_FOUND_DUPP_KEY)
@@ -13308,7 +13584,7 @@ bool ha_mroonga::wrapper_inplace_alter_table(
result = true;
}
mrn_free_share_alloc(tmp_share);
- my_free(tmp_share, MYF(0));
+ my_free(tmp_share);
MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
DBUG_RETURN(result);
@@ -13434,6 +13710,12 @@ bool ha_mroonga::storage_inplace_alter_table_index(
ha_alter_info->key_count,
index_tables,
index_columns, false);
+ if (error == HA_ERR_FOUND_DUPP_UNIQUE) {
+ my_printf_error(ER_DUP_UNIQUE, ER(ER_DUP_UNIQUE), MYF(0),
+ table_share->table_name);
+ } else if (error) {
+ my_message(error, "failed to create multiple column index", MYF(0));
+ }
for (i = 0; i < n_columns; ++i) {
Field *field = altered_table->field[i];
field->move_field_offset(-ptr_diff);
@@ -13460,7 +13742,7 @@ bool ha_mroonga::storage_inplace_alter_table_index(
have_error = true;
}
mrn_free_share_alloc(tmp_share);
- my_free(tmp_share, MYF(0));
+ my_free(tmp_share);
MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
@@ -13532,12 +13814,10 @@ bool ha_mroonga::storage_inplace_alter_table_add_column(
grn_obj_flags col_flags = GRN_OBJ_PERSISTENT;
if (tmp_share->col_flags[i]) {
- // TODO: parse flags
- if (strcmp(tmp_share->col_flags[i], "COLUMN_VECTOR") == 0) {
- col_flags |= GRN_OBJ_COLUMN_VECTOR;
- } else {
- col_flags |= GRN_OBJ_COLUMN_SCALAR;
- }
+ col_flags |= mrn_parse_grn_column_create_flags(ha_thd(),
+ ctx,
+ tmp_share->col_flags[i],
+ tmp_share->col_flags_length[i]);
} else {
col_flags |= GRN_OBJ_COLUMN_SCALAR;
}
@@ -13570,7 +13850,7 @@ bool ha_mroonga::storage_inplace_alter_table_add_column(
grn_obj_unlink(ctx, table_obj);
mrn_free_share_alloc(tmp_share);
- my_free(tmp_share, MYF(0));
+ my_free(tmp_share);
DBUG_RETURN(have_error);
}
@@ -13752,7 +14032,7 @@ bool ha_mroonga::wrapper_commit_inplace_alter_table(
bool result;
MRN_DBUG_ENTER_METHOD();
if (!alter_handler_flags) {
- my_free(alter_key_info_buffer, MYF(0));
+ my_free(alter_key_info_buffer);
alter_key_info_buffer = NULL;
DBUG_RETURN(false);
}
@@ -13765,7 +14045,7 @@ bool ha_mroonga::wrapper_commit_inplace_alter_table(
MRN_SET_BASE_ALTER_KEY(this, ha_alter_info);
MRN_SET_BASE_SHARE_KEY(share, table->s);
MRN_SET_BASE_TABLE_KEY(this, table);
- my_free(alter_key_info_buffer, MYF(0));
+ my_free(alter_key_info_buffer);
alter_key_info_buffer = NULL;
DBUG_RETURN(result);
}
@@ -13990,7 +14270,7 @@ int ha_mroonga::wrapper_add_index(TABLE *table_arg, KEY *key_info,
}
#endif
mrn_free_share_alloc(tmp_share);
- my_free(tmp_share, MYF(0));
+ my_free(tmp_share);
MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
DBUG_RETURN(error);
@@ -14104,7 +14384,7 @@ int ha_mroonga::storage_add_index(TABLE *table_arg, KEY *key_info,
}
#endif
mrn_free_share_alloc(tmp_share);
- my_free(tmp_share, MYF(0));
+ my_free(tmp_share);
MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
DBUG_RETURN(error);
@@ -15277,7 +15557,7 @@ void ha_mroonga::wrapper_free_foreign_key_create_info(char* str)
void ha_mroonga::storage_free_foreign_key_create_info(char* str)
{
MRN_DBUG_ENTER_METHOD();
- my_free(str, MYF(0));
+ my_free(str);
DBUG_VOID_RETURN;
}
#else
diff --git a/storage/mroonga/ha_mroonga.hpp b/storage/mroonga/ha_mroonga.hpp
index 224abb09732..a5379dbddbb 100644
--- a/storage/mroonga/ha_mroonga.hpp
+++ b/storage/mroonga/ha_mroonga.hpp
@@ -263,7 +263,6 @@ private:
grn_obj **grn_column_ranges;
grn_obj **grn_index_tables;
grn_obj **grn_index_columns;
- bool grn_table_is_referenced;
// buffers
grn_obj encoded_key_buffer;
@@ -349,7 +348,7 @@ public:
uint max_supported_record_length() const;
uint max_supported_keys() const;
- uint max_supported_key_parts();
+ uint max_supported_key_parts() const;
uint max_supported_key_length() const;
uint max_supported_key_part_length() const;
@@ -641,7 +640,7 @@ private:
void storage_store_field_geometry(Field *field,
const char *value, uint value_length);
void storage_store_field(Field *field, const char *value, uint value_length);
- void storage_store_field_column(Field *field,
+ void storage_store_field_column(Field *field, bool is_primary_key,
int nth_column, grn_id record_id);
void storage_store_fields(uchar *buf, grn_id record_id);
void storage_store_fields_for_prep_update(const uchar *old_data,
@@ -742,7 +741,6 @@ private:
int wrapper_open(const char *name, int mode, uint test_if_locked);
int wrapper_open_indexes(const char *name);
int storage_open(const char *name, int mode, uint test_if_locked);
- void update_grn_table_is_referenced();
int open_table(const char *name);
int storage_open_columns(void);
int storage_open_indexes(const char *name);
@@ -785,7 +783,9 @@ private:
grn_obj *index_column);
int storage_write_row_multiple_column_indexes(uchar *buf, grn_id record_id);
int storage_write_row_unique_index(uchar *buf,
- KEY *key_info, grn_obj *index_table,
+ KEY *key_info,
+ grn_obj *index_table,
+ grn_obj *index_column,
grn_id *key_id);
int storage_write_row_unique_indexes(uchar *buf);
int wrapper_get_record_id(uchar *data, grn_id *record_id, const char *context);
@@ -812,8 +812,8 @@ private:
uint storage_max_supported_record_length() const;
uint wrapper_max_supported_keys() const;
uint storage_max_supported_keys() const;
- uint wrapper_max_supported_key_parts();
- uint storage_max_supported_key_parts();
+ uint wrapper_max_supported_key_parts() const;
+ uint storage_max_supported_key_parts() const;
uint wrapper_max_supported_key_length() const;
uint storage_max_supported_key_length() const;
uint wrapper_max_supported_key_part_length() const;
@@ -904,6 +904,7 @@ private:
grn_obj *match_columns,
uint *consumed_keyword_length,
grn_obj *tmp_objects);
+ grn_expr_flags expr_flags_in_boolean_mode();
grn_rc generic_ft_init_ext_prepare_expression_in_boolean_mode(
struct st_mrn_ft_info *info,
String *key,
@@ -1029,6 +1030,7 @@ private:
bool storage_is_crashed() const;
bool wrapper_auto_repair(int error) const;
bool storage_auto_repair(int error) const;
+ int generic_disable_index(int i, KEY *key_info);
int wrapper_disable_indexes(uint mode);
int storage_disable_indexes(uint mode);
int wrapper_enable_indexes(uint mode);
diff --git a/storage/mroonga/lib/mrn_database_manager.cpp b/storage/mroonga/lib/mrn_database_manager.cpp
index 52ec78fccc0..365f47337fa 100644
--- a/storage/mroonga/lib/mrn_database_manager.cpp
+++ b/storage/mroonga/lib/mrn_database_manager.cpp
@@ -26,6 +26,8 @@
#include "mrn_lock.hpp"
#include "mrn_path_mapper.hpp"
+#include <groonga/plugin.h>
+
// for debug
#define MRN_CLASS_NAME "mrn::DatabaseManager"
@@ -38,19 +40,19 @@
# define MRN_MKDIR(pathname, mode) mkdir((pathname), (mode))
#endif
+extern "C" {
+ grn_rc GRN_PLUGIN_IMPL_NAME_TAGGED(init, normalizers_mysql)(grn_ctx *ctx);
+ grn_rc GRN_PLUGIN_IMPL_NAME_TAGGED(register, normalizers_mysql)(grn_ctx *ctx);
+}
+
namespace mrn {
- DatabaseManager::DatabaseManager(grn_ctx *ctx)
+ DatabaseManager::DatabaseManager(grn_ctx *ctx, mysql_mutex_t *mutex)
: ctx_(ctx),
cache_(NULL),
- mutex_(),
- mutex_initialized_(false) {
+ mutex_(mutex) {
}
DatabaseManager::~DatabaseManager(void) {
- if (mutex_initialized_) {
- pthread_mutex_destroy(&mutex_);
- }
-
if (cache_) {
void *db_address;
GRN_HASH_EACH(ctx_, cache_, id, NULL, 0, &db_address, {
@@ -75,13 +77,6 @@ namespace mrn {
DBUG_RETURN(false);
}
- if (pthread_mutex_init(&mutex_, NULL) != 0) {
- GRN_LOG(ctx_, GRN_LOG_ERROR,
- "failed to initialize mutex for opened database cache hash table");
- DBUG_RETURN(false);
- }
-
- mutex_initialized_ = true;
DBUG_RETURN(true);
}
@@ -92,7 +87,7 @@ namespace mrn {
*db = NULL;
mrn::PathMapper mapper(path);
- mrn::Lock lock(&mutex_);
+ mrn::Lock lock(mutex_);
error = mrn::encoding::set(ctx_, system_charset_info);
if (error) {
@@ -145,7 +140,7 @@ namespace mrn {
MRN_DBUG_ENTER_METHOD();
mrn::PathMapper mapper(path);
- mrn::Lock lock(&mutex_);
+ mrn::Lock lock(mutex_);
grn_id id;
void *db_address;
@@ -171,7 +166,7 @@ namespace mrn {
MRN_DBUG_ENTER_METHOD();
mrn::PathMapper mapper(path);
- mrn::Lock lock(&mutex_);
+ mrn::Lock lock(mutex_);
grn_id id;
void *db_address;
@@ -211,7 +206,7 @@ namespace mrn {
int error = 0;
- mrn::Lock lock(&mutex_);
+ mrn::Lock lock(mutex_);
grn_hash_cursor *cursor;
cursor = grn_hash_cursor_open(ctx_, cache_,
@@ -323,15 +318,12 @@ namespace mrn {
if (mysql_normalizer) {
grn_obj_unlink(ctx_, mysql_normalizer);
} else {
-#ifdef GROONGA_NORMALIZER_MYSQL_PLUGIN_IS_BUNDLED_STATIC
- char ref_path[FN_REFLEN + 1], *tmp;
- tmp = strmov(ref_path, opt_plugin_dir);
- tmp = strmov(tmp, "/ha_mroonga");
- strcpy(tmp, SO_EXT);
- grn_plugin_register_by_path(ctx_, ref_path);
-#else
+# ifdef MRN_GROONGA_NORMALIZER_MYSQL_EMBED
+ GRN_PLUGIN_IMPL_NAME_TAGGED(init, normalizers_mysql)(ctx_);
+ GRN_PLUGIN_IMPL_NAME_TAGGED(register, normalizers_mysql)(ctx_);
+# else
grn_plugin_register(ctx_, GROONGA_NORMALIZER_MYSQL_PLUGIN_NAME);
-#endif
+# endif
}
}
#endif
diff --git a/storage/mroonga/lib/mrn_database_manager.hpp b/storage/mroonga/lib/mrn_database_manager.hpp
index 46bce7ab1a5..76c76dab6d5 100644
--- a/storage/mroonga/lib/mrn_database_manager.hpp
+++ b/storage/mroonga/lib/mrn_database_manager.hpp
@@ -27,7 +27,7 @@
namespace mrn {
class DatabaseManager {
public:
- DatabaseManager(grn_ctx *ctx);
+ DatabaseManager(grn_ctx *ctx, mysql_mutex_t *mutex);
~DatabaseManager(void);
bool init(void);
int open(const char *path, grn_obj **db);
@@ -38,8 +38,7 @@ namespace mrn {
private:
grn_ctx *ctx_;
grn_hash *cache_;
- pthread_mutex_t mutex_;
- bool mutex_initialized_;
+ mysql_mutex_t *mutex_;
void mkdir_p(const char *directory);
void ensure_database_directory(void);
diff --git a/storage/mroonga/lib/mrn_lock.cpp b/storage/mroonga/lib/mrn_lock.cpp
index 94f8a4774af..3340149b237 100644
--- a/storage/mroonga/lib/mrn_lock.cpp
+++ b/storage/mroonga/lib/mrn_lock.cpp
@@ -20,12 +20,12 @@
#include "mrn_lock.hpp"
namespace mrn {
- Lock::Lock(pthread_mutex_t *mutex)
+ Lock::Lock(mysql_mutex_t *mutex)
: mutex_(mutex) {
- pthread_mutex_lock(mutex_);
+ mysql_mutex_lock(mutex_);
}
Lock::~Lock() {
- pthread_mutex_unlock(mutex_);
+ mysql_mutex_unlock(mutex_);
}
}
diff --git a/storage/mroonga/lib/mrn_lock.hpp b/storage/mroonga/lib/mrn_lock.hpp
index 31dd7b3e53b..08e47b39c58 100644
--- a/storage/mroonga/lib/mrn_lock.hpp
+++ b/storage/mroonga/lib/mrn_lock.hpp
@@ -26,10 +26,10 @@
namespace mrn {
class Lock {
public:
- Lock(pthread_mutex_t *mutex);
+ Lock(mysql_mutex_t *mutex);
~Lock();
private:
- pthread_mutex_t *mutex_;
+ mysql_mutex_t *mutex_;
};
}
diff --git a/storage/mroonga/lib/mrn_parameters_parser.cpp b/storage/mroonga/lib/mrn_parameters_parser.cpp
index 9a05097e548..3edf910ee91 100644
--- a/storage/mroonga/lib/mrn_parameters_parser.cpp
+++ b/storage/mroonga/lib/mrn_parameters_parser.cpp
@@ -35,10 +35,10 @@ namespace mrn {
};
~Parameter() {
if (key_) {
- my_free(key_, MYF(0));
+ my_free(key_);
}
if (value_) {
- my_free(value_, MYF(0));
+ my_free(value_);
}
};
};
diff --git a/storage/mroonga/lib/mrn_path_mapper.cpp b/storage/mroonga/lib/mrn_path_mapper.cpp
index ee5432f16bb..796101a10d1 100644
--- a/storage/mroonga/lib/mrn_path_mapper.cpp
+++ b/storage/mroonga/lib/mrn_path_mapper.cpp
@@ -2,7 +2,7 @@
/*
Copyright(C) 2010 Tetsuro IKEDA
Copyright(C) 2011-2013 Kentoku SHIBA
- Copyright(C) 2011-2012 Kouhei Sutou <kou@clear-code.com>
+ Copyright(C) 2011-2015 Kouhei Sutou <kou@clear-code.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -184,6 +184,9 @@ namespace mrn {
int i = len, j = 0;
for (; mysql_path_[--i] != FN_LIBCHAR ;) {}
for (; i < len ;) {
+ if (len - i - 1 >= 3 && strncmp(mysql_path_ + i + 1, "#P#", 3) == 0) {
+ break;
+ }
mysql_table_name_[j++] = mysql_path_[++i];
}
mysql_table_name_[j] = '\0';
diff --git a/storage/mroonga/mrn_err.h b/storage/mroonga/mrn_err.h
index c2ca885407a..bfaf2d44fa8 100644
--- a/storage/mroonga/mrn_err.h
+++ b/storage/mroonga/mrn_err.h
@@ -28,5 +28,11 @@
#define ER_MRN_ERROR_FROM_GROONGA_STR "Error from Groonga [%s]"
#define ER_MRN_INVALID_NULL_VALUE_NUM 16505
#define ER_MRN_INVALID_NULL_VALUE_STR "NULL value can't be used for %s"
+#define ER_MRN_UNSUPPORTED_COLUMN_FLAG_NUM 16506
+#define ER_MRN_UNSUPPORTED_COLUMN_FLAG_STR \
+ "The column flag '%-.64s' is unsupported. It is ignored"
+#define ER_MRN_INVALID_COLUMN_FLAG_NUM 16507
+#define ER_MRN_INVALID_COLUMN_FLAG_STR \
+ "The column flag '%-.64s' is invalid. '%-64s' is used instead"
#endif /* MRN_ERR_H_ */
diff --git a/storage/mroonga/mrn_mysql_compat.h b/storage/mroonga/mrn_mysql_compat.h
index 7312dd70827..61b4ddd67a2 100644
--- a/storage/mroonga/mrn_mysql_compat.h
+++ b/storage/mroonga/mrn_mysql_compat.h
@@ -1,6 +1,6 @@
/* -*- c-basic-offset: 2 -*- */
/*
- Copyright(C) 2011-2013 Kouhei Sutou <kou@clear-code.com>
+ Copyright(C) 2011-2014 Kouhei Sutou <kou@clear-code.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -22,15 +22,6 @@
#include "mrn_mysql.h"
-#if MYSQL_VERSION_ID >= 50500
-# define my_free(PTR, FLAG) my_free(PTR)
-#endif
-
-#if MYSQL_VERSION_ID < 50500
-# define mysql_mutex_lock(mutex) pthread_mutex_lock(mutex)
-# define mysql_mutex_unlock(mutex) pthread_mutex_unlock(mutex)
-#endif
-
#if MYSQL_VERSION_ID >= 50604
# define MRN_HAVE_MYSQL_TYPE_TIMESTAMP2
# define MRN_HAVE_MYSQL_TYPE_DATETIME2
diff --git a/storage/mroonga/mrn_table.cpp b/storage/mroonga/mrn_table.cpp
index 877cc6489ed..8011112c6ba 100644
--- a/storage/mroonga/mrn_table.cpp
+++ b/storage/mroonga/mrn_table.cpp
@@ -47,6 +47,7 @@
extern HASH *mrn_table_def_cache;
#endif
+#ifdef HAVE_PSI_INTERFACE
#ifdef WIN32
# ifdef MRN_TABLE_SHARE_HAVE_LOCK_SHARE
extern PSI_mutex_key *mrn_table_share_lock_share;
@@ -55,20 +56,23 @@ extern PSI_mutex_key *mrn_table_share_lock_share;
extern PSI_mutex_key *mrn_table_share_lock_ha_data;
# endif
#endif
+extern PSI_mutex_key mrn_share_mutex_key;
+extern PSI_mutex_key mrn_long_term_share_auto_inc_mutex_key;
+#endif
#ifdef __cplusplus
extern "C" {
#endif
extern HASH mrn_open_tables;
-extern pthread_mutex_t mrn_open_tables_mutex;
+extern mysql_mutex_t mrn_open_tables_mutex;
extern HASH mrn_long_term_share;
-extern pthread_mutex_t mrn_long_term_share_mutex;
+extern mysql_mutex_t mrn_long_term_share_mutex;
extern char *mrn_default_parser;
extern char *mrn_default_wrapper_engine;
extern handlerton *mrn_hton_ptr;
extern HASH mrn_allocated_thds;
-extern pthread_mutex_t mrn_allocated_thds_mutex;
+extern mysql_mutex_t mrn_allocated_thds_mutex;
static char *mrn_get_string_between_quote(const char *ptr)
{
@@ -424,7 +428,7 @@ int mrn_parse_table_param(MRN_SHARE *share, TABLE *table)
}
}
- my_free(params_string, MYF(0));
+ my_free(params_string);
params_string = NULL;
}
}
@@ -455,7 +459,7 @@ int mrn_parse_table_param(MRN_SHARE *share, TABLE *table)
!strncasecmp(share->engine, MRN_GROONGA_STR, MRN_GROONGA_LEN)
)
) {
- my_free(share->engine, MYF(0));
+ my_free(share->engine);
share->engine = NULL;
share->engine_length = 0;
} else {
@@ -474,7 +478,7 @@ int mrn_parse_table_param(MRN_SHARE *share, TABLE *table)
error:
if (params_string)
- my_free(params_string, MYF(0));
+ my_free(params_string);
DBUG_RETURN(error);
}
@@ -500,7 +504,7 @@ int mrn_add_index_param(MRN_SHARE *share, KEY *key_info, int i)
if (key_info->comment.length == 0)
{
if (share->key_parser[i]) {
- my_free(share->key_parser[i], MYF(0));
+ my_free(share->key_parser[i]);
}
if (
!(share->key_parser[i] = my_strdup(mrn_default_parser, MYF(MY_WME)))
@@ -574,12 +578,12 @@ int mrn_add_index_param(MRN_SHARE *share, KEY *key_info, int i)
}
if (param_string)
- my_free(param_string, MYF(0));
+ my_free(param_string);
DBUG_RETURN(0);
error:
if (param_string)
- my_free(param_string, MYF(0));
+ my_free(param_string);
#if MYSQL_VERSION_ID >= 50500
error_alloc_param_string:
#endif
@@ -677,12 +681,12 @@ int mrn_add_column_param(MRN_SHARE *share, Field *field, int i)
}
if (param_string)
- my_free(param_string, MYF(0));
+ my_free(param_string);
DBUG_RETURN(0);
error:
if (param_string)
- my_free(param_string, MYF(0));
+ my_free(param_string);
error_alloc_param_string:
DBUG_RETURN(error);
}
@@ -714,26 +718,26 @@ int mrn_free_share_alloc(
uint i;
MRN_DBUG_ENTER_FUNCTION();
if (share->engine)
- my_free(share->engine, MYF(0));
+ my_free(share->engine);
if (share->default_tokenizer)
- my_free(share->default_tokenizer, MYF(0));
+ my_free(share->default_tokenizer);
if (share->normalizer)
- my_free(share->normalizer, MYF(0));
+ my_free(share->normalizer);
if (share->token_filters)
- my_free(share->token_filters, MYF(0));
+ my_free(share->token_filters);
for (i = 0; i < share->table_share->keys; i++)
{
if (share->index_table && share->index_table[i])
- my_free(share->index_table[i], MYF(0));
+ my_free(share->index_table[i]);
if (share->key_parser[i])
- my_free(share->key_parser[i], MYF(0));
+ my_free(share->key_parser[i]);
}
for (i = 0; i < share->table_share->fields; i++)
{
if (share->col_flags && share->col_flags[i])
- my_free(share->col_flags[i], MYF(0));
+ my_free(share->col_flags[i]);
if (share->col_type && share->col_type[i])
- my_free(share->col_type[i], MYF(0));
+ my_free(share->col_type[i]);
}
DBUG_RETURN(0);
}
@@ -745,8 +749,8 @@ void mrn_free_long_term_share(MRN_LONG_TERM_SHARE *long_term_share)
mrn::Lock lock(&mrn_long_term_share_mutex);
my_hash_delete(&mrn_long_term_share, (uchar*) long_term_share);
}
- pthread_mutex_destroy(&long_term_share->auto_inc_mutex);
- my_free(long_term_share, MYF(0));
+ mysql_mutex_destroy(&long_term_share->auto_inc_mutex);
+ my_free(long_term_share);
DBUG_VOID_RETURN;
}
@@ -775,8 +779,9 @@ MRN_LONG_TERM_SHARE *mrn_get_long_term_share(const char *table_name,
long_term_share->table_name = tmp_name;
long_term_share->table_name_length = table_name_length;
memcpy(long_term_share->table_name, table_name, table_name_length);
- if (pthread_mutex_init(&long_term_share->auto_inc_mutex,
- MY_MUTEX_INIT_FAST))
+ if (mysql_mutex_init(mrn_long_term_share_auto_inc_mutex_key,
+ &long_term_share->auto_inc_mutex,
+ MY_MUTEX_INIT_FAST) != 0)
{
*error = HA_ERR_OUT_OF_MEM;
goto error_init_auto_inc_mutex;
@@ -790,9 +795,9 @@ MRN_LONG_TERM_SHARE *mrn_get_long_term_share(const char *table_name,
DBUG_RETURN(long_term_share);
error_hash_insert:
- pthread_mutex_destroy(&long_term_share->auto_inc_mutex);
+ mysql_mutex_destroy(&long_term_share->auto_inc_mutex);
error_init_auto_inc_mutex:
- my_free(long_term_share, MYF(0));
+ my_free(long_term_share);
error_alloc_long_term_share:
DBUG_RETURN(NULL);
}
@@ -912,7 +917,9 @@ MRN_SHARE *mrn_get_share(const char *table_name, TABLE *table, int *error)
share->wrap_table_share = wrap_table_share;
}
- if (pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST))
+ if (mysql_mutex_init(mrn_share_mutex_key,
+ &share->mutex,
+ MY_MUTEX_INIT_FAST) != 0)
{
*error = HA_ERR_OUT_OF_MEM;
goto error_init_mutex;
@@ -934,11 +941,11 @@ MRN_SHARE *mrn_get_share(const char *table_name, TABLE *table, int *error)
error_hash_insert:
error_get_long_term_share:
- pthread_mutex_destroy(&share->mutex);
+ mysql_mutex_destroy(&share->mutex);
error_init_mutex:
error_parse_table_param:
mrn_free_share_alloc(share);
- my_free(share, MYF(0));
+ my_free(share);
error_alloc_share:
DBUG_RETURN(NULL);
}
@@ -954,7 +961,7 @@ int mrn_free_share(MRN_SHARE *share)
plugin_unlock(NULL, share->plugin);
mrn_free_share_alloc(share);
thr_lock_delete(&share->lock);
- pthread_mutex_destroy(&share->mutex);
+ mysql_mutex_destroy(&share->mutex);
if (share->wrapper_mode) {
#ifdef MRN_TABLE_SHARE_HAVE_LOCK_SHARE
mysql_mutex_destroy(&(share->wrap_table_share->LOCK_share));
@@ -963,7 +970,7 @@ int mrn_free_share(MRN_SHARE *share)
mysql_mutex_destroy(&(share->wrap_table_share->LOCK_ha_data));
#endif
}
- my_free(share, MYF(0));
+ my_free(share);
}
DBUG_RETURN(0);
}
@@ -1025,9 +1032,9 @@ TABLE_SHARE *mrn_create_tmp_table_share(TABLE_LIST *table_list, const char *path
}
share->tmp_table = INTERNAL_TMP_TABLE; // TODO: is this right?
share->path.str = (char *) path;
- share->path.length = strlen(path);
- share->normalized_path.str = share->path.str;
- share->normalized_path.length = share->path.length;
+ share->path.length = strlen(share->path.str);
+ share->normalized_path.str = my_strdup(path, MYF(MY_WME));
+ share->normalized_path.length = strlen(share->normalized_path.str);
if (open_table_def(thd, share, GTS_TABLE))
{
*error = ER_CANT_OPEN_FILE;
@@ -1039,7 +1046,9 @@ TABLE_SHARE *mrn_create_tmp_table_share(TABLE_LIST *table_list, const char *path
void mrn_free_tmp_table_share(TABLE_SHARE *tmp_table_share)
{
MRN_DBUG_ENTER_FUNCTION();
+ char *normalized_path = tmp_table_share->normalized_path.str;
free_table_share(tmp_table_share);
+ my_free(normalized_path);
DBUG_VOID_RETURN;
}
@@ -1131,11 +1140,11 @@ void mrn_clear_alter_share(THD *thd)
slot_data->alter_create_info = NULL;
slot_data->disable_keys_create_info = NULL;
if (slot_data->alter_connect_string) {
- my_free(slot_data->alter_connect_string, MYF(0));
+ my_free(slot_data->alter_connect_string);
slot_data->alter_connect_string = NULL;
}
if (slot_data->alter_comment) {
- my_free(slot_data->alter_comment, MYF(0));
+ my_free(slot_data->alter_comment);
slot_data->alter_comment = NULL;
}
}
diff --git a/storage/mroonga/mrn_table.hpp b/storage/mroonga/mrn_table.hpp
index 813e69e1023..9118455b53d 100644
--- a/storage/mroonga/mrn_table.hpp
+++ b/storage/mroonga/mrn_table.hpp
@@ -33,7 +33,7 @@ typedef struct st_mroonga_long_term_share
uint table_name_length;
// for auto_increment (storage mode only)
- pthread_mutex_t auto_inc_mutex;
+ mysql_mutex_t auto_inc_mutex;
bool auto_inc_inited;
ulonglong auto_inc_value;
} MRN_LONG_TERM_SHARE;
@@ -43,7 +43,7 @@ typedef struct st_mroonga_share
char *table_name;
uint table_name_length;
uint use_count;
- pthread_mutex_t mutex;
+ mysql_mutex_t mutex;
THR_LOCK lock;
TABLE_SHARE *table_share;
TABLE_SHARE *wrap_table_share;
diff --git a/storage/mroonga/mysql-test/mroonga/include/mroonga/check_libgroonga_support_lz4.inc b/storage/mroonga/mysql-test/mroonga/include/mroonga/check_libgroonga_support_lz4.inc
new file mode 100644
index 00000000000..1c74cbffc46
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/include/mroonga/check_libgroonga_support_lz4.inc
@@ -0,0 +1,20 @@
+# Copyright(C) 2014 Naoya Murakami <naoya@createfield.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+--disable_query_log
+let $libgroonga_support_lz4 =
+ `SELECT @@mroonga_libgroonga_support_lz4;`;
+--enable_query_log
diff --git a/storage/mroonga/mysql-test/mroonga/include/mroonga/check_libgroonga_support_zlib.inc b/storage/mroonga/mysql-test/mroonga/include/mroonga/check_libgroonga_support_zlib.inc
new file mode 100644
index 00000000000..5ab5fcd2fb8
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/include/mroonga/check_libgroonga_support_zlib.inc
@@ -0,0 +1,20 @@
+# Copyright(C) 2014 Naoya Murakami <naoya@createfield.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+--disable_query_log
+let $libgroonga_support_zlib =
+ `SELECT @@mroonga_libgroonga_support_zlib;`;
+--enable_query_log
diff --git a/storage/mroonga/mysql-test/mroonga/include/mroonga/support_libgroonga_lz4.inc b/storage/mroonga/mysql-test/mroonga/include/mroonga/support_libgroonga_lz4.inc
new file mode 100644
index 00000000000..e67f826b0ce
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/include/mroonga/support_libgroonga_lz4.inc
@@ -0,0 +1,22 @@
+# Copyright(C) 2014 Naoya Murakami <naoya@createfield.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+--source ../../include/mroonga/check_libgroonga_support_lz4.inc
+
+if (!$libgroonga_support_lz4) {
+ --source ../../include/mroonga/have_mroonga_deinit.inc
+ skip "This test is for libgroonga supports lz4";
+}
diff --git a/storage/mroonga/mysql-test/mroonga/include/mroonga/support_libgroonga_zlib.inc b/storage/mroonga/mysql-test/mroonga/include/mroonga/support_libgroonga_zlib.inc
new file mode 100644
index 00000000000..9f5196f742b
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/include/mroonga/support_libgroonga_zlib.inc
@@ -0,0 +1,22 @@
+# Copyright(C) 2014 Naoya Murakami <naoya@createfield.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+--source ../../include/mroonga/check_libgroonga_support_zlib.inc
+
+if (!$libgroonga_support_zlib) {
+ --source ../../include/mroonga/have_mroonga_deinit.inc
+ skip "This test is for libgroonga supports zlib";
+}
diff --git a/storage/mroonga/mysql-test/mroonga/include/mroonga/unsupport_libgroonga_lz4.inc b/storage/mroonga/mysql-test/mroonga/include/mroonga/unsupport_libgroonga_lz4.inc
new file mode 100644
index 00000000000..80874a7a50b
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/include/mroonga/unsupport_libgroonga_lz4.inc
@@ -0,0 +1,22 @@
+# Copyright(C) 2014 Naoya Murakami <naoya@createfield.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+--source ../../include/mroonga/check_libgroonga_support_lz4.inc
+
+if ($libgroonga_support_lz4) {
+ --source ../../include/mroonga/have_mroonga_deinit.inc
+ skip "This test is for libgroonga doesn't support lz4";
+}
diff --git a/storage/mroonga/mysql-test/mroonga/include/mroonga/unsupport_libgroonga_zlib.inc b/storage/mroonga/mysql-test/mroonga/include/mroonga/unsupport_libgroonga_zlib.inc
new file mode 100644
index 00000000000..d6c3f6dbeda
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/include/mroonga/unsupport_libgroonga_zlib.inc
@@ -0,0 +1,22 @@
+# Copyright(C) 2014 Naoya Murakami <naoya@createfield.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+--source ../../include/mroonga/check_libgroonga_support_zlib.inc
+
+if ($libgroonga_support_zlib) {
+ --source ../../include/mroonga/have_mroonga_deinit.inc
+ skip "This test is for libgroonga doesn't support zlib";
+}
diff --git a/storage/mroonga/mysql-test/mroonga/storage/disabled.def b/storage/mroonga/mysql-test/mroonga/storage/disabled.def
index 3f546dad2a4..6866adc1e35 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/disabled.def
+++ b/storage/mroonga/mysql-test/mroonga/storage/disabled.def
@@ -6,4 +6,5 @@ create_table_token_filters_index_comment_one_token_filter : Bundled Mroonga does
create_table_token_filters_table_comment_multiple_token_filters : Bundled Mroonga does not support token filter yet.
create_table_token_filters_table_comment_one_token_filter : Bundled Mroonga does not support token filter yet.
foreign_key_create : Bundled Mroonga does not support this test yet.
+partition_insert : Bundled Mroonga does not support this test yet.
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/alter_table_add_index_unique_multiple_column_duplicated.result b/storage/mroonga/mysql-test/mroonga/storage/r/alter_table_add_index_unique_multiple_column_duplicated.result
new file mode 100644
index 00000000000..8ab7ef22aca
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/alter_table_add_index_unique_multiple_column_duplicated.result
@@ -0,0 +1,19 @@
+DROP TABLE IF EXISTS ids;
+CREATE TABLE ids (
+id1 INT,
+id2 INT
+) DEFAULT CHARSET=utf8mb4;
+INSERT INTO ids (id1, id2) values (1, 2), (1, 2);
+ALTER TABLE ids ADD UNIQUE INDEX (id1, id2);
+ERROR 23000: Can't write, because of unique constraint, to table 'ids'
+SHOW CREATE TABLE ids;
+Table Create Table
+ids CREATE TABLE `ids` (
+ `id1` int(11) DEFAULT NULL,
+ `id2` int(11) DEFAULT NULL
+) ENGINE=Mroonga DEFAULT CHARSET=utf8mb4
+SELECT * FROM ids;
+id1 id2
+1 2
+1 2
+DROP TABLE ids;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/alter_table_disable_keys_fulltext_table.result b/storage/mroonga/mysql-test/mroonga/storage/r/alter_table_disable_keys_fulltext_table.result
new file mode 100644
index 00000000000..c7051127946
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/alter_table_disable_keys_fulltext_table.result
@@ -0,0 +1,27 @@
+SET NAMES utf8;
+CREATE TABLE terms (
+term varchar(256) NOT NULL PRIMARY KEY
+) COMMENT='default_tokenizer "TokenBigram", normalizer "NormalizerAuto"'
+ DEFAULT CHARSET=utf8;
+CREATE TABLE memos (
+id int PRIMARY KEY,
+content text NOT NULL,
+FULLTEXT INDEX content_index (content) COMMENT 'table "terms"'
+) DEFAULT CHARSET=utf8;
+SELECT mroonga_command("dump");
+mroonga_command("dump")
+table_create terms TABLE_PAT_KEY ShortText --default_tokenizer TokenBigram --normalizer NormalizerAuto
+column_create terms term COLUMN_SCALAR ShortText
+table_create memos TABLE_PAT_KEY Int32
+column_create memos content COLUMN_SCALAR LongText
+column_create memos id COLUMN_SCALAR Int32
+column_create terms content_index COLUMN_INDEX|WITH_POSITION memos content
+ALTER TABLE memos DISABLE KEYS;
+SELECT mroonga_command("dump");
+mroonga_command("dump")
+table_create terms TABLE_PAT_KEY ShortText --default_tokenizer TokenBigram --normalizer NormalizerAuto
+column_create terms term COLUMN_SCALAR ShortText
+table_create memos TABLE_PAT_KEY Int32
+column_create memos content COLUMN_SCALAR LongText
+column_create memos id COLUMN_SCALAR Int32
+DROP TABLE memos, terms;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/alter_table_enable_keys_fulltext_table.result b/storage/mroonga/mysql-test/mroonga/storage/r/alter_table_enable_keys_fulltext_table.result
new file mode 100644
index 00000000000..97d2be3f8d5
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/alter_table_enable_keys_fulltext_table.result
@@ -0,0 +1,28 @@
+SET NAMES utf8;
+CREATE TABLE terms (
+term varchar(256) NOT NULL PRIMARY KEY
+) COMMENT='default_tokenizer "TokenBigram", normalizer "NormalizerAuto"'
+ DEFAULT CHARSET=utf8;
+CREATE TABLE memos (
+id int PRIMARY KEY,
+content text NOT NULL,
+FULLTEXT INDEX content_index (content) COMMENT 'table "terms"'
+) DEFAULT CHARSET=utf8;
+ALTER TABLE memos DISABLE KEYS;
+SELECT mroonga_command("dump");
+mroonga_command("dump")
+table_create terms TABLE_PAT_KEY ShortText --default_tokenizer TokenBigram --normalizer NormalizerAuto
+column_create terms term COLUMN_SCALAR ShortText
+table_create memos TABLE_PAT_KEY Int32
+column_create memos content COLUMN_SCALAR LongText
+column_create memos id COLUMN_SCALAR Int32
+ALTER TABLE memos ENABLE KEYS;
+SELECT mroonga_command("dump");
+mroonga_command("dump")
+table_create terms TABLE_PAT_KEY ShortText --default_tokenizer TokenBigram --normalizer NormalizerAuto
+column_create terms term COLUMN_SCALAR ShortText
+table_create memos TABLE_PAT_KEY Int32
+column_create memos content COLUMN_SCALAR LongText
+column_create memos id COLUMN_SCALAR Int32
+column_create terms content_index COLUMN_INDEX|WITH_POSITION memos content
+DROP TABLE memos, terms;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_index_fulltext_other_table.result b/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_index_fulltext_other_table.result
index 87c14a98f15..767fe491e99 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_index_fulltext_other_table.result
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_index_fulltext_other_table.result
@@ -1,42 +1,30 @@
-DROP DATABASE IF EXISTS mroonga;
-CREATE DATABASE mroonga;
-USE mroonga;
-CREATE TABLE tags (
+CREATE TABLE terms (
name VARCHAR(64) PRIMARY KEY
) DEFAULT CHARSET=utf8
-COLLATE=utf8_bin
-COMMENT='default_tokenizer "TokenDelimit"';
+COMMENT='default_tokenizer "TokenBigram"';
CREATE TABLE bugs (
id INT UNSIGNED PRIMARY KEY,
-tags TEXT COMMENT 'flags "COLUMN_VECTOR", type "tags"',
-FULLTEXT INDEX bugs_tags_index (tags) COMMENT 'table "tags"'
+title TEXT,
+FULLTEXT INDEX (title) COMMENT 'table "terms"'
) DEFAULT CHARSET=utf8;
-INSERT INTO bugs (id, tags) VALUES (1, "Linux MySQL groonga");
-SELECT mroonga_command("dump");
-mroonga_command("dump")
-table_create tags TABLE_PAT_KEY ShortText --default_tokenizer TokenDelimit
-column_create tags name COLUMN_SCALAR ShortText
-table_create bugs TABLE_PAT_KEY UInt32
-column_create bugs id COLUMN_SCALAR UInt32
-column_create bugs tags COLUMN_VECTOR tags
-column_create tags bugs_tags_index COLUMN_INDEX|WITH_POSITION bugs tags
-load --table tags
-[
-["_key","name"],
-["Linux",""],
-["MySQL",""],
-["groonga",""]
-]
-load --table bugs
-[
-["_key","id","tags"],
-[1,1,["Linux","MySQL","groonga"]]
-]
-SELECT *, MATCH (tags) AGAINST ("MySQL" IN BOOLEAN MODE) AS score
+INSERT INTO bugs (id, title) VALUES (1, "Mroonga can't build with MySQL X.Y.Z");
+SELECT * FROM terms ORDER BY name;
+name
+'
+.
+BUILD
+CAN
+MROONGA
+MYSQL
+T
+WITH
+X
+Y
+Z
+SELECT *, MATCH (title) AGAINST ("+MySQL" IN BOOLEAN MODE) AS score
FROM bugs
-WHERE MATCH (tags) AGAINST ("MySQL" IN BOOLEAN MODE);
-id tags score
-1 Linux MySQL groonga 1
+WHERE MATCH (title) AGAINST ("+MySQL" IN BOOLEAN MODE);
+id title score
+1 Mroonga can't build with MySQL X.Y.Z 1
DROP TABLE bugs;
-DROP TABLE tags;
-DROP DATABASE mroonga;
+DROP TABLE terms;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_index_fulltext_vector_other_table.result b/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_index_fulltext_vector_other_table.result
new file mode 100644
index 00000000000..6ac2e1937fe
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_index_fulltext_vector_other_table.result
@@ -0,0 +1,42 @@
+DROP DATABASE IF EXISTS mroonga;
+CREATE DATABASE mroonga;
+USE mroonga;
+CREATE TABLE tags (
+name VARCHAR(64) PRIMARY KEY
+) DEFAULT CHARSET=utf8
+COLLATE=utf8_bin
+COMMENT='default_tokenizer "TokenDelimit"';
+CREATE TABLE bugs (
+id INT UNSIGNED PRIMARY KEY,
+tags TEXT COMMENT 'flags "COLUMN_VECTOR", type "tags"',
+FULLTEXT INDEX bugs_tags_index (tags) COMMENT 'table "tags"'
+) DEFAULT CHARSET=utf8;
+INSERT INTO bugs (id, tags) VALUES (1, "Linux MySQL groonga");
+SELECT mroonga_command("dump");
+mroonga_command("dump")
+table_create tags TABLE_PAT_KEY ShortText --default_tokenizer TokenDelimit
+column_create tags name COLUMN_SCALAR ShortText
+table_create bugs TABLE_PAT_KEY UInt32
+column_create bugs id COLUMN_SCALAR UInt32
+column_create bugs tags COLUMN_VECTOR tags
+column_create tags bugs_tags_index COLUMN_INDEX|WITH_POSITION bugs tags
+load --table tags
+[
+["_key","name"],
+["Linux",""],
+["MySQL",""],
+["groonga",""]
+]
+load --table bugs
+[
+["_key","id","tags"],
+[1,1,["Linux","MySQL","groonga"]]
+]
+SELECT *, MATCH (tags) AGAINST ("+MySQL" IN BOOLEAN MODE) AS score
+FROM bugs
+WHERE MATCH (tags) AGAINST ("+MySQL" IN BOOLEAN MODE);
+id tags score
+1 Linux MySQL groonga 1
+DROP TABLE bugs;
+DROP TABLE tags;
+DROP DATABASE mroonga;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_support_lz4.result b/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_support_lz4.result
new file mode 100644
index 00000000000..11875e15018
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_support_lz4.result
@@ -0,0 +1,10 @@
+DROP TABLE IF EXISTS entries;
+CREATE TABLE entries (
+id INT UNSIGNED PRIMARY KEY,
+content TEXT COMMENT 'flags "COLUMN_SCALAR|COMPRESS_LZ4"'
+) DEFAULT CHARSET=utf8;
+INSERT INTO entries (id, content) VALUES (1, "I found Mroonga that is a MySQL storage engine to use Groonga!");
+SELECT * FROM entries;
+id content
+1 I found Mroonga that is a MySQL storage engine to use Groonga!
+DROP TABLE entries;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_support_zlib.result b/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_support_zlib.result
new file mode 100644
index 00000000000..5d704e3ebec
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_support_zlib.result
@@ -0,0 +1,10 @@
+DROP TABLE IF EXISTS entries;
+CREATE TABLE entries (
+id INT UNSIGNED PRIMARY KEY,
+content TEXT COMMENT 'flags "COLUMN_SCALAR|COMPRESS_ZLIB"'
+) DEFAULT CHARSET=utf8;
+INSERT INTO entries (id, content) VALUES (1, "I found Mroonga that is a MySQL storage engine to use Groonga!");
+SELECT * FROM entries;
+id content
+1 I found Mroonga that is a MySQL storage engine to use Groonga!
+DROP TABLE entries;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_unsupport_lz4.result b/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_unsupport_lz4.result
new file mode 100644
index 00000000000..a9a5f55fd7f
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_unsupport_lz4.result
@@ -0,0 +1,12 @@
+DROP TABLE IF EXISTS entries;
+CREATE TABLE entries (
+id INT UNSIGNED PRIMARY KEY,
+content TEXT COMMENT 'flags "COLUMN_SCALAR|COMPRESS_LZ4"'
+) DEFAULT CHARSET=utf8;
+Warnings:
+Warning 16506 The column flag 'COMPRESS_LZ4' is unsupported. It is ignored
+INSERT INTO entries (id, content) VALUES (1, "I found Mroonga that is a MySQL storage engine to use Groonga!");
+SELECT * FROM entries;
+id content
+1 I found Mroonga that is a MySQL storage engine to use Groonga!
+DROP TABLE entries;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_unsupport_zlib.result b/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_unsupport_zlib.result
new file mode 100644
index 00000000000..068ce58bf74
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_unsupport_zlib.result
@@ -0,0 +1,12 @@
+DROP TABLE IF EXISTS entries;
+CREATE TABLE entries (
+id INT UNSIGNED PRIMARY KEY,
+content TEXT COMMENT 'flags "COLUMN_SCALAR|COMPRESS_ZLIB"'
+) DEFAULT CHARSET=utf8;
+Warnings:
+Warning 16506 The column flag 'COMPRESS_ZLIB' is unsupported. It is ignored
+INSERT INTO entries (id, content) VALUES (1, "I found Mroonga that is a MySQL storage engine to use Groonga!");
+SELECT * FROM entries;
+id content
+1 I found Mroonga that is a MySQL storage engine to use Groonga!
+DROP TABLE entries;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_fulltext_index.result b/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_fulltext_index_comment.result
index e2d405a1e35..e2d405a1e35 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_fulltext_index.result
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_fulltext_index_comment.result
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_no_utf8_charset_with_utf8_normalizer.result b/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_fulltext_index_no_utf8_charset_with_utf8_normalizer.result
index 9d12e2d0e39..9d12e2d0e39 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_no_utf8_charset_with_utf8_normalizer.result
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_fulltext_index_no_utf8_charset_with_utf8_normalizer.result
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_fulltext_index_none.result b/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_fulltext_index_none.result
new file mode 100644
index 00000000000..52c6f055e88
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_fulltext_index_none.result
@@ -0,0 +1,16 @@
+DROP TABLE IF EXISTS diaries;
+SET NAMES utf8;
+CREATE TABLE diaries (
+day DATE PRIMARY KEY,
+content VARCHAR(64) NOT NULL,
+FULLTEXT INDEX (content) COMMENT 'normalizer "none"'
+) DEFAULT CHARSET=utf8;
+INSERT INTO diaries VALUES ("2013-04-23", "Mroonga");
+SELECT * FROM diaries
+WHERE MATCH (content) AGAINST ("+Mroonga" IN BOOLEAN MODE);
+day content
+2013-04-23 Mroonga
+SELECT * FROM diaries
+WHERE MATCH (content) AGAINST ("+mroonga" IN BOOLEAN MODE);
+day content
+DROP TABLE diaries;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_table_comment.result b/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_primary_key_table_comment.result
index dbf69362ee7..dbf69362ee7 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_table_comment.result
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_primary_key_table_comment.result
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/index_unique_search_after_duplicated.result b/storage/mroonga/mysql-test/mroonga/storage/r/index_unique_search_after_duplicated.result
new file mode 100644
index 00000000000..1d9d5fbbf51
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/index_unique_search_after_duplicated.result
@@ -0,0 +1,18 @@
+DROP TABLE IF EXISTS users;
+CREATE TABLE users (
+id int PRIMARY KEY,
+name varchar(100) NOT NULL,
+UNIQUE KEY (name)
+) DEFAULT CHARSET=utf8;
+INSERT INTO users VALUES (1, "Alice");
+INSERT INTO users VALUES (2, "Bob");
+INSERT INTO users VALUES (3, "Bob");
+ERROR 23000: Duplicate entry 'Bob' for key 'name'
+SELECT * FROM users;
+id name
+1 Alice
+2 Bob
+SELECT * FROM users WHERE name = "Bob";
+id name
+2 Bob
+DROP TABLE users;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/information_schema_plugins.result b/storage/mroonga/mysql-test/mroonga/storage/r/information_schema_plugins.result
index 8d3decfa32a..63ecb8c669a 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/r/information_schema_plugins.result
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/information_schema_plugins.result
@@ -1,4 +1,4 @@
select PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_TYPE
from information_schema.plugins where plugin_name = "Mroonga";
PLUGIN_NAME PLUGIN_VERSION PLUGIN_TYPE
-Mroonga 4.6 STORAGE ENGINE
+Mroonga 5.0 STORAGE ENGINE
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/insert_on_duplicate_key_update_unique_key.result b/storage/mroonga/mysql-test/mroonga/storage/r/insert_on_duplicate_key_update_unique_key.result
index 288e9e3a2c8..fbec44527f7 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/r/insert_on_duplicate_key_update_unique_key.result
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/insert_on_duplicate_key_update_unique_key.result
@@ -15,16 +15,19 @@ diaries CREATE TABLE `diaries` (
UNIQUE KEY `day` (`day`)
) ENGINE=Mroonga DEFAULT CHARSET=utf8
INSERT INTO diaries (day, title)
-VALUES ("2012-02-14", "clear day")
-ON DUPLICATE KEY UPDATE title = "clear day (duplicated)";
+VALUES ("2012-02-14", "clear day1")
+ON DUPLICATE KEY UPDATE title = "clear day1 (duplicated)";
INSERT INTO diaries (day, title)
-VALUES ("2012-02-14", "rainy day")
-ON DUPLICATE KEY UPDATE title = "rainy day (duplicated)";
+VALUES ("2012-02-14", "clear day2")
+ON DUPLICATE KEY UPDATE title = "clear day2 (duplicated)";
+INSERT INTO diaries (day, title)
+VALUES ("2012-02-14", "clear day3")
+ON DUPLICATE KEY UPDATE title = "clear day3 (duplicated)";
INSERT INTO diaries (day, title)
VALUES ("2012-02-15", "cloudy day")
ON DUPLICATE KEY UPDATE title = "cloudy day (duplicated)";
SELECT * FROM diaries;
id day title
-1 2012-02-14 rainy day (duplicated)
-3 2012-02-15 cloudy day
+1 2012-02-14 clear day3 (duplicated)
+4 2012-02-15 cloudy day
DROP TABLE diaries;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/partition_insert.result b/storage/mroonga/mysql-test/mroonga/storage/r/partition_insert.result
new file mode 100644
index 00000000000..ea1e63e39d0
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/partition_insert.result
@@ -0,0 +1,42 @@
+DROP TABLE IF EXISTS logs;
+SET NAMES UTF8;
+CREATE TABLE logs (
+timestamp DATETIME,
+message TEXT
+) DEFAULT CHARSET=UTF8
+PARTITION BY RANGE (TO_DAYS(timestamp)) (
+PARTITION p201501 VALUES LESS THAN (TO_DAYS('2015-02-01')),
+PARTITION p201502 VALUES LESS THAN (TO_DAYS('2015-03-01')),
+PARTITION p201503 VALUES LESS THAN (TO_DAYS('2015-04-01')),
+PARTITION pfuture VALUES LESS THAN MAXVALUE
+);
+SHOW CREATE TABLE logs;
+Table Create Table
+logs CREATE TABLE `logs` (
+ `timestamp` datetime DEFAULT NULL,
+ `message` text
+) ENGINE=Mroonga DEFAULT CHARSET=utf8
+/*!50100 PARTITION BY RANGE (TO_DAYS(timestamp))
+(PARTITION p201501 VALUES LESS THAN (735995) ENGINE = Mroonga,
+ PARTITION p201502 VALUES LESS THAN (736023) ENGINE = Mroonga,
+ PARTITION p201503 VALUES LESS THAN (736054) ENGINE = Mroonga,
+ PARTITION pfuture VALUES LESS THAN MAXVALUE ENGINE = Mroonga) */
+INSERT INTO logs VALUES('2015-01-01 00:00:00', 'Start');
+INSERT INTO logs VALUES('2015-01-31 23:59:59', 'Shutdown');
+INSERT INTO logs VALUES('2015-02-01 00:00:00', 'Start');
+INSERT INTO logs VALUES('2015-02-28 23:59:59', 'Shutdown');
+INSERT INTO logs VALUES('2015-03-01 00:00:00', 'Start');
+INSERT INTO logs VALUES('2015-03-31 23:59:59', 'Shutdown');
+INSERT INTO logs VALUES('2015-04-01 00:00:00', 'Start');
+INSERT INTO logs VALUES('2015-04-30 23:59:59', 'Shutdown');
+SELECT * FROM logs ORDER BY timestamp;
+timestamp message
+2015-01-01 00:00:00 Start
+2015-01-31 23:59:59 Shutdown
+2015-02-01 00:00:00 Start
+2015-02-28 23:59:59 Shutdown
+2015-03-01 00:00:00 Start
+2015-03-31 23:59:59 Shutdown
+2015-04-01 00:00:00 Start
+2015-04-30 23:59:59 Shutdown
+DROP TABLE logs;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/replace_without_key.result b/storage/mroonga/mysql-test/mroonga/storage/r/replace_without_key.result
new file mode 100644
index 00000000000..2c6c1cbc7e8
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/replace_without_key.result
@@ -0,0 +1,10 @@
+DROP TABLE IF EXISTS diaries;
+SET NAMES utf8;
+CREATE TABLE diaries (
+id varchar(32) NOT NULL PRIMARY KEY,
+content text,
+FULLTEXT INDEX (content)
+) DEFAULT CHARSET=utf8;
+REPLACE INTO diaries(content) VALUES("Hello");
+ERROR HY000: primary key is empty
+DROP TABLE diaries;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_allow_column.result b/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_allow_column.result
new file mode 100644
index 00000000000..37826335b02
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_allow_column.result
@@ -0,0 +1,18 @@
+SET @mroonga_boolean_mode_syntax_flags_backup =
+@@mroonga_boolean_mode_syntax_flags;
+SET mroonga_boolean_mode_syntax_flags = "SYNTAX_QUERY,ALLOW_COLUMN";
+SET NAMES UTF8;
+CREATE TABLE diaries (
+title TEXT,
+content TEXT,
+FULLTEXT KEY (title),
+FULLTEXT KEY (content)
+) DEFAULT CHARSET=utf8;
+INSERT INTO diaries VALUES("Groonga", "Hello Groonga");
+SELECT * FROM diaries
+WHERE MATCH(title) AGAINST("content:@Hello" IN BOOLEAN MODE);
+title content
+Groonga Hello Groonga
+DROP TABLE diaries;
+SET mroonga_boolean_mode_syntax_flags =
+@mroonga_boolean_mode_syntax_flags_backup;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_allow_leading_not.result b/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_allow_leading_not.result
new file mode 100644
index 00000000000..d3ccb150eab
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_allow_leading_not.result
@@ -0,0 +1,16 @@
+SET @mroonga_boolean_mode_syntax_flags_backup =
+@@mroonga_boolean_mode_syntax_flags;
+SET mroonga_boolean_mode_syntax_flags = "SYNTAX_QUERY,ALLOW_LEADING_NOT";
+SET NAMES UTF8;
+CREATE TABLE diaries (
+title TEXT,
+FULLTEXT KEY (title)
+) DEFAULT CHARSET=utf8;
+INSERT INTO diaries VALUES("Groonga");
+INSERT INTO diaries VALUES("Mroonga");
+SELECT * FROM diaries WHERE MATCH(title) AGAINST("-Groonga" IN BOOLEAN MODE);
+title
+Mroonga
+DROP TABLE diaries;
+SET mroonga_boolean_mode_syntax_flags =
+@mroonga_boolean_mode_syntax_flags_backup;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_allow_update.result b/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_allow_update.result
new file mode 100644
index 00000000000..55cd8742758
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_allow_update.result
@@ -0,0 +1,18 @@
+SET @mroonga_boolean_mode_syntax_flags_backup =
+@@mroonga_boolean_mode_syntax_flags;
+SET mroonga_boolean_mode_syntax_flags = "SYNTAX_QUERY,ALLOW_COLUMN,ALLOW_UPDATE";
+SET NAMES UTF8;
+CREATE TABLE diaries (
+title TEXT,
+content TEXT,
+FULLTEXT KEY (title),
+FULLTEXT KEY (content)
+) DEFAULT CHARSET=utf8;
+INSERT INTO diaries VALUES("Groonga", "Hello Groonga");
+SELECT * FROM diaries
+WHERE MATCH(title) AGAINST('content:="Hello Mroonga"' IN BOOLEAN MODE);
+title content
+Groonga Hello Mroonga
+DROP TABLE diaries;
+SET mroonga_boolean_mode_syntax_flags =
+@mroonga_boolean_mode_syntax_flags_backup;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_syntax_query.result b/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_syntax_query.result
new file mode 100644
index 00000000000..5736fd52c89
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_syntax_query.result
@@ -0,0 +1,15 @@
+SET @mroonga_boolean_mode_syntax_flags_backup =
+@@mroonga_boolean_mode_syntax_flags;
+SET mroonga_boolean_mode_syntax_flags = "SYNTAX_QUERY";
+SET NAMES UTF8;
+CREATE TABLE diaries (
+title TEXT,
+FULLTEXT KEY (title)
+) DEFAULT CHARSET=utf8;
+INSERT INTO diaries VALUES("Re:Mroonga");
+SELECT * FROM diaries WHERE MATCH(title) AGAINST("Re:Mroonga" IN BOOLEAN MODE);
+title
+Re:Mroonga
+DROP TABLE diaries;
+SET mroonga_boolean_mode_syntax_flags =
+@mroonga_boolean_mode_syntax_flags_backup;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_syntax_script.result b/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_syntax_script.result
new file mode 100644
index 00000000000..e42fa259e4a
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_syntax_script.result
@@ -0,0 +1,16 @@
+SET @mroonga_boolean_mode_syntax_flags_backup =
+@@mroonga_boolean_mode_syntax_flags;
+SET mroonga_boolean_mode_syntax_flags = "SYNTAX_SCRIPT";
+SET NAMES UTF8;
+CREATE TABLE diaries (
+title TEXT,
+FULLTEXT KEY (title)
+) DEFAULT CHARSET=utf8;
+INSERT INTO diaries VALUES("Re:Mroonga");
+SELECT * FROM diaries
+WHERE MATCH(title) AGAINST("title @ 'Re:Mroonga'" IN BOOLEAN MODE);
+title
+Re:Mroonga
+DROP TABLE diaries;
+SET mroonga_boolean_mode_syntax_flags =
+@mroonga_boolean_mode_syntax_flags_backup;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/variable_version.result b/storage/mroonga/mysql-test/mroonga/storage/r/variable_version.result
index aae83fe2b38..9b99165c047 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/r/variable_version.result
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/variable_version.result
@@ -1,3 +1,3 @@
show variables like 'mroonga_version';
Variable_name Value
-mroonga_version 4.06
+mroonga_version 5.00
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/alter_table_add_index_unique_multiple_column_duplicated.test b/storage/mroonga/mysql-test/mroonga/storage/t/alter_table_add_index_unique_multiple_column_duplicated.test
new file mode 100644
index 00000000000..72e0ebc14a4
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/alter_table_add_index_unique_multiple_column_duplicated.test
@@ -0,0 +1,39 @@
+# Copyright(C) 2015 Kouhei Sutou <kou@clear-code.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+--source include/not_embedded.inc
+--source ../../include/mroonga/have_mroonga.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS ids;
+--enable_warnings
+
+CREATE TABLE ids (
+ id1 INT,
+ id2 INT
+) DEFAULT CHARSET=utf8mb4;
+
+INSERT INTO ids (id1, id2) values (1, 2), (1, 2);
+
+--error ER_DUP_UNIQUE
+ALTER TABLE ids ADD UNIQUE INDEX (id1, id2);
+SHOW CREATE TABLE ids;
+
+SELECT * FROM ids;
+
+DROP TABLE ids;
+
+--source ../../include/mroonga/have_mroonga_deinit.inc
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/alter_table_disable_keys_fulltext_table.test b/storage/mroonga/mysql-test/mroonga/storage/t/alter_table_disable_keys_fulltext_table.test
new file mode 100644
index 00000000000..d0c1313c784
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/alter_table_disable_keys_fulltext_table.test
@@ -0,0 +1,45 @@
+# Copyright(C) 2014 Kouhei Sutou <kou@clear-code.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+--source ../../include/mroonga/have_mroonga.inc
+--source ../../include/mroonga/load_mroonga_functions.inc
+
+--disable_query_log
+DROP DATABASE test;
+CREATE DATABASE test;
+USE test;
+--enable_query_log
+
+SET NAMES utf8;
+CREATE TABLE terms (
+ term varchar(256) NOT NULL PRIMARY KEY
+) COMMENT='default_tokenizer "TokenBigram", normalizer "NormalizerAuto"'
+ DEFAULT CHARSET=utf8;
+
+CREATE TABLE memos (
+ id int PRIMARY KEY,
+ content text NOT NULL,
+ FULLTEXT INDEX content_index (content) COMMENT 'table "terms"'
+) DEFAULT CHARSET=utf8;
+
+SELECT mroonga_command("dump");
+ALTER TABLE memos DISABLE KEYS;
+SELECT mroonga_command("dump");
+
+DROP TABLE memos, terms;
+
+--source ../../include/mroonga/unload_mroonga_functions.inc
+--source ../../include/mroonga/have_mroonga_deinit.inc
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/alter_table_enable_keys_fulltext_table.test b/storage/mroonga/mysql-test/mroonga/storage/t/alter_table_enable_keys_fulltext_table.test
new file mode 100644
index 00000000000..b05fa6aa116
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/alter_table_enable_keys_fulltext_table.test
@@ -0,0 +1,46 @@
+# Copyright(C) 2014 Kouhei Sutou <kou@clear-code.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+--source ../../include/mroonga/have_mroonga.inc
+--source ../../include/mroonga/load_mroonga_functions.inc
+
+--disable_query_log
+DROP DATABASE test;
+CREATE DATABASE test;
+USE test;
+--enable_query_log
+
+SET NAMES utf8;
+CREATE TABLE terms (
+ term varchar(256) NOT NULL PRIMARY KEY
+) COMMENT='default_tokenizer "TokenBigram", normalizer "NormalizerAuto"'
+ DEFAULT CHARSET=utf8;
+
+CREATE TABLE memos (
+ id int PRIMARY KEY,
+ content text NOT NULL,
+ FULLTEXT INDEX content_index (content) COMMENT 'table "terms"'
+) DEFAULT CHARSET=utf8;
+
+ALTER TABLE memos DISABLE KEYS;
+SELECT mroonga_command("dump");
+ALTER TABLE memos ENABLE KEYS;
+SELECT mroonga_command("dump");
+
+DROP TABLE memos, terms;
+
+--source ../../include/mroonga/unload_mroonga_functions.inc
+--source ../../include/mroonga/have_mroonga_deinit.inc
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_index_fulltext_other_table.test b/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_index_fulltext_other_table.test
index 805c744236f..dbaf2fb429f 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_index_fulltext_other_table.test
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_index_fulltext_other_table.test
@@ -1,4 +1,4 @@
-# Copyright(C) 2013 Kouhei Sutou <kou@clear-code.com>
+# Copyright(C) 2014 Kouhei Sutou <kou@clear-code.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -16,39 +16,27 @@
--source include/not_embedded.inc
--source ../../include/mroonga/have_mroonga.inc
---source ../../include/mroonga/load_mroonga_functions.inc
---disable_warnings
-DROP DATABASE IF EXISTS mroonga;
---enable_warnings
-
-CREATE DATABASE mroonga;
-USE mroonga;
-
-CREATE TABLE tags (
+CREATE TABLE terms (
name VARCHAR(64) PRIMARY KEY
) DEFAULT CHARSET=utf8
- COLLATE=utf8_bin
- COMMENT='default_tokenizer "TokenDelimit"';
+ COMMENT='default_tokenizer "TokenBigram"';
CREATE TABLE bugs (
id INT UNSIGNED PRIMARY KEY,
- tags TEXT COMMENT 'flags "COLUMN_VECTOR", type "tags"',
- FULLTEXT INDEX bugs_tags_index (tags) COMMENT 'table "tags"'
+ title TEXT,
+ FULLTEXT INDEX (title) COMMENT 'table "terms"'
) DEFAULT CHARSET=utf8;
-INSERT INTO bugs (id, tags) VALUES (1, "Linux MySQL groonga");
+INSERT INTO bugs (id, title) VALUES (1, "Mroonga can't build with MySQL X.Y.Z");
-SELECT mroonga_command("dump");
+SELECT * FROM terms ORDER BY name;
-SELECT *, MATCH (tags) AGAINST ("MySQL" IN BOOLEAN MODE) AS score
+SELECT *, MATCH (title) AGAINST ("+MySQL" IN BOOLEAN MODE) AS score
FROM bugs
- WHERE MATCH (tags) AGAINST ("MySQL" IN BOOLEAN MODE);
+ WHERE MATCH (title) AGAINST ("+MySQL" IN BOOLEAN MODE);
DROP TABLE bugs;
-DROP TABLE tags;
-
-DROP DATABASE mroonga;
+DROP TABLE terms;
---source ../../include/mroonga/unload_mroonga_functions.inc
--source ../../include/mroonga/have_mroonga_deinit.inc
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_index_fulltext_vector_other_table.test b/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_index_fulltext_vector_other_table.test
new file mode 100644
index 00000000000..86ef09cc8bb
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_index_fulltext_vector_other_table.test
@@ -0,0 +1,54 @@
+# Copyright(C) 2013 Kouhei Sutou <kou@clear-code.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+--source include/not_embedded.inc
+--source ../../include/mroonga/have_mroonga.inc
+--source ../../include/mroonga/load_mroonga_functions.inc
+
+--disable_warnings
+DROP DATABASE IF EXISTS mroonga;
+--enable_warnings
+
+CREATE DATABASE mroonga;
+USE mroonga;
+
+CREATE TABLE tags (
+ name VARCHAR(64) PRIMARY KEY
+) DEFAULT CHARSET=utf8
+ COLLATE=utf8_bin
+ COMMENT='default_tokenizer "TokenDelimit"';
+
+CREATE TABLE bugs (
+ id INT UNSIGNED PRIMARY KEY,
+ tags TEXT COMMENT 'flags "COLUMN_VECTOR", type "tags"',
+ FULLTEXT INDEX bugs_tags_index (tags) COMMENT 'table "tags"'
+) DEFAULT CHARSET=utf8;
+
+INSERT INTO bugs (id, tags) VALUES (1, "Linux MySQL groonga");
+
+SELECT mroonga_command("dump");
+
+SELECT *, MATCH (tags) AGAINST ("+MySQL" IN BOOLEAN MODE) AS score
+ FROM bugs
+ WHERE MATCH (tags) AGAINST ("+MySQL" IN BOOLEAN MODE);
+
+DROP TABLE bugs;
+DROP TABLE tags;
+
+DROP DATABASE mroonga;
+
+--source ../../include/mroonga/unload_mroonga_functions.inc
+--source ../../include/mroonga/have_mroonga_deinit.inc
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_support_lz4.test b/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_support_lz4.test
new file mode 100644
index 00000000000..5de8f951d8f
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_support_lz4.test
@@ -0,0 +1,37 @@
+# Copyright(C) 2014 Naoya Murakami <naoya@createfield.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+--source ../../include/mroonga/have_mroonga.inc
+--source ../../include/mroonga/support_libgroonga_lz4.inc
+--source ../../include/mroonga/load_mroonga_functions.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS entries;
+--enable_warnings
+
+CREATE TABLE entries (
+ id INT UNSIGNED PRIMARY KEY,
+ content TEXT COMMENT 'flags "COLUMN_SCALAR|COMPRESS_LZ4"'
+) DEFAULT CHARSET=utf8;
+
+INSERT INTO entries (id, content) VALUES (1, "I found Mroonga that is a MySQL storage engine to use Groonga!");
+
+SELECT * FROM entries;
+
+DROP TABLE entries;
+
+--source ../../include/mroonga/unload_mroonga_functions.inc
+--source ../../include/mroonga/have_mroonga_deinit.inc
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_support_zlib.test b/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_support_zlib.test
new file mode 100644
index 00000000000..3ec14ebef76
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_support_zlib.test
@@ -0,0 +1,37 @@
+# Copyright(C) 2014 Naoya Murakami <naoya@createfield.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+--source ../../include/mroonga/have_mroonga.inc
+--source ../../include/mroonga/support_libgroonga_zlib.inc
+--source ../../include/mroonga/load_mroonga_functions.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS entries;
+--enable_warnings
+
+CREATE TABLE entries (
+ id INT UNSIGNED PRIMARY KEY,
+ content TEXT COMMENT 'flags "COLUMN_SCALAR|COMPRESS_ZLIB"'
+) DEFAULT CHARSET=utf8;
+
+INSERT INTO entries (id, content) VALUES (1, "I found Mroonga that is a MySQL storage engine to use Groonga!");
+
+SELECT * FROM entries;
+
+DROP TABLE entries;
+
+--source ../../include/mroonga/unload_mroonga_functions.inc
+--source ../../include/mroonga/have_mroonga_deinit.inc
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_unsupport_lz4.test b/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_unsupport_lz4.test
new file mode 100644
index 00000000000..324b7ac89f5
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_unsupport_lz4.test
@@ -0,0 +1,37 @@
+# Copyright(C) 2014 Naoya Murakami <naoya@createfield.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+--source ../../include/mroonga/have_mroonga.inc
+--source ../../include/mroonga/unsupport_libgroonga_lz4.inc
+--source ../../include/mroonga/load_mroonga_functions.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS entries;
+--enable_warnings
+
+CREATE TABLE entries (
+ id INT UNSIGNED PRIMARY KEY,
+ content TEXT COMMENT 'flags "COLUMN_SCALAR|COMPRESS_LZ4"'
+) DEFAULT CHARSET=utf8;
+
+INSERT INTO entries (id, content) VALUES (1, "I found Mroonga that is a MySQL storage engine to use Groonga!");
+
+SELECT * FROM entries;
+
+DROP TABLE entries;
+
+--source ../../include/mroonga/unload_mroonga_functions.inc
+--source ../../include/mroonga/have_mroonga_deinit.inc
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_unsupport_zlib.test b/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_unsupport_zlib.test
new file mode 100644
index 00000000000..10e77e40e3d
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_unsupport_zlib.test
@@ -0,0 +1,37 @@
+# Copyright(C) 2014 Naoya Murakami <naoya@createfield.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+--source ../../include/mroonga/have_mroonga.inc
+--source ../../include/mroonga/unsupport_libgroonga_zlib.inc
+--source ../../include/mroonga/load_mroonga_functions.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS entries;
+--enable_warnings
+
+CREATE TABLE entries (
+ id INT UNSIGNED PRIMARY KEY,
+ content TEXT COMMENT 'flags "COLUMN_SCALAR|COMPRESS_ZLIB"'
+) DEFAULT CHARSET=utf8;
+
+INSERT INTO entries (id, content) VALUES (1, "I found Mroonga that is a MySQL storage engine to use Groonga!");
+
+SELECT * FROM entries;
+
+DROP TABLE entries;
+
+--source ../../include/mroonga/unload_mroonga_functions.inc
+--source ../../include/mroonga/have_mroonga_deinit.inc
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_fulltext_index.test b/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_fulltext_index_comment.test
index 02e2cb9e81a..02e2cb9e81a 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_fulltext_index.test
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_fulltext_index_comment.test
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_no_utf8_charset_with_utf8_normalizer.test b/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_fulltext_index_no_utf8_charset_with_utf8_normalizer.test
index f28fb5b8695..f28fb5b8695 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_no_utf8_charset_with_utf8_normalizer.test
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_fulltext_index_no_utf8_charset_with_utf8_normalizer.test
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_fulltext_index_none.test b/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_fulltext_index_none.test
new file mode 100644
index 00000000000..ae4d4cb9f1b
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_fulltext_index_none.test
@@ -0,0 +1,42 @@
+# Copyright(C) 2014 Kouhei Sutou <kou@clear-code.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+--source ../../include/mroonga/have_mroonga.inc
+--source ../../include/mroonga/load_mroonga_functions.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS diaries;
+--enable_warnings
+
+SET NAMES utf8;
+
+CREATE TABLE diaries (
+ day DATE PRIMARY KEY,
+ content VARCHAR(64) NOT NULL,
+ FULLTEXT INDEX (content) COMMENT 'normalizer "none"'
+) DEFAULT CHARSET=utf8;
+
+INSERT INTO diaries VALUES ("2013-04-23", "Mroonga");
+
+SELECT * FROM diaries
+ WHERE MATCH (content) AGAINST ("+Mroonga" IN BOOLEAN MODE);
+SELECT * FROM diaries
+ WHERE MATCH (content) AGAINST ("+mroonga" IN BOOLEAN MODE);
+
+DROP TABLE diaries;
+
+--source ../../include/mroonga/unload_mroonga_functions.inc
+--source ../../include/mroonga/have_mroonga_deinit.inc
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_table_comment.test b/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_primary_key_table_comment.test
index 1da8026f56d..1da8026f56d 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_table_comment.test
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_primary_key_table_comment.test
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/index_unique_search_after_duplicated.test b/storage/mroonga/mysql-test/mroonga/storage/t/index_unique_search_after_duplicated.test
new file mode 100644
index 00000000000..533422ec087
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/index_unique_search_after_duplicated.test
@@ -0,0 +1,40 @@
+# Copyright(C) 2015 Kouhei Sutou <kou@clear-code.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+--source ../../include/mroonga/have_mroonga.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS users;
+--enable_warnings
+
+CREATE TABLE users (
+ id int PRIMARY KEY,
+ name varchar(100) NOT NULL,
+ UNIQUE KEY (name)
+) DEFAULT CHARSET=utf8;
+
+INSERT INTO users VALUES (1, "Alice");
+
+INSERT INTO users VALUES (2, "Bob");
+-- error ER_DUP_ENTRY
+INSERT INTO users VALUES (3, "Bob");
+
+SELECT * FROM users;
+SELECT * FROM users WHERE name = "Bob";
+
+DROP TABLE users;
+
+--source ../../include/mroonga/have_mroonga_deinit.inc
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/insert_on_duplicate_key_update_unique_key.test b/storage/mroonga/mysql-test/mroonga/storage/t/insert_on_duplicate_key_update_unique_key.test
index 782b7bee9ca..350440515c1 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/t/insert_on_duplicate_key_update_unique_key.test
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/insert_on_duplicate_key_update_unique_key.test
@@ -29,11 +29,14 @@ CREATE TABLE diaries (
SHOW CREATE TABLE diaries;
INSERT INTO diaries (day, title)
- VALUES ("2012-02-14", "clear day")
- ON DUPLICATE KEY UPDATE title = "clear day (duplicated)";
+ VALUES ("2012-02-14", "clear day1")
+ ON DUPLICATE KEY UPDATE title = "clear day1 (duplicated)";
INSERT INTO diaries (day, title)
- VALUES ("2012-02-14", "rainy day")
- ON DUPLICATE KEY UPDATE title = "rainy day (duplicated)";
+ VALUES ("2012-02-14", "clear day2")
+ ON DUPLICATE KEY UPDATE title = "clear day2 (duplicated)";
+INSERT INTO diaries (day, title)
+ VALUES ("2012-02-14", "clear day3")
+ ON DUPLICATE KEY UPDATE title = "clear day3 (duplicated)";
INSERT INTO diaries (day, title)
VALUES ("2012-02-15", "cloudy day")
ON DUPLICATE KEY UPDATE title = "cloudy day (duplicated)";
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/partition_insert.test b/storage/mroonga/mysql-test/mroonga/storage/t/partition_insert.test
new file mode 100644
index 00000000000..219c3440d69
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/partition_insert.test
@@ -0,0 +1,49 @@
+# Copyright(C) 2015 Kouhei Sutou <kou@clear-code.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+--source ../../include/mroonga/have_mroonga.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS logs;
+--enable_warnings
+
+SET NAMES UTF8;
+CREATE TABLE logs (
+ timestamp DATETIME,
+ message TEXT
+) DEFAULT CHARSET=UTF8
+ PARTITION BY RANGE (TO_DAYS(timestamp)) (
+ PARTITION p201501 VALUES LESS THAN (TO_DAYS('2015-02-01')),
+ PARTITION p201502 VALUES LESS THAN (TO_DAYS('2015-03-01')),
+ PARTITION p201503 VALUES LESS THAN (TO_DAYS('2015-04-01')),
+ PARTITION pfuture VALUES LESS THAN MAXVALUE
+);
+SHOW CREATE TABLE logs;
+
+INSERT INTO logs VALUES('2015-01-01 00:00:00', 'Start');
+INSERT INTO logs VALUES('2015-01-31 23:59:59', 'Shutdown');
+INSERT INTO logs VALUES('2015-02-01 00:00:00', 'Start');
+INSERT INTO logs VALUES('2015-02-28 23:59:59', 'Shutdown');
+INSERT INTO logs VALUES('2015-03-01 00:00:00', 'Start');
+INSERT INTO logs VALUES('2015-03-31 23:59:59', 'Shutdown');
+INSERT INTO logs VALUES('2015-04-01 00:00:00', 'Start');
+INSERT INTO logs VALUES('2015-04-30 23:59:59', 'Shutdown');
+
+SELECT * FROM logs ORDER BY timestamp;
+
+DROP TABLE logs;
+
+--source ../../include/mroonga/have_mroonga_deinit.inc
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/replace_without_key.test b/storage/mroonga/mysql-test/mroonga/storage/t/replace_without_key.test
new file mode 100644
index 00000000000..a38c4953e67
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/replace_without_key.test
@@ -0,0 +1,35 @@
+# Copyright(C) 2014 Kouhei Sutou <kou@clear-code.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+--source ../../include/mroonga/have_mroonga.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS diaries;
+--enable_warnings
+
+SET NAMES utf8;
+CREATE TABLE diaries (
+ id varchar(32) NOT NULL PRIMARY KEY,
+ content text,
+ FULLTEXT INDEX (content)
+) DEFAULT CHARSET=utf8;
+
+-- error ER_ERROR_ON_WRITE
+REPLACE INTO diaries(content) VALUES("Hello");
+
+DROP TABLE diaries;
+
+--source ../../include/mroonga/have_mroonga_deinit.inc
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_allow_column.test b/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_allow_column.test
new file mode 100644
index 00000000000..11ca867d82c
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_allow_column.test
@@ -0,0 +1,43 @@
+# Copyright(C) 2014 Kouhei Sutou <kou@clear-code.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+--source ../../include/mroonga/have_mroonga.inc
+
+SET @mroonga_boolean_mode_syntax_flags_backup =
+ @@mroonga_boolean_mode_syntax_flags;
+
+SET mroonga_boolean_mode_syntax_flags = "SYNTAX_QUERY,ALLOW_COLUMN";
+
+SET NAMES UTF8;
+
+CREATE TABLE diaries (
+ title TEXT,
+ content TEXT,
+ FULLTEXT KEY (title),
+ FULLTEXT KEY (content)
+) DEFAULT CHARSET=utf8;
+
+INSERT INTO diaries VALUES("Groonga", "Hello Groonga");
+
+SELECT * FROM diaries
+ WHERE MATCH(title) AGAINST("content:@Hello" IN BOOLEAN MODE);
+
+DROP TABLE diaries;
+
+SET mroonga_boolean_mode_syntax_flags =
+ @mroonga_boolean_mode_syntax_flags_backup;
+
+--source ../../include/mroonga/have_mroonga_deinit.inc
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_allow_leading_not.test b/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_allow_leading_not.test
new file mode 100644
index 00000000000..665682fde6e
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_allow_leading_not.test
@@ -0,0 +1,41 @@
+# Copyright(C) 2014 Kouhei Sutou <kou@clear-code.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+--source ../../include/mroonga/have_mroonga.inc
+
+SET @mroonga_boolean_mode_syntax_flags_backup =
+ @@mroonga_boolean_mode_syntax_flags;
+
+SET mroonga_boolean_mode_syntax_flags = "SYNTAX_QUERY,ALLOW_LEADING_NOT";
+
+SET NAMES UTF8;
+
+CREATE TABLE diaries (
+ title TEXT,
+ FULLTEXT KEY (title)
+) DEFAULT CHARSET=utf8;
+
+INSERT INTO diaries VALUES("Groonga");
+INSERT INTO diaries VALUES("Mroonga");
+
+SELECT * FROM diaries WHERE MATCH(title) AGAINST("-Groonga" IN BOOLEAN MODE);
+
+DROP TABLE diaries;
+
+SET mroonga_boolean_mode_syntax_flags =
+ @mroonga_boolean_mode_syntax_flags_backup;
+
+--source ../../include/mroonga/have_mroonga_deinit.inc
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_allow_update.test b/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_allow_update.test
new file mode 100644
index 00000000000..8a55c0fb0f7
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_allow_update.test
@@ -0,0 +1,43 @@
+# Copyright(C) 2014 Kouhei Sutou <kou@clear-code.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+--source ../../include/mroonga/have_mroonga.inc
+
+SET @mroonga_boolean_mode_syntax_flags_backup =
+ @@mroonga_boolean_mode_syntax_flags;
+
+SET mroonga_boolean_mode_syntax_flags = "SYNTAX_QUERY,ALLOW_COLUMN,ALLOW_UPDATE";
+
+SET NAMES UTF8;
+
+CREATE TABLE diaries (
+ title TEXT,
+ content TEXT,
+ FULLTEXT KEY (title),
+ FULLTEXT KEY (content)
+) DEFAULT CHARSET=utf8;
+
+INSERT INTO diaries VALUES("Groonga", "Hello Groonga");
+
+SELECT * FROM diaries
+ WHERE MATCH(title) AGAINST('content:="Hello Mroonga"' IN BOOLEAN MODE);
+
+DROP TABLE diaries;
+
+SET mroonga_boolean_mode_syntax_flags =
+ @mroonga_boolean_mode_syntax_flags_backup;
+
+--source ../../include/mroonga/have_mroonga_deinit.inc
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_syntax_query.test b/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_syntax_query.test
new file mode 100644
index 00000000000..0ff2d8aed43
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_syntax_query.test
@@ -0,0 +1,40 @@
+# Copyright(C) 2014 Kouhei Sutou <kou@clear-code.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+--source ../../include/mroonga/have_mroonga.inc
+
+SET @mroonga_boolean_mode_syntax_flags_backup =
+ @@mroonga_boolean_mode_syntax_flags;
+
+SET mroonga_boolean_mode_syntax_flags = "SYNTAX_QUERY";
+
+SET NAMES UTF8;
+
+CREATE TABLE diaries (
+ title TEXT,
+ FULLTEXT KEY (title)
+) DEFAULT CHARSET=utf8;
+
+INSERT INTO diaries VALUES("Re:Mroonga");
+
+SELECT * FROM diaries WHERE MATCH(title) AGAINST("Re:Mroonga" IN BOOLEAN MODE);
+
+DROP TABLE diaries;
+
+SET mroonga_boolean_mode_syntax_flags =
+ @mroonga_boolean_mode_syntax_flags_backup;
+
+--source ../../include/mroonga/have_mroonga_deinit.inc
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_syntax_script.test b/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_syntax_script.test
new file mode 100644
index 00000000000..61d5daa63d9
--- /dev/null
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_syntax_script.test
@@ -0,0 +1,41 @@
+# Copyright(C) 2014 Kouhei Sutou <kou@clear-code.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+--source ../../include/mroonga/have_mroonga.inc
+
+SET @mroonga_boolean_mode_syntax_flags_backup =
+ @@mroonga_boolean_mode_syntax_flags;
+
+SET mroonga_boolean_mode_syntax_flags = "SYNTAX_SCRIPT";
+
+SET NAMES UTF8;
+
+CREATE TABLE diaries (
+ title TEXT,
+ FULLTEXT KEY (title)
+) DEFAULT CHARSET=utf8;
+
+INSERT INTO diaries VALUES("Re:Mroonga");
+
+SELECT * FROM diaries
+ WHERE MATCH(title) AGAINST("title @ 'Re:Mroonga'" IN BOOLEAN MODE);
+
+DROP TABLE diaries;
+
+SET mroonga_boolean_mode_syntax_flags =
+ @mroonga_boolean_mode_syntax_flags_backup;
+
+--source ../../include/mroonga/have_mroonga_deinit.inc
diff --git a/storage/mroonga/packages/Makefile.am b/storage/mroonga/packages/Makefile.am
new file mode 100644
index 00000000000..fed925c3dfc
--- /dev/null
+++ b/storage/mroonga/packages/Makefile.am
@@ -0,0 +1,7 @@
+SUBDIRS = \
+ apt \
+ rpm \
+ source \
+ ubuntu \
+ windows \
+ yum
diff --git a/storage/mroonga/packages/apt/Makefile.am b/storage/mroonga/packages/apt/Makefile.am
new file mode 100644
index 00000000000..26f5609c527
--- /dev/null
+++ b/storage/mroonga/packages/apt/Makefile.am
@@ -0,0 +1,67 @@
+REPOSITORIES_PATH = repositories
+DISTRIBUTIONS = debian
+ARCHITECTURES = i386 amd64
+CODE_NAMES = wheezy
+
+all:
+
+release: build sign-packages update-repository sign-repository upload
+
+remove-existing-packages:
+ for distribution in $(DISTRIBUTIONS); do \
+ find $(REPOSITORIES_PATH)/$${distribution}/pool \
+ -type f -delete; \
+ done
+
+download:
+ for distribution in $(DISTRIBUTIONS); do \
+ rsync -avz --progress --delete \
+ $(RSYNC_PATH)/$${distribution} $(REPOSITORIES_PATH)/; \
+ done
+
+sign-packages:
+ ./sign-packages.sh '$(GPG_UID)' '$(REPOSITORIES_PATH)/' '$(CODE_NAMES)'
+
+update-repository:
+ ./update-repository.sh '$(PACKAGE_NAME)' '$(REPOSITORIES_PATH)/' \
+ '$(ARCHITECTURES)' '$(CODE_NAMES)'
+
+sign-repository:
+ ./sign-repository.sh '$(GPG_UID)' '$(REPOSITORIES_PATH)/' '$(CODE_NAMES)'
+
+ensure-rsync-path:
+ @if test -z "$(RSYNC_PATH)"; then \
+ echo "--with-rsync-path configure option must be specified."; \
+ false; \
+ fi
+
+upload: ensure-rsync-path
+ for distribution in $(DISTRIBUTIONS); do \
+ (cd $(REPOSITORIES_PATH)/$${distribution}; \
+ rsync -avz --progress --delete \
+ dists pool $(RSYNC_PATH)/$${distribution}; \
+ ); \
+ done
+
+build: build-package-deb
+
+build-package-deb: prepare-build-package-deb
+ vagrant destroy --force
+ for architecture in $(ARCHITECTURES); do \
+ for code_name in $(CODE_NAMES); do \
+ id=debian-$$code_name-$$architecture; \
+ vagrant up $$id || exit 1; \
+ vagrant destroy --force $$id; \
+ done; \
+ done
+
+prepare-build-package-deb: source env.sh
+ cp env.sh tmp/
+ rm -rf tmp/debian
+ cp -rp $(srcdir)/../debian tmp/
+
+source: tmp/$(PACKAGE)-$(VERSION).tar.gz
+
+tmp/$(PACKAGE)-$(VERSION).tar.gz: $(abs_top_builddir)/$(PACKAGE)-$(VERSION).tar.gz
+ mkdir -p tmp
+ cp $(abs_top_builddir)/$(PACKAGE)-$(VERSION).tar.gz $@
diff --git a/storage/mroonga/packages/apt/Vagrantfile b/storage/mroonga/packages/apt/Vagrantfile
new file mode 100644
index 00000000000..4483412326a
--- /dev/null
+++ b/storage/mroonga/packages/apt/Vagrantfile
@@ -0,0 +1,29 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+
+# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
+VAGRANTFILE_API_VERSION = "2"
+
+Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
+ vms = [
+ {
+ :id => "debian-wheezy-i386",
+ :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_debian-7.8-i386_chef-provisionerless.box",
+ },
+ {
+ :id => "debian-wheezy-amd64",
+ :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_debian-7.8_chef-provisionerless.box",
+ },
+ ]
+
+ vms.each do |vm|
+ config.vm.define(vm[:id]) do |node|
+ node.vm.box = vm[:id]
+ node.vm.box_url = vm[:box_url]
+ node.vm.provision(:shell, :path => "build-deb.sh")
+ node.vm.provider("virtualbox") do |virtual_box|
+ virtual_box.memory = 768
+ end
+ end
+ end
+end
diff --git a/storage/mroonga/packages/apt/build-deb.sh b/storage/mroonga/packages/apt/build-deb.sh
new file mode 100755
index 00000000000..7db24068a7c
--- /dev/null
+++ b/storage/mroonga/packages/apt/build-deb.sh
@@ -0,0 +1,78 @@
+#!/bin/sh
+
+LANG=C
+
+mysql_server_package=mysql-server
+
+run()
+{
+ "$@"
+ if test $? -ne 0; then
+ echo "Failed $@"
+ exit 1
+ fi
+}
+
+. /vagrant/tmp/env.sh
+
+grep '^deb ' /etc/apt/sources.list | \
+ sed -e 's/^deb /deb-src /' > /etc/apt/sources.list.d/base-source.list
+
+run apt-get update
+run apt-get install -y lsb-release
+
+distribution=$(lsb_release --id --short | tr 'A-Z' 'a-z')
+code_name=$(lsb_release --codename --short)
+case "${distribution}" in
+ debian)
+ component=main
+ run cat <<EOF > /etc/apt/sources.list.d/groonga.list
+deb http://packages.groonga.org/debian/ wheezy main
+deb-src http://packages.groonga.org/debian/ wheezy main
+EOF
+ if ! grep --quiet security /etc/apt/sources.list; then
+ run cat <<EOF > /etc/apt/sources.list.d/security.list
+deb http://security.debian.org/ ${code_name}/updates main
+deb-src http://security.debian.org/ ${code_name}/updates main
+EOF
+ fi
+ run apt-get update
+ run apt-get install -y --allow-unauthenticated groonga-keyring
+ run apt-get update
+ ;;
+ ubuntu)
+ component=universe
+ run cat <<EOF > /etc/apt/sources.list.d/security.list
+deb http://security.ubuntu.com/ubuntu ${code_name}-security main restricted
+deb-src http://security.ubuntu.com/ubuntu ${code_name}-security main restricted
+EOF
+ run sed -e 's/main/universe/' /etc/apt/sources.list > \
+ /etc/apt/sources.list.d/universe.list
+ run apt-get -y install software-properties-common
+ run add-apt-repository -y universe
+ run add-apt-repository -y ppa:groonga/ppa
+ run apt-get update
+ ;;
+esac
+
+run apt-get install -V -y build-essential devscripts ${DEPENDED_PACKAGES}
+run apt-get build-dep -y ${mysql_server_package}
+
+run mkdir -p build
+run cp /vagrant/tmp/${PACKAGE}-${VERSION}.tar.gz \
+ build/${PACKAGE}_${VERSION}.orig.tar.gz
+run cd build
+run tar xfz ${PACKAGE}_${VERSION}.orig.tar.gz
+run cd ${PACKAGE}-${VERSION}/
+run cp -rp /vagrant/tmp/debian debian
+# export DEB_BUILD_OPTIONS=noopt
+MYSQL_PACKAGE_INFO=$(apt-cache show mysql-server | grep Version | sort | tail -1)
+MYSQL_PACKAGE_VERSION=${MYSQL_PACKAGE_INFO##Version: }
+sed -i "s/MYSQL_VERSION/$MYSQL_PACKAGE_VERSION/" debian/control
+run debuild -us -uc
+run cd -
+
+package_initial=$(echo "${PACKAGE}" | sed -e 's/\(.\).*/\1/')
+pool_dir="/vagrant/repositories/${distribution}/pool/${code_name}/${component}/${package_initial}/${PACKAGE}"
+run mkdir -p "${pool_dir}/"
+run cp *.tar.gz *.diff.gz *.dsc *.deb "${pool_dir}/"
diff --git a/storage/mroonga/packages/apt/env.sh.in b/storage/mroonga/packages/apt/env.sh.in
new file mode 100644
index 00000000000..a44d6b36871
--- /dev/null
+++ b/storage/mroonga/packages/apt/env.sh.in
@@ -0,0 +1,15 @@
+PACKAGE=@PACKAGE@
+VERSION=@VERSION@
+DEPENDED_PACKAGES="
+debhelper
+autotools-dev
+libgroonga-dev
+pkg-config
+libmecab-dev
+mecab-utils
+libmysqlclient-dev
+libmysqld-dev
+libssl-dev
+groonga-normalizer-mysql
+wget
+"
diff --git a/storage/mroonga/packages/apt/sign-packages.sh b/storage/mroonga/packages/apt/sign-packages.sh
new file mode 100755
index 00000000000..11a4aea26db
--- /dev/null
+++ b/storage/mroonga/packages/apt/sign-packages.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+script_base_dir=`dirname $0`
+
+if [ $# != 3 ]; then
+ echo "Usage: $0 GPG_UID DESITINATION CODES"
+ echo " e.g.: $0 'F10399C0' repositories/ 'lenny unstable hardy karmic'"
+ exit 1
+fi
+
+GPG_UID=$1
+DESTINATION=$2
+CODES=$3
+
+run()
+{
+ "$@"
+ if test $? -ne 0; then
+ echo "Failed $@"
+ exit 1
+ fi
+}
+
+for code_name in ${CODES}; do
+ case ${code_name} in
+ squeeze|wheezy|jessie|unstable)
+ distribution=debian
+ ;;
+ *)
+ distribution=ubuntu
+ ;;
+ esac
+
+ base_directory=${DESTINATION}${distribution}
+ debsign -pgpg2 --re-sign -k${GPG_UID} \
+ $(find ${base_directory} -name '*.dsc' -or -name '*.changes') &
+ if [ "${PARALLEL}" != "yes" ]; then
+ wait
+ fi
+done
+
+wait
diff --git a/storage/mroonga/packages/apt/sign-repository.sh b/storage/mroonga/packages/apt/sign-repository.sh
new file mode 100755
index 00000000000..fb0de850d6f
--- /dev/null
+++ b/storage/mroonga/packages/apt/sign-repository.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+script_base_dir=`dirname $0`
+
+if [ $# != 3 ]; then
+ echo "Usage: $0 GPG_UID DESTINATION CODES"
+ echo " e.g.: $0 'F10399C0' repositories/ 'lenny unstable hardy karmic'"
+ exit 1
+fi
+
+GPG_UID=$1
+DESTINATION=$2
+CODES=$3
+
+run()
+{
+ "$@"
+ if test $? -ne 0; then
+ echo "Failed $@"
+ exit 1
+ fi
+}
+
+for code_name in ${CODES}; do
+ case ${code_name} in
+ squeeze|wheezy|jessie|unstable)
+ distribution=debian
+ ;;
+ *)
+ distribution=ubuntu
+ ;;
+ esac
+
+ release=${DESTINATION}${distribution}/dists/${code_name}/Release
+ rm -f ${release}.gpg
+ gpg2 --sign --detach-sign --armor \
+ --local-user ${GPG_UID} \
+ --output ${release}.gpg \
+ ${release} &
+
+ if [ "${PARALLEL}" != "yes" ]; then
+ wait
+ fi
+done
+
+wait
diff --git a/storage/mroonga/packages/apt/update-repository.sh b/storage/mroonga/packages/apt/update-repository.sh
new file mode 100755
index 00000000000..da1f8cd121c
--- /dev/null
+++ b/storage/mroonga/packages/apt/update-repository.sh
@@ -0,0 +1,130 @@
+#!/bin/sh
+
+script_base_dir=`dirname $0`
+
+if [ $# != 4 ]; then
+ echo "Usage: $0 PROJECT_NAME DESTINATION ARCHITECTURES CODES"
+ echo " e.g.: $0 mroonga repositories/ 'i386 amd64' 'lenny unstable hardy karmic'"
+ exit 1
+fi
+
+PROJECT_NAME=$1
+DESTINATION=$2
+ARCHITECTURES=$3
+CODES=$4
+
+run()
+{
+ "$@"
+ if test $? -ne 0; then
+ echo "Failed $@"
+ exit 1
+ fi
+}
+
+update_repository()
+{
+ distribution=$1
+ code_name=$2
+ component=$3
+
+ rm -rf dists/${code_name}
+ mkdir -p dists/${code_name}/${component}/binary-i386/
+ mkdir -p dists/${code_name}/${component}/binary-amd64/
+ mkdir -p dists/${code_name}/${component}/source/
+
+ cat <<EOF > dists/.htaccess
+Options +Indexes
+EOF
+
+ cat <<EOF > dists/${code_name}/${component}/binary-i386/Release
+Archive: ${code_name}
+Component: ${component}
+Origin: The ${PROJECT_NAME} project
+Label: The ${PROJECT_NAME} project
+Architecture: i386
+EOF
+
+ cat <<EOF > dists/${code_name}/${component}/binary-amd64/Release
+Archive: ${code_name}
+Component: ${component}
+Origin: The ${PROJECT_NAME} project
+Label: The ${PROJECT_NAME} project
+Architecture: amd64
+EOF
+
+ cat <<EOF > dists/${code_name}/${component}/source/Release
+Archive: ${code_name}
+Component: ${component}
+Origin: The ${PROJECT_NAME} project
+Label: The ${PROJECT_NAME} project
+Architecture: source
+EOF
+
+ cat <<EOF > generate-${code_name}.conf
+Dir::ArchiveDir ".";
+Dir::CacheDir ".";
+TreeDefault::Directory "pool/${code_name}/${component}";
+TreeDefault::SrcDirectory "pool/${code_name}/${component}";
+Default::Packages::Extensions ".deb";
+Default::Packages::Compress ". gzip bzip2";
+Default::Sources::Compress ". gzip bzip2";
+Default::Contents::Compress "gzip bzip2";
+
+BinDirectory "dists/${code_name}/${component}/binary-i386" {
+ Packages "dists/${code_name}/${component}/binary-i386/Packages";
+ Contents "dists/${code_name}/Contents-i386";
+ SrcPackages "dists/${code_name}/${component}/source/Sources";
+};
+
+BinDirectory "dists/${code_name}/${component}/binary-amd64" {
+ Packages "dists/${code_name}/${component}/binary-amd64/Packages";
+ Contents "dists/${code_name}/Contents-amd64";
+ SrcPackages "dists/${code_name}/${component}/source/Sources";
+};
+
+Tree "dists/${code_name}" {
+ Sections "${component}";
+ Architectures "i386 amd64 source";
+};
+EOF
+ apt-ftparchive generate generate-${code_name}.conf
+ chmod 644 dists/${code_name}/Contents-*
+
+ rm -f dists/${code_name}/Release*
+ rm -f *.db
+ cat <<EOF > release-${code_name}.conf
+APT::FTPArchive::Release::Origin "The ${PROJECT_NAME} project";
+APT::FTPArchive::Release::Label "The ${PROJECT_NAME} project";
+APT::FTPArchive::Release::Architectures "i386 amd64";
+APT::FTPArchive::Release::Codename "${code_name}";
+APT::FTPArchive::Release::Suite "${code_name}";
+APT::FTPArchive::Release::Components "${component}";
+APT::FTPArchive::Release::Description "${PACKAGE_NAME} packages";
+EOF
+ apt-ftparchive -c release-${code_name}.conf \
+ release dists/${code_name} > /tmp/Release
+ mv /tmp/Release dists/${code_name}
+}
+
+for code_name in ${CODES}; do
+ case ${code_name} in
+ squeeze|wheezy|jessie|unstable)
+ distribution=debian
+ component=main
+ ;;
+ *)
+ distribution=ubuntu
+ component=universe
+ ;;
+ esac
+
+ mkdir -p ${DESTINATION}${distribution}
+ (cd ${DESTINATION}${distribution}
+ update_repository $distribution $code_name $component) &
+ if [ "${PARALLEL}" != "yes" ]; then
+ wait
+ fi
+done
+
+wait
diff --git a/storage/mroonga/packages/check-utility.sh b/storage/mroonga/packages/check-utility.sh
new file mode 100755
index 00000000000..211e231a473
--- /dev/null
+++ b/storage/mroonga/packages/check-utility.sh
@@ -0,0 +1,665 @@
+#!/bin/sh
+
+# Usage: check-utility.sh [--install-groonga]
+# [--check-install]
+# [--check-address]
+# [--enable-repository]
+#
+# CODES="squeeze wheezy unstable lucid natty oneiric precise"
+# DISTRIBUTIONS="centos fedora"
+
+CHROOT_ROOT=/var/lib/chroot
+CHECK_ADDRESS=0
+CHECK_INSTALL=0
+CHECK_INSTALL_PACKAGE=mysql-server-mroonga
+CHECK_BUILD=0
+CHECK_DEPENDS=0
+CHECK_PROVIDES=0
+ENABLE_REPOSITORY=0
+DISABLE_REPOSITORY=0
+INSTALL_SCRIPT=0
+INSTALL_MROONGA=0
+UNINSTALL_MROONGA=0
+
+common_deb_procedure ()
+{
+ for code in $CODES; do
+ for arch in $DEB_ARCHITECTURES; do
+ root_dir=$CHROOT_ROOT/$code-$arch
+ eval $1 $code $arch $root_dir
+ done
+ done
+}
+
+common_rpm_procedure ()
+{
+ for dist in $DISTRIBUTIONS; do
+ case $dist in
+ "fedora")
+ DISTRIBUTIONS_VERSION="19"
+ ;;
+ "centos")
+ DISTRIBUTIONS_VERSION="5 6"
+ ;;
+ esac
+ for ver in $DISTRIBUTIONS_VERSION; do
+ for arch in $RPM_ARCHITECTURES; do
+ root_dir=$CHROOT_ROOT/$dist-$ver-$arch
+ eval $1 $dist $arch $ver $root_dir
+ done
+ done
+ done
+}
+
+echo_packages_repository_address ()
+{
+ root_dir=$1
+ code=$2
+ arch=$3
+ address=`grep "packages.groonga.org" $root_dir/etc/hosts | grep -v "#"`
+ if [ -z "$address" ]; then
+ echo "$code-$arch: default"
+ else
+ echo "$code-$arch: $address"
+ fi
+}
+
+setup_distributions ()
+{
+ if [ -z "$DISTRIBUTIONS" ]; then
+ DISTRIBUTIONS="centos fedora"
+ fi
+}
+
+setup_rpm_architectures ()
+{
+ if [ -z "$RPM_ARCHITECTURES" ]; then
+ RPM_ARCHITECTURES="i386 x86_64"
+ fi
+}
+
+setup_codes ()
+{
+ if [ -z "$CODES" ]; then
+ CODES="squeeze wheezy jessie unstable lucid precise quantal raring"
+ fi
+}
+setup_deb_architectures ()
+{
+ if [ -z "$DEB_ARCHITECTURES" ]; then
+ DEB_ARCHITECTURES="i386 amd64"
+ fi
+}
+
+check_packages_repository_address ()
+{
+ common_deb_procedure "check_packages_deb_repository_address"
+ common_rpm_procedure "check_packages_rpm_repository_address"
+}
+
+check_packages_deb_repository_address ()
+{
+ code=$1
+ arch=$2
+ root_dir=$4
+ echo_packages_repository_address "$root_dir" "$code" "$arch"
+}
+
+check_packages_rpm_repository_address ()
+{
+ dist=$1
+ arch=$2
+ ver=$3
+ root_dir=$4
+ echo_packages_repository_address "$root_dir" "$dist-$ver" "$arch"
+}
+
+host_address ()
+{
+ ifconfig_result=`LANG=C /sbin/ifconfig wlan0`
+ inet_addr=`echo "$ifconfig_result" | grep "inet addr:192"`
+ address=`echo $inet_addr | ruby -ne '/inet addr:(.+?)\s/ =~ $_ && puts($1)'`
+ HOST_ADDRESS=$address
+}
+
+check_build_packages ()
+{
+ common_deb_procedure "check_build_deb_packages"
+ common_rpm_procedure "check_build_rpm_packages"
+}
+
+check_build_deb_packages ()
+{
+ code=$1
+ arch=$2
+ BASE_VERSION=`cat ../version`
+ RESULT_SET=`find apt/repositories -name "*$BASE_VERSION*" | grep $code | grep $arch`
+ if [ -z "$RESULT_SET" ]; then
+ printf "%8s %5s %s => 0 deb\n" $code $arch $BASE_VERSION
+ else
+ PACKAGE_COUNT=`find apt/repositories -name "*$BASE_VERSION*" | grep $code | grep $arch | wc | awk '{print \$1}'`
+ printf "%8s %5s %s => %2d debs\n" $code $arch $BASE_VERSION $PACKAGE_COUNT
+ fi
+}
+
+check_build_rpm_packages ()
+{
+ dist=$1
+ arch=$2
+ ver=$3
+ BASE_VERSION=`cat ../version`
+ FIND_PATH=yum/repositories/$dist/$ver/$arch
+ RESULT_SET=`find $FIND_PATH -name "*$BASE_VERSION*"`
+ if [ -z "$RESULT_SET" ]; then
+ printf "%8s %6s %s => 0 rpm\n" $dist$ver $arch $BASE_VERSION
+ else
+ PACKAGE_COUNT=`find $FIND_PATH -name "*$BASE_VERSION*" | wc -l`
+ printf "%8s %6s %s => %2d rpms\n" $dist$ver $arch $BASE_VERSION $PACKAGE_COUNT
+ fi
+}
+
+check_depends_packages ()
+{
+ common_deb_procedure "check_depends_deb_packages"
+ common_rpm_procedure "check_depends_rpm_packages"
+}
+
+check_depends_deb_packages ()
+{
+ code=$1
+ arch=$2
+ BASE_VERSION=`cat ../version`
+ FIND_PATH=apt/repositories/*/pool/$code
+ RESULT_SET=`find $FIND_PATH -name "*$BASE_VERSION*.deb"`
+ if [ -z "$RESULT_SET" ]; then
+ printf "%8s %5s %s => 404 deb\n" $code $arch $BASE_VERSION
+ else
+ for pkg in $RESULT_SET; do
+ DEB_NAME=`basename $pkg`
+ DEPENDS=`dpkg -I $pkg | grep "Depends"`
+ printf "%8s %5s %s => %s\n" $code $arch $DEB_NAME "$DEPENDS"
+ done
+ fi
+}
+
+check_depends_rpm_packages ()
+{
+ dist=$1
+ arch=$2
+ ver=$3
+ BASE_VERSION=`cat ../version`
+ FIND_PATH=yum/repositories/$dist/$ver/$arch
+ RESULT_SET=`find $FIND_PATH -name "*$BASE_VERSION*"`
+ if [ -z "$RESULT_SET" ]; then
+ printf "%8s %6s %s => 404 rpm\n" $dist$ver $arch $BASE_VERSION
+ else
+ for pkg in $RESULT_SET; do
+ RPM_NAME=`basename $pkg`
+ DEPENDS=`rpm -qp --requires $pkg | grep -i "mysql" | tr -t '\n' ' '`
+ printf "%9s %6s %s => %s\n" $dist$ver $arch $RPM_NAME "$DEPENDS"
+ done
+ fi
+}
+
+check_provided_mysql_packages ()
+{
+ common_deb_procedure "check_provided_mysql_deb_packages"
+ common_rpm_procedure "check_provided_mysql_rpm_packages"
+ for code in $CODES; do
+ echo $code
+ cat tmp/$code-amd64-mysql-server.txt
+ done
+ for dist in $DISTRIBUTIONS; do
+ echo $dist
+ cat tmp/$dist-x86_64-mysql-server.txt
+ done
+}
+
+check_provided_mysql_deb_packages ()
+{
+ code=$1
+ arch=$2
+ root_dir=$3
+ cat > tmp/check-provided-mysql.sh <<EOF
+#!/bin/sh
+apt-get update > /dev/null
+apt-cache show mysql-server | grep "Version" | head -1 > /tmp/$code-$arch-mysql-server.txt
+EOF
+ if [ -d $root_dir ]; then
+ CHECK_SCRIPT=check-provided-mysql.sh
+ echo "copy check script $CHECK_SCRIPT to $root_dir/tmp"
+ sudo rm -f $root_dir/tmp/$CHECK_SCRIPT
+ cp tmp/$CHECK_SCRIPT $root_dir/tmp
+ sudo chmod 755 $root_dir/tmp/$CHECK_SCRIPT
+ sudo chname $code-$arch chroot $root_dir /tmp/$CHECK_SCRIPT
+ cp $root_dir/tmp/$code-$arch-mysql-server.txt tmp
+ fi
+}
+
+check_provided_mysql_rpm_packages ()
+{
+ dist=$1
+ arch=$2
+ ver=$3
+ root_dir=$4
+ cat > tmp/check-provided-mysql.sh <<EOF
+#!/bin/sh
+yum update > /dev/null
+yum info mysql-server | grep "Version" > /tmp/$code-$arch-mysql-server.txt
+EOF
+ if [ -d $root_dir ]; then
+ CHECK_SCRIPT=check-provided-mysql.sh
+ echo "copy check script $CHECK_SCRIPT to $root_dir/tmp"
+ sudo rm -f $root_dir/tmp/$CHECK_SCRIPT
+ cp tmp/$CHECK_SCRIPT $root_dir/tmp
+ sudo chmod 755 $root_dir/tmp/$CHECK_SCRIPT
+ sudo chname $code-$arch chroot $root_dir /tmp/$CHECK_SCRIPT
+ cp $root_dir/tmp/$code-$arch-mysql-server.txt tmp
+ fi
+}
+
+check_installed_mroonga_packages ()
+{
+ common_deb_procedure "check_installed_mroonga_deb_packages"
+ common_rpm_procedure "check_installed_mroonga_rpm_packages"
+}
+
+check_installed_mroonga_deb_packages ()
+{
+ code=$1
+ arch=$2
+ root_dir=$3
+ cat > tmp/check-deb-mroonga.sh <<EOF
+#!/bin/sh
+dpkg -l | grep $CHECK_INSTALL_PACKAGE
+EOF
+ if [ -d $root_dir ]; then
+ CHECK_SCRIPT=check-deb-mroonga.sh
+ echo "copy check script $CHECK_SCRIPT to $root_dir/tmp"
+ sudo rm -f $root_dir/tmp/$CHECK_SCRIPT
+ cp tmp/$CHECK_SCRIPT $root_dir/tmp
+ sudo chmod 755 $root_dir/tmp/$CHECK_SCRIPT
+ sudo chname $code-$arch chroot $root_dir /tmp/$CHECK_SCRIPT
+ fi
+}
+
+check_installed_mroonga_rpm_packages ()
+{
+ dist=$1
+ arch=$2
+ ver=$3
+ root_dir=$4
+ cat > tmp/check-rpm-mroonga.sh <<EOF
+#!/bin/sh
+rpm -qa | grep $CHECK_INSTALL_PACKAGE
+EOF
+ CHECK_SCRIPT=check-rpm-mroonga.sh
+ if [ -d $root_dir ]; then
+ echo "copy check script $CHECK_SCRIPT to $root_dir/tmp"
+ sudo rm -f $root_dir/tmp/$CHECK_SCRIPT
+ cp tmp/$CHECK_SCRIPT $root_dir/tmp
+ sudo chmod 755 $root_dir/tmp/$CHECK_SCRIPT
+ sudo chname $code-$ver-$arch chroot $root_dir /tmp/$CHECK_SCRIPT
+ fi
+}
+
+install_mroonga_packages ()
+{
+ common_deb_procedure "install_mroonga_deb_packages"
+ common_rpm_procedure "install_mroonga_rpm_packages"
+}
+
+install_mroonga_deb_packages ()
+{
+ code=$1
+ arch=$2
+ root_dir=$4
+ cat > tmp/install-aptitude-mroonga.sh <<EOF
+#!/bin/sh
+sudo aptitude clean
+rm -f /var/lib/apt/lists/packages.groonga.org_*
+rm -f /var/lib/apt/lists/partial/packages.groonga.org_*
+sudo aptitude update
+sudo aptitude -V -D -y --allow-untrusted install groonga-keyring
+sudo aptitude update
+sudo aptitude -V -D install mysql-server-mroonga
+sudo aptitude -V -D install groonga-tokenizer-mecab
+EOF
+ cat > tmp/install-aptget-mroonga.sh <<EOF
+#!/bin/sh
+sudo apt-get clean
+rm -f /var/lib/apt/lists/packages.groonga.org_*
+rm -f /var/lib/apt/lists/partial/packages.groonga.org_*
+sudo apt-get update
+sudo apt-get -y --allow-unauthenticated install groonga-keyring
+sudo apt-get update
+sudo apt-get -V -y install mysql-server-mroonga
+sudo apt-get -V -y install groonga-tokenizer-mecab
+EOF
+ root_dir=$CHROOT_ROOT/$code-$arch
+ INSTALL_SCRIPT=""
+ case $code in
+ squeeze|unstable)
+ INSTALL_SCRIPT=install-aptitude-mroonga.sh
+ ;;
+ *)
+ INSTALL_SCRIPT=install-aptget-mroonga.sh
+ ;;
+ esac
+ if [ -d $root_dir ]; then
+ echo "copy install script $INSTALL_SCRIPT to $root_dir/tmp"
+ sudo rm -f $root_dir/tmp/$INSTALL_SCRIPT
+ cp tmp/$INSTALL_SCRIPT $root_dir/tmp
+ chmod 755 $root_dir/tmp/$INSTALL_SCRIPT
+ sudo chname $code-$arch chroot $root_dir /tmp/$INSTALL_SCRIPT
+ fi
+}
+
+install_mroonga_rpm_packages ()
+{
+ dist=$1
+ arch=$2
+ ver=$3
+ root_dir=$4
+ cat > tmp/install-centos5-mroonga.sh <<EOF
+sudo rpm -ivh http://packages.groonga.org/centos/groonga-release-1.1.0-0.noarch.rpm
+sudo yum makecache
+sudo yum install -y MySQL-server
+sudo service mysql start
+sudo yum install -y mysql-mroonga
+sudo yum install -y groonga-tokenizer-mecab
+EOF
+ cat > tmp/install-centos6-mroonga.sh <<EOF
+sudo rpm -ivh http://packages.groonga.org/centos/groonga-release-1.1.0-0.noarch.rpm
+sudo yum makecache
+sudo yum install -y mysql-server
+sudo service mysql start
+sudo yum install -y mysql-mroonga
+sudo yum install -y groonga-tokenizer-mecab
+EOF
+ cat > tmp/install-fedora-mroonga.sh <<EOF
+sudo rpm -ivh http://packages.groonga.org/fedora/groonga-release-1.1.0-0.noarch.rpm
+sudo yum makecache
+sudo yum install -y mysql-mroonga
+sudo yum install -y groonga-tokenizer-mecab
+EOF
+ INSTALL_SCRIPT=""
+ case "$dist-$ver" in
+ centos-5)
+ INSTALL_SCRIPT=install-centos5-mroonga.sh
+ ;;
+ centos-6)
+ INSTALL_SCRIPT=install-centos6-mroonga.sh
+ ;;
+ fedora-18)
+ INSTALL_SCRIPT=install-fedora-mroonga.sh
+ ;;
+ *)
+ ;;
+ esac
+ if [ -d $root_dir ]; then
+ echo "copy install script $INSTALL_SCRIPT to $root_dir/tmp"
+ sudo rm -f $root_dir/tmp/$INSTALL_SCRIPT
+ cp tmp/$INSTALL_SCRIPT $root_dir/tmp
+ chmod 755 $root_dir/tmp/$INSTALL_SCRIPT
+ sudo chname $code-$ver-$arch chroot $root_dir /tmp/$INSTALL_SCRIPT
+ fi
+}
+
+
+uninstall_mroonga_packages ()
+{
+ common_deb_procedure "uninstall_mroonga_deb_packages"
+ common_rpm_procedure "uninstall_mroonga_rpm_packages"
+}
+
+uninstall_mroonga_deb_packages ()
+{
+ code=$1
+ arch=$2
+ root_dir=$4
+ UNINSTALL_SCRIPT=uninstall-deb-mroonga.sh
+ cat > $UNINSTALL_SCRIPT <<EOF
+#!/bin/sh
+sudo apt-get purge mroonga-* mysql-*
+EOF
+ if [ -d $root_dir ]; then
+ echo "copy uninstall script $UNINSTALL_SCRIPT to $root_dir/tmp"
+ sudo rm -f $root_dir/tmp/$UNINSTALL_SCRIPT
+ cp $UNINSTALL_SCRIPT $root_dir/tmp
+ chmod 755 $root_dir/tmp/$UNINSTALL_SCRIPT
+ sudo chname $code-$arch chroot $root_dir /tmp/$UNINSTALL_SCRIPT
+ fi
+}
+
+uninstall_mroonga_rpm_packages ()
+{
+ dist=$1
+ arch=$2
+ ver=$3
+ root_dir=$4
+ UNINSTALL_SCRIPT=uninstall-rpm-mroonga.sh
+ cat > tmp/$UNINSTALL_SCRIPT <<EOF
+#!/bin/sh
+sudo yum remove mroonga-* mysql-*
+EOF
+ if [ -d $root_dir ]; then
+ echo "copy install script $UNINSTALL_SCRIPT to $root_dir/tmp"
+ sudo rm -f $root_dir/tmp/$UNINSTALL_SCRIPT
+ cp tmp/$UNINSTALL_SCRIPT $root_dir/tmp
+ chmod 755 $root_dir/tmp/$UNINSTALL_SCRIPT
+ sudo chname $code-$ver-$arch chroot $root_dir /tmp/$UNINSTALL_SCRIPT
+ fi
+}
+
+
+enable_temporaly_mroonga_repository ()
+{
+ cat > tmp/enable-repository.sh <<EOF
+#!/bin/sh
+
+grep -v "packages.groonga.org" /etc/hosts > /tmp/hosts
+echo "$HOST_ADDRESS packages.groonga.org" >> /tmp/hosts
+cp -f /tmp/hosts /etc/hosts
+EOF
+ common_deb_procedure "enable_temporaly_mroonga_deb_repository"
+ common_rpm_procedure "enable_temporaly_mroonga_rpm_repository"
+ check_packages_repository_address
+}
+
+enable_temporaly_mroonga_deb_repository ()
+{
+ code=$1
+ arch=$2
+ root_dir=$4
+ today=`date '+%Y%m%d.%s'`
+ if [ -d $root_dir ]; then
+ sudo cp $root_dir/etc/hosts $root_dir/etc/hosts.$today
+ sudo cp tmp/enable-repository.sh $root_dir/tmp
+ sudo chname $code-$arch chroot $root_dir /tmp/enable-repository.sh
+ fi
+}
+
+enable_temporaly_mroonga_rpm_repository ()
+{
+ dist=$1
+ arch=$2
+ ver=$3
+ root_dir=$4
+ today=`date '+%Y%m%d.%s'`
+ if [ -d $root_dir ]; then
+ sudo cp $root_dir/etc/hosts $root_dir/etc/hosts.$today
+ sudo cp tmp/enable-repository.sh $root_dir/tmp
+ sudo chname $code-$arch chroot $root_dir /tmp/enable-repository.sh
+ fi
+}
+
+disable_temporaly_mroonga_repository ()
+{
+ cat > tmp/disable-repository.sh <<EOF
+#!/bin/sh
+
+grep -v "packages.groonga.org" /etc/hosts > /tmp/hosts
+cp -f /tmp/hosts /etc/hosts
+EOF
+ common_deb_procedure "disable_temporaly_mroonga_deb_repository"
+ common_rpm_procedure "disable_temporaly_mroonga_rpm_repository"
+ check_packages_repository_address
+}
+
+disable_temporaly_mroonga_deb_repository ()
+{
+ code=$1
+ arch=$2
+ root_dir=$4
+ DISABLE_SCRIPT=disable-repository.sh
+ today=`date '+%Y%m%d.%s'`
+ if [ -d $root_dir ]; then
+ sudo cp $root_dir/etc/hosts $root_dir/etc/hosts.$today
+ cp tmp/$DISABLE_SCRIPT $root_dir/tmp
+ chmod 755 $root_dir/tmp/$DISABLE_SCRIPT
+ sudo chname $code-$arch chroot $root_dir /tmp/$DISABLE_SCRIPT
+ fi
+
+}
+
+disable_temporaly_mroonga_rpm_repository ()
+{
+ dist=$1
+ arch=$2
+ ver=$3
+ root_dir=$4
+ DISABLE_SCRIPT=disable-repository.sh
+ today=`date '+%Y%m%d.%s'`
+ if [ -d $root_dir ]; then
+ sudo cp $root_dir/etc/hosts $root_dir/etc/hosts.$today
+ cp tmp/$DISABLE_SCRIPT $root_dir/tmp
+ chmod 755 $root_dir/tmp/$DISABLE_SCRIPT
+ sudo chname $code-$arch chroot $root_dir /tmp/$DISABLE_SCRIPT
+ fi
+}
+
+host_address
+echo $HOST_ADDRESS
+
+while [ $# -ne 0 ]; do
+ case $1 in
+ --check-install)
+ CHECK_INSTALL=1
+ shift
+ if [ ! -z "$1" ]; then
+ case $1 in
+ groonga|mroonga|roonga|mecab|mysql)
+ CHECK_INSTALL_PACKAGE=$1
+ ;;
+ *)
+ ;;
+ esac
+ fi
+ ;;
+ --check-address)
+ CHECK_ADDRESS=1
+ shift
+ ;;
+ --check-depends)
+ CHECK_DEPENDS=1
+ shift
+ ;;
+ --check-provides)
+ CHECK_PROVIDES=1
+ shift
+ ;;
+ --check-build)
+ CHECK_BUILD=1
+ shift
+ ;;
+ --enable-repository)
+ ENABLE_REPOSITORY=1
+ shift
+ ;;
+ --disable-repository)
+ DISABLE_REPOSITORY=1
+ shift
+ ;;
+ --install-mroonga)
+ INSTALL_MROONGA=1
+ shift
+ ;;
+ --uninstall-mroonga)
+ UNINSTALL_MROONGA=1
+ shift
+ ;;
+ --code)
+ shift
+ if [ "$1" = "all" ]; then
+ setup_codes
+ else
+ CODES=$1
+ fi
+ shift
+ ;;
+ --code-arch)
+ shift
+ if [ "$1" = "all" ]; then
+ setup_deb_architectures
+ else
+ DEB_ARCHITECTURES=$1
+ fi
+ shift
+ ;;
+ --dist)
+ shift
+ if [ "$1" = "all" ]; then
+ setup_distributions
+ else
+ DISTRIBUTIONS=$1
+ fi
+ shift
+ ;;
+ --dist-arch)
+ shift
+ if [ "$1" = "all" ]; then
+ setup_rpm_architectures
+ else
+ RPM_ARCHITECTURES=$1
+ fi
+ shift
+ ;;
+ *)
+ shift
+ ;;
+ esac
+done
+
+mkdir -p tmp
+setup_deb_architectures
+setup_rpm_architectures
+
+if [ $CHECK_INSTALL -ne 0 ]; then
+ check_installed_mroonga_packages
+fi
+if [ $CHECK_ADDRESS -ne 0 ]; then
+ check_packages_repository_address
+fi
+if [ $CHECK_BUILD -ne 0 ]; then
+ check_build_packages
+fi
+if [ $CHECK_DEPENDS -ne 0 ]; then
+ check_depends_packages
+fi
+if [ $CHECK_PROVIDES -ne 0 ]; then
+ check_provided_mysql_packages
+fi
+if [ $ENABLE_REPOSITORY -ne 0 ]; then
+ enable_temporaly_mroonga_repository
+fi
+if [ $DISABLE_REPOSITORY -ne 0 ]; then
+ disable_temporaly_mroonga_repository
+fi
+if [ $INSTALL_MROONGA -ne 0 ]; then
+ install_mroonga_packages
+fi
+if [ $UNINSTALL_MROONGA -ne 0 ]; then
+ uninstall_mroonga_packages
+fi
+
diff --git a/storage/mroonga/packages/debian/apparmor/mysql-server-mroonga b/storage/mroonga/packages/debian/apparmor/mysql-server-mroonga
new file mode 100644
index 00000000000..259f8d1dc0c
--- /dev/null
+++ b/storage/mroonga/packages/debian/apparmor/mysql-server-mroonga
@@ -0,0 +1,5 @@
+/usr/lib/groonga/plugins/ r,
+/usr/lib/groonga/plugins/** rm,
+/etc/mecabrc r,
+/var/lib/mecab/dic/** r,
+#include <local/mysql-server-mroonga>
diff --git a/storage/mroonga/packages/debian/changelog b/storage/mroonga/packages/debian/changelog
new file mode 100644
index 00000000000..6aa6fd58d17
--- /dev/null
+++ b/storage/mroonga/packages/debian/changelog
@@ -0,0 +1,391 @@
+mroonga (5.00-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- <hayashi@clear-code.com> Mon, 09 Feb 2015 00:00:00 +0900
+
+mroonga (4.10-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Thu, 29 Jan 2015 00:00:00 +0900
+
+mroonga (4.09-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Kouhei Sutou <kou@cozmixng.org> Mon, 29 Dec 2014 00:00:00 +0900
+
+mroonga (4.08-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Sat, 29 Nov 2014 00:00:00 +0900
+
+mroonga (4.07-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Kouhei Sutou <kou@clear-code.com> Wed, 29 Oct 2014 00:00:00 +0900
+
+mroonga (4.06-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Kouhei Sutou <kou@clear-code.com> Mon, 29 Sep 2014 00:00:00 +0900
+
+mroonga (4.05-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Kouhei Sutou <kou@clear-code.com> Fri, 29 Aug 2014 00:00:00 +0900
+
+mroonga (4.04-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Tue, 29 Jul 2014 00:00:00 +0900
+
+mroonga (4.03-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Kouhei Sutou <kou@clear-code.com> Thu, 29 May 2014 00:00:00 +0900
+
+mroonga (4.02-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Kouhei Sutou <kou@clear-code.com> Tue, 29 Apr 2014 00:00:00 +0900
+
+mroonga (4.01-2) unstable; urgency=low
+
+ * Built for mysql-server 5.5.37
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Mon, 28 Apr 2014 00:00:00 +0900
+
+mroonga (4.01-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Sat, 29 Mar 2014 00:00:00 +0900
+
+mroonga (4.00-2) unstable; urgency=low
+
+ * Built for mysql-server 5.5.35+dfsg-2 on Debian jessie
+ * Built for mysql-server 5.5.35+dfsg-2 on Debian sid
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Thu, 06 Mar 2014 00:00:00 +0900
+
+mroonga (4.00-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Sun, 09 Feb 2014 00:00:00 +0900
+
+mroonga (3.12-2) unstable; urgency=low
+
+ * Built for mysql-server updates on Ubuntu 12.04,12.10, and 13.10.
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Wed, 29 Jan 2014 13:12:56 +0900
+
+mroonga (3.12-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Wed, 29 Jan 2014 00:00:00 +0900
+
+mroonga (3.11-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Sun, 29 Dec 2013 00:00:00 +0900
+
+mroonga (3.10-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Fri, 29 Nov 2013 00:00:00 +0900
+
+mroonga (3.09-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Tue, 29 Oct 2013 00:00:00 +0900
+
+mroonga (3.08-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Sun, 29 Sep 2013 00:00:00 +0900
+
+mroonga (3.07-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Thu, 29 Aug 2013 00:00:00 +0900
+
+mroonga (3.06-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Mon, 29 Jul 2013 00:00:00 +0900
+
+mroonga (3.05-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Sat, 29 Jun 2013 00:00:00 +0900
+
+mroonga (3.04-2) unstable; urgency=low
+
+ * Built for mysql-server 5.5.31-0ubuntu0.12.04.2 on Ubuntu 12.04 (precise)
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Thu, 13 Jun 2013 00:00:00 +0900
+
+mroonga (3.04-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Wed, 29 May 2013 00:00:00 +0900
+
+mroonga (3.03-2) unstable; urgency=low
+
+ * Built for mysql-server 5.5.31+dfsg-0+wheezy1 on Debian wheezy
+ * Built for mysql-server 5.5.31+dfsg-1 on Debian unstable
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Thu, 16 May 2013 00:00:00 +0900
+
+mroonga (3.03-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Mon, 29 Apr 2013 00:00:00 +0900
+
+mroonga (3.02-2) unstable; urgency=low
+
+ * Built for mysql-server 5.5.29-0ubuntu0.12.04.2 on Ubuntu 12.04 (precise)
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Fri, 29 Mar 2013 22:15:39 +0900
+
+mroonga (3.02-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Fri, 29 Mar 2013 00:00:00 +0900
+
+mroonga (3.01-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Thu, 28 Feb 2013 00:00:00 +0900
+
+mroonga (3.00-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Sat, 09 Feb 2013 00:00:00 +0900
+
+mroonga (2.10-2) unstable; urgency=low
+
+ * Built for mysql-server 5.5.29+dfsg-1 on Debian/unstable.
+ * Built for mysql-server 5.1.67-0ubuntu0.10.04.1 on Ubuntu 10.04(lucid).
+ * Built for mysql-server 5.1.67-0ubuntu0.11.10.1 on Ubuntu 11.10(oneiric).
+ * Built for mysql-server 5.5.29-0ubuntu0.12.04.1 on Ubuntu 12.04(precise).
+ * Built for mysql-server 5.5.29-0ubuntu0.12.10.1 on Ubuntu 12.10(quantal).
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Thu, 24 Jan 2013 10:28:16 +0900
+
+mroonga (2.10-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Sat, 29 Dec 2012 00:00:00 +0900
+
+mroonga (2.09-2) unstable; urgency=low
+
+ * Built for mysql-server 5.5.28-0ubuntu0.12.10.2 on Ubuntu 12.10.
+ Reported by @watanabekiyokaz
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Wed, 12 Dec 2012 13:28:00 +0900
+
+mroonga (2.09-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Thu, 29 Nov 2012 00:00:00 +0900
+
+mroonga (2.08-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Mon, 29 Oct 2012 00:00:00 +0900
+
+mroonga (2.07-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Sat, 29 Sep 2012 00:00:00 +0900
+
+mroonga (2.06-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Kouhei Sutou <kou@clear-code.com> Wed, 29 Aug 2012 00:00:00 +0900
+
+mroonga (2.05-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- HAYASHI Kentaro <hayashi@clear-code.com> Sun, 29 Jul 2012 00:00:00 +0900
+
+mroonga (2.04-1) unstable; urgency=low
+
+ * New upstream release.
+ * Ensure deleting mroonga plugin before install.
+ Suggested by Kazuhiro Isobe. Thanks!!!
+
+ -- Kouhei Sutou <kou@clear-code.com> Fri, 29 Jun 2012 00:00:00 +0900
+
+mroonga (2.03-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Kouhei Sutou <kou@clear-code.com> Tue, 29 May 2012 00:00:00 +0900
+
+mroonga (2.02-1) unstable; urgency=low
+
+ * New upstream release.
+ * Require groonga >= 2.0.2.
+
+ -- Kouhei Sutou <kou@clear-code.com> Sun, 29 Apr 2012 00:00:00 +0900
+
+mroonga (2.01-1) unstable; urgency=low
+
+ * New upstream release.
+ * Ensure plugin is uninstalled by closing all tables use mroonga.
+
+ -- Kouhei Sutou <kou@clear-code.com> Thu, 29 Mar 2012 00:00:00 +0900
+
+mroonga (2.00-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Kouhei Sutou <kou@clear-code.com> Wed, 29 Feb 2012 00:00:00 +0900
+
+mroonga (1.20-1) unstable; urgency=low
+
+ * New upstream release.
+ * Add mysql-server-mroonga-compatible package for "groonga" storage engine.
+
+ -- Kouhei Sutou <kou@clear-code.com> Sun, 29 Jan 2012 00:00:00 +0900
+
+mroonga (1.11-1) unstable; urgency=low
+
+ * New upstream release.
+ * Change apparmor configuration file name:
+ mysql-server-groonga -> mysql-server-mroonga
+
+ -- Kouhei Sutou <kou@clear-code.com> Thu, 29 Dec 2011 00:00:00 +0900
+
+mroonga (1.10-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Kouhei Sutou <kou@clear-code.com> Sat, 29 Oct 2011 00:00:00 +0900
+
+groonga-storage-engine (1.0.0-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Kouhei Sutou <kou@clear-code.com> Thu, 29 Sep 2011 00:00:00 +0900
+
+groonga-storage-engine (0.9-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Kouhei Sutou <kou@clear-code.com> Mon, 29 Aug 2011 00:00:00 +0900
+
+groonga-storage-engine (0.8-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Kouhei Sutou <kou@clear-code.com> Fri, 29 Jul 2011 00:00:00 +0900
+
+groonga-storage-engine (0.7-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Kouhei Sutou <kou@clear-code.com> Wed, 29 Jun 2011 00:00:00 +0900
+
+groonga-storage-engine (0.6-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Kouhei Sutou <kou@clear-code.com> Sun, 29 May 2011 00:00:00 +0900
+
+groonga-storage-engine (0.5-4) unstable; urgency=low
+
+ * fix a typo.
+
+ -- Kouhei Sutou <kou@clear-code.com> Tue, 30 Mar 2011 01:05:00 +0900
+
+groonga-storage-engine (0.5-3) unstable; urgency=low
+
+ * fix AppArmor files.
+
+ -- Kouhei Sutou <kou@clear-code.com> Tue, 30 Mar 2011 00:59:00 +0900
+
+groonga-storage-engine (0.5-2) unstable; urgency=low
+
+ * hook script fix.
+
+ -- Kouhei Sutou <kou@clear-code.com> Tue, 30 Mar 2011 00:58:00 +0900
+
+groonga-storage-engine (0.5-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Kouhei Sutou <kou@clear-code.com> Tue, 29 Mar 2011 00:00:00 +0900
+
+groonga-storage-engine (0.4-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Kouhei Sutou <kou@clear-code.com> Mon, 29 Nov 2010 00:00:00 +0900
+
+groonga-storage-engine (0.3-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Kouhei Sutou <kou@clear-code.com> Fri, 29 Oct 2010 16:34:04 +0900
+
+groonga-storage-engine (0.2-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Kouhei Sutou <kou@clear-code.com> Sat, 25 Sep 2010 14:52:49 +0900
+
+groonga-storage-engine (0.1-4) unstable; urgency=low
+
+ * follow configure option changes.
+
+ -- Kouhei Sutou <kou@cozmixng.org> Fri, 10 Sep 2010 08:45:53 +0900
+
+groonga-storage-engine (0.1-3) unstable; urgency=low
+
+ * Use HEAD.
+
+ -- Kouhei Sutou <kou@clear-code.com> Thu, 02 Sep 2010 12:03:46 +0900
+
+groonga-storage-engine (0.1-2) unstable; urgency=low
+
+ * Built with groonga 1.0.0.
+
+ -- Kouhei Sutou <kou@cozmixng.org> Mon, 30 Aug 2010 13:26:25 +0900
+
+groonga-storage-engine (0.1-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Kouhei Sutou <kou@clear-code.com> Mon, 23 Aug 2010 13:52:01 +0900
diff --git a/storage/mroonga/packages/debian/compat b/storage/mroonga/packages/debian/compat
new file mode 100644
index 00000000000..ec635144f60
--- /dev/null
+++ b/storage/mroonga/packages/debian/compat
@@ -0,0 +1 @@
+9
diff --git a/storage/mroonga/packages/debian/control.in b/storage/mroonga/packages/debian/control.in
new file mode 100644
index 00000000000..d6d03fa9a4e
--- /dev/null
+++ b/storage/mroonga/packages/debian/control.in
@@ -0,0 +1,51 @@
+Source: mroonga
+Section: database
+Priority: optional
+Maintainer: Kouhei Sutou <kou@clear-code.com>
+Build-Depends:
+ debhelper (>= 7.0.50),
+ autotools-dev,
+ pkg-config,
+ libgroonga-dev (>= @REQUIRED_GROONGA_VERSION@),
+ groonga-normalizer-mysql,
+ libmysqlclient-dev,
+ libmysqld-dev,
+ libssl-dev,
+ wget,
+ lsb-release
+Standards-Version: 3.9.1
+Homepage: http://mroonga.org/
+
+Package: mysql-server-mroonga
+Section: database
+Architecture: any
+Replaces: mysql-server-groonga (<< 1.10-1)
+Breaks: mysql-server-groonga (<< 1.10-1)
+Depends:
+ ${misc:Depends},
+ ${shlibs:Depends},
+ libgroonga0 (>= @REQUIRED_GROONGA_VERSION@),
+ mysql-server (= MYSQL_VERSION),
+ groonga-normalizer-mysql
+Description: A fast fulltext searchable storage engine for MySQL.
+ Mroonga is a fast fulltext searchable storage engine for MySQL.
+ It is based on Groonga, a fast fulltext search engine and column store.
+ Groonga is good at real time update.
+ .
+ This package provides a MySQL storage engine as a shared library.
+ This provides "mroonga" storage engine. It means you can use
+ "ENGINE = mroonga" in "CREATE TABLE".
+
+Package: mysql-server-mroonga-doc
+Section: doc
+Architecture: all
+Replaces: mysql-server-groonga-doc (<< 1.10-1)
+Breaks: mysql-server-groonga-doc (<< 1.10-1)
+Depends:
+ ${misc:Depends}
+Description: Documentation of Mroonga.
+ Mroonga is a fast fulltext searchable storage engine for MySQL.
+ It is based on Groonga, a fast fulltext search engine and column store.
+ Groonga is good at real time update.
+ .
+ This package provides documentation of Mroonga.
diff --git a/storage/mroonga/packages/debian/copyright b/storage/mroonga/packages/debian/copyright
new file mode 100644
index 00000000000..bb41984e8e4
--- /dev/null
+++ b/storage/mroonga/packages/debian/copyright
@@ -0,0 +1,27 @@
+This work was packaged for Debian by:
+
+ Kouhei Sutou <kou@clear-code.com> on Thu, 02 Sep 2010 13:51:56 +0900.
+
+It was downloaded:
+
+ <http://github.com/mroonga/mroonga/downloads>
+
+Upstream Author(s):
+
+ Tetsuro IKEDA <ikdttr at gmail.com>
+ Daijiro MORI <morita at razil. jp>
+ Tasuku SUENAGA <a at razil. jp>
+ Kouhei Sutou <kou at clear-code. com>
+
+Copyright:
+
+ Copyright(C) 2009-2010 Tetsuro IKEDA
+
+License:
+
+ LGPLv2.1
+
+ See `/usr/share/common-licenses/LGPL-2.1'.
+
+The Debian packaging is done by Kouhei Sutou <kou@clear-code.com> in 2010,
+and put into public domain, anyone can use it for any purpose.
diff --git a/storage/mroonga/packages/debian/mysql-server-mroonga-doc.install b/storage/mroonga/packages/debian/mysql-server-mroonga-doc.install
new file mode 100644
index 00000000000..ad2e27ef7dd
--- /dev/null
+++ b/storage/mroonga/packages/debian/mysql-server-mroonga-doc.install
@@ -0,0 +1 @@
+usr/share/doc/mysql-server-mroonga-doc/
diff --git a/storage/mroonga/packages/debian/mysql-server-mroonga.install b/storage/mroonga/packages/debian/mysql-server-mroonga.install
new file mode 100644
index 00000000000..03f64cfedb4
--- /dev/null
+++ b/storage/mroonga/packages/debian/mysql-server-mroonga.install
@@ -0,0 +1,3 @@
+usr/lib/mysql/plugin/ha_mroonga.so*
+usr/share/mroonga/*
+debian/apparmor/mysql-server-mroonga etc/apparmor.d/abstractions/
diff --git a/storage/mroonga/packages/debian/mysql-server-mroonga.postinst b/storage/mroonga/packages/debian/mysql-server-mroonga.postinst
new file mode 100755
index 00000000000..9a3db8784a2
--- /dev/null
+++ b/storage/mroonga/packages/debian/mysql-server-mroonga.postinst
@@ -0,0 +1,72 @@
+#! /bin/sh
+
+set -e
+
+prevver="$2"
+
+install_plugin() {
+ cat /usr/share/mroonga/install.sql | \
+ mysql --defaults-file=/etc/mysql/debian.cnf || true
+}
+
+install_apparmor() {
+ mysql_apparmor_profile_name=usr.sbin.mysqld
+ mysql_apparmor_profile=/etc/apparmor.d/${mysql_apparmor_profile_name}
+ mysql_local_apparmor_profile=/etc/apparmor.d/local/${mysql_apparmor_profile_name}
+ apparmor_profile_name=mysql-server-mroonga
+ include_profile="#include <abstractions/${apparmor_profile_name}>"
+ local_apparmor_profile=/etc/apparmor.d/local/${apparmor_profile_name}
+ if test -f "${mysql_local_apparmor_profile}"; then
+ if ! grep -q "${include_profile}" "${mysql_local_apparmor_profile}"; then
+ echo >> "${mysql_local_apparmor_profile}"
+ echo "${include_profile}" >> "${mysql_local_apparmor_profile}"
+ fi
+ else
+ mysql_abstraction_apparmor_profile=/etc/apparmor.d/abstractions/mysql
+ mysql_plugin_dir=/usr/lib/mysql/plugin
+ if test -f "${mysql_abstraction_apparmor_profile}" && \
+ ! grep -q "${mysql_plugin_dir}" \
+ "${mysql_abstraction_apparmor_profile}"; then
+ # For Lucid.
+ cat <<EOF >> "${mysql_abstraction_apparmor_profile}"
+
+# ${apparmor_profile_name}: START
+# Added by mysql-server-mroonga.
+${mysql_plugin_dir}/ r,
+${mysql_plugin_dir}/*.so* mr,
+${include_profile}
+# ${apparmor_profile_name}: END
+EOF
+ fi
+ fi
+
+ if ! test -e "$local_apparmor_profile"; then
+ mkdir -p $(dirname "$local_apparmor_profile")
+ cat <<EOF > "$local_apparmor_profile"
+# Site-specific additions and overrides for ${apparmor_profile_name}.
+# For more details, please see /etc/apparmor.d/local/README.
+EOF
+ fi
+
+ if aa-status --enabled 2>/dev/null; then
+ apparmor_parser -r -T -W "${mysql_apparmor_profile}" || true
+ fi
+
+ true
+}
+
+case "$1" in
+ configure)
+ install_apparmor
+ install_plugin
+ ;;
+ abort-upgrade|abort-deconfigure|abort-remove)
+ :
+ ;;
+ *)
+ echo "Called with unknown argument $1, bailing out."
+ exit 1
+ ;;
+esac
+
+#DEBHELPER#
diff --git a/storage/mroonga/packages/debian/mysql-server-mroonga.postrm b/storage/mroonga/packages/debian/mysql-server-mroonga.postrm
new file mode 100755
index 00000000000..84d7f1ef4ab
--- /dev/null
+++ b/storage/mroonga/packages/debian/mysql-server-mroonga.postrm
@@ -0,0 +1,38 @@
+#! /bin/sh
+
+set -e
+
+if [ "$1" = "purge" ]; then
+ mysql_apparmor_profile_name=usr.sbin.mysqld
+ mysql_apparmor_profile=/etc/apparmor.d/${mysql_apparmor_profile_name}
+ mysql_local_apparmor_profile=/etc/apparmor.d/local/${mysql_apparmor_profile_name}
+ mysql_abstraction_apparmor_profile=/etc/apparmor.d/abstractions/mysql
+ apparmor_profile_name=mysql-server-mroonga
+ if test -f "${mysql_local_apparmor_profile}"; then
+ include_profile="#include <abstractions/${apparmor_profile_name}>"
+ if grep -q "${include_profile}" "${mysql_local_apparmor_profile}"; then
+ sed -i'' -e "s,${include_profile},," \
+ "${mysql_local_apparmor_profile}"
+ fi
+ else
+ start_marker_re="^# ${apparmor_profile_name}: START$"
+ end_marker_re="^# ${apparmor_profile_name}: END$"
+ if test -f "${mysql_abstraction_apparmor_profile}" && \
+ grep -q "${start_marker_re}" \
+ "${mysql_abstraction_apparmor_profile}"; then
+ sed -i'' -e "/${start_marker_re}/,/${end_marker_re}/d" \
+ "${mysql_abstraction_apparmor_profile}"
+ fi
+ fi
+
+ rm -f "/etc/apparmor.d/local/${apparmor_profile_name}" || true
+ rmdir /etc/apparmor.d/local 2>/dev/null || true
+
+ if aa-status --enabled 2>/dev/null; then
+ apparmor_parser -r -T -W "${mysql_apparmor_profile}" || true
+ fi
+fi
+
+#DEBHELPER#
+
+exit 0
diff --git a/storage/mroonga/packages/debian/mysql-server-mroonga.prerm b/storage/mroonga/packages/debian/mysql-server-mroonga.prerm
new file mode 100755
index 00000000000..7fad990d75f
--- /dev/null
+++ b/storage/mroonga/packages/debian/mysql-server-mroonga.prerm
@@ -0,0 +1,10 @@
+#! /bin/sh
+
+set -e
+
+cat /usr/share/mroonga/uninstall.sql | \
+ mysql --defaults-file=/etc/mysql/debian.cnf || true
+
+#DEBHELPER#
+
+exit 0
diff --git a/storage/mroonga/packages/debian/rules b/storage/mroonga/packages/debian/rules
new file mode 100755
index 00000000000..2a397b333e1
--- /dev/null
+++ b/storage/mroonga/packages/debian/rules
@@ -0,0 +1,39 @@
+#!/usr/bin/make -f
+# -*- makefile-gmake -*-
+#
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+# This has to be exported to make some magic below work.
+export DH_OPTIONS
+
+export MYSQL_VERSION := $(shell apt-cache show mysql-server-5.5 | grep Version | head -n 1 | awk '{print $$2}' | awk -F '-' '{print $$1}')
+
+%:
+ dh $@
+
+override_dh_auto_configure:
+ path=main/m/mysql-5.5/mysql-5.5_$(MYSQL_VERSION).orig.tar.gz; \
+ if [ "$$(lsb_release --id --short)" = "Ubuntu" ]; then \
+ base_url=http://archive.ubuntu.com/ubuntu/pool; \
+ security_base_url=http://security.ubuntu.com/ubuntu/pool; \
+ else \
+ base_url=http://ftp.debian.org/debian/pool; \
+ security_base_url=http://security.debian.org/pool/updates; \
+ fi; \
+ wget $${security_base_url}/$${path} || \
+ wget $${base_url}/$${path}
+ tar xf mysql-5.5_$(MYSQL_VERSION).orig.tar.gz
+ dh_auto_configure -- --with-mysql-source=./mysql-$(MYSQL_VERSION)
+
+# disable 'make check'.
+override_dh_auto_test:
+
+override_dh_install:
+ mv debian/tmp/usr/share/doc/mroonga/ \
+ debian/tmp/usr/share/doc/mysql-server-mroonga-doc/
+ dh_install
+# if test -x /usr/bin/dh_apparmor; then \
+# dh_apparmor \
+# -pmysql-server-mroonga \
+# --profile-name=usr.lib.mysql.plugin.ha_mroonga; \
+# fi
diff --git a/storage/mroonga/packages/rpm/Makefile.am b/storage/mroonga/packages/rpm/Makefile.am
new file mode 100644
index 00000000000..aa1ba3ad9c6
--- /dev/null
+++ b/storage/mroonga/packages/rpm/Makefile.am
@@ -0,0 +1,2 @@
+SUBDIRS = \
+ centos
diff --git a/storage/mroonga/packages/rpm/centos/Makefile.am b/storage/mroonga/packages/rpm/centos/Makefile.am
new file mode 100644
index 00000000000..e7b22cfa025
--- /dev/null
+++ b/storage/mroonga/packages/rpm/centos/Makefile.am
@@ -0,0 +1,9 @@
+EXTRA_DIST = \
+ mysql55-mroonga.spec.in \
+ mysql56-community-mroonga.spec.in \
+ mariadb-mroonga.spec.in
+
+noinst_DATA = \
+ mysql55-mroonga.spec \
+ mysql56-community-mroonga.spec \
+ mariadb-mroonga.spec
diff --git a/storage/mroonga/packages/rpm/centos/mariadb-mroonga.spec.in b/storage/mroonga/packages/rpm/centos/mariadb-mroonga.spec.in
new file mode 100644
index 00000000000..337eeccb1cf
--- /dev/null
+++ b/storage/mroonga/packages/rpm/centos/mariadb-mroonga.spec.in
@@ -0,0 +1,396 @@
+%define mariadb_epoch_default 1
+%define mariadb_version_default 5.5.41
+%define mariadb_release_default 1
+%define mariadb_dist_default .el7_0
+%define mariadb_download_base_url_default http://vault.centos.org/7.0.1406/updates/Source/SPackages
+%define mariadb_spec_file_default mariadb.spec
+
+%{!?mariadb_epoch:%define mariadb_epoch %{mariadb_epoch_default}}
+%{!?mariadb_version:%define mariadb_version %{mariadb_version_default}}
+%{!?mariadb_release:%define mariadb_release %{mariadb_release_default}}
+%{!?mariadb_dist:%define mariadb_dist %{mariadb_dist_default}}
+%{!?mariadb_download_base_url:%define mariadb_download_base_url %{mariadb_download_base_url_default}}
+%{!?mariadb_spec_file:%define mariadb_spec_file %{mariadb_spec_file_default}}
+
+%define mariadb_package_version %{mariadb_epoch}:%{mariadb_version}-%{mariadb_release}%{mariadb_dist}
+
+%define groonga_required_version @REQUIRED_GROONGA_VERSION@
+
+Name: mariadb-mroonga
+Version: @VERSION@
+Release: 1%{?dist}
+Summary: A fast fulltext searchable storage engine for MariaDB
+
+Group: Applications/Databases
+License: LGPLv2.1
+URL: http://mroonga.org/
+Source0: http://packages.groonga.org/source/mroonga/mroonga-%{version}.tar.gz
+
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-%(%{__id_u} -n)
+BuildRequires: groonga-devel >= %{groonga_required_version}
+BuildRequires: groonga-normalizer-mysql-devel
+BuildRequires: wget
+BuildRequires: mariadb-devel
+Requires: mariadb-server = %{mariadb_package_version}
+Requires: mariadb = %{mariadb_package_version}
+Requires: groonga-libs >= %{groonga_required_version}
+Requires: groonga-normalizer-mysql
+
+%description
+Mroonga is a fast fulltext searchable storage plugin for MariaDB.
+It is based on Groonga that is a fast fulltext search engine and
+column store. Groonga is good at real-time update.
+
+%package doc
+Summary: Documentation for Mroonga
+Group: Documentation
+License: LGPLv2.1
+
+%description doc
+Documentation for Mroonga
+
+
+%prep
+%setup -q -n mroonga-%{version}
+
+mariadb_full_version=%{mariadb_version}-%{mariadb_release}%{mariadb_dist}
+srpm=mariadb-${mariadb_full_version}.src.rpm
+if [ ! -f ../../SRPMS/$srpm ]; then
+ wget --continue -O ../../SRPMS/$srpm %{mariadb_download_base_url}/$srpm
+ rpm -Uvh ../../SRPMS/$srpm
+ rm ../../SRPMS/$srpm
+fi
+
+%build
+mariadb_source=../mariadb-%{mariadb_version}
+if [ ! -d ${mariadb_source} ]; then
+ rpmbuild -bc \
+ --define 'runselftest 0' \
+ --define 'optflags -O0' \
+ ../../SPECS/%{mariadb_spec_file}
+fi
+%configure \
+ --disable-static \
+ --with-mysql-source=${mariadb_source} \
+ %{?mroonga_configure_options}
+make %{?_smp_mflags}
+
+
+%install
+rm -rf $RPM_BUILD_ROOT
+make install DESTDIR=$RPM_BUILD_ROOT
+rm $RPM_BUILD_ROOT%{_libdir}/mysql/plugin/*.la
+mv $RPM_BUILD_ROOT%{_datadir}/doc/mroonga/ mysql-mroonga-doc/
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+if /usr/bin/mysql -u root -e "quit"; then
+ password_option=""
+else
+ password_option="-p"
+fi
+current_version=0
+version=$(echo %{groonga_required_version} | sed -e 's/\.//g')
+required_version=$(expr $version)
+version=$(/usr/bin/mysql -e "SHOW VARIABLES LIKE 'mroonga_libgroonga_version'" | \
+ grep mroonga | cut -f 2 | sed -e 's/\.//g')
+if [ -n "$version" ]; then
+ current_version=$(expr $version)
+fi
+install_sql=%{_datadir}/mroonga/install.sql
+uninstall_sql=%{_datadir}/mroonga/uninstall.sql
+
+if [ "$1" = 2 ] ; then
+ if [ $current_version -lt $required_version ]; then
+ command="/usr/bin/mysql -u root $password_option"
+ echo "run the following command after restarting MySQL server:";
+ echo " $command < ${uninstall_sql}"
+ echo " $command < ${install_sql}"
+ exit 0
+ else
+ command="/usr/bin/mysql -u root $password_option"
+ command="${command} < ${uninstall_sql}"
+ echo $command
+ eval $command || \
+ (echo "run the following command to unregister Mroonga:"; \
+ echo " $command")
+ fi
+fi
+
+command="/usr/bin/mysql -u root $password_option < ${install_sql}"
+echo $command
+eval $command || \
+ (echo "run the following command to register Mroonga:"; \
+ echo " $command")
+
+%preun
+uninstall_sql=%{_datadir}/mroonga/uninstall.sql
+
+if mysql -u root -e "quit"; then
+ password_option=""
+else
+ password_option="-p"
+fi
+if [ "$1" = 0 ]; then
+ command="/usr/bin/mysql -u root $password_option < ${uninstall_sql}"
+ echo $command
+ eval $command || \
+ (echo "run the following command to unregister Mroonga:"; \
+ echo " $command")
+fi
+
+%files
+%defattr(-,root,root,-)
+%{_libdir}/mysql/plugin/
+%{_datadir}/mroonga/*
+%{_datadir}/man/man1/*
+%{_datadir}/man/*/man1/*
+
+%files doc
+%defattr(-,root,root,-)
+%doc README COPYING
+%doc mysql-mroonga-doc/*
+
+%changelog
+* Mon Feb 09 2015 <hayashi@clear-code.com> - 5.00-1
+- new upstream release.
+
+* Thu Jan 29 2015 HAYASHI Kentaro <hayashi@clear-code.com> - 4.10-1
+- new upstream release.
+
+* Wed Jan 14 2015 HAYASHI Kentaro <hayashi@clear-code.com> - 4.09-2
+- build against mariadb-5.5.40-2.el7_0.
+
+* Mon Dec 29 2014 Kouhei Sutou <kou@cozmixng.org> - 4.09-1
+- new upstream release.
+
+* Sat Nov 29 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.08-1
+- new upstream release.
+
+* Wed Oct 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.07-1
+- new upstream release.
+
+* Mon Sep 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.06-1
+- new upstream release.
+
+* Fri Aug 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.05-1
+- new upstream release.
+
+* Thu Aug 14 2014 Kouhei Sutou <kou@clear-code.com> - 4.04-4
+- build MariaDB for libmysqlservices.a.
+
+* Thu Aug 14 2014 Kouhei Sutou <kou@clear-code.com> - 4.04-3
+- support epoch in MariaDB.
+
+* Wed Aug 13 2014 Kouhei Sutou <kou@clear-code.com> - 4.04-2
+- build against mariadb-5.5.37-1.el7_0.
+
+* Sun Aug 10 2014 Kouhei Sutou <kou@clear-code.com> - 4.04-1
+- initial packaging for CentOS 7 based on mysql-mroogna package.
+
+* Tue Jul 29 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.04-1
+- new upstream release.
+
+* Thu May 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.03-1
+- new upstream release.
+
+* Tue Apr 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.02-1
+- new upstream release.
+
+* Sat Mar 29 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.01-1
+- new upstream release.
+
+* Thu Feb 13 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.00-2
+- use MySQL 5.1.73-3 on CentOS 6.
+
+* Sun Feb 09 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.00-1
+- new upstream release.
+
+* Wed Jan 29 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 3.12-1
+- new upstream release.
+
+* Sun Dec 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.11-1
+- new upstream release.
+
+* Sat Dec 7 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.10-2
+- use MySQL 5.1.71-1 on CentOS 6.
+
+* Fri Nov 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.10-1
+- new upstream release.
+
+* Tue Oct 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.09-1
+- new upstream release.
+
+* Sun Sep 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.08-1
+- new upstream release.
+- use MySQL 5.6.14-1 on CentOS 5.
+
+* Wed Sep 4 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.07-2
+- fix a bug that mroonga is removed accidentally on upgrade #1918.
+ Reported by @ceekz. Thanks!!!
+
+* Thu Aug 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.07-1
+- new upstream release.
+- use MySQL 5.6.13-1 on CentOS 5.
+
+* Mon Jul 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.06-1
+- new upstream release.
+- use MySQL 5.6.12-2 on CentOS 5.
+
+* Sat Jun 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.05-1
+- new upstream release.
+- use MySQL 5.6.12 on CentOS 5.
+
+* Wed May 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.04-1
+- new upstream release.
+
+* Fri May 10 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.03-2
+- use MySQL 5.6.11-2 on CentOS 5. see http://bugs.mysql.com/bug.php?id=69027
+ Reported by Y.Kentaro. Thanks!!!
+
+* Mon Apr 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.03-1
+- new upstream release.
+
+* Fri Mar 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.02-0
+- new upstream release.
+
+* Thu Feb 28 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.01-0
+- new upstream release.
+
+* Sat Feb 09 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.00-0
+- new upstream release.
+- require groonga 3.0.0 or later
+
+* Tue Feb 05 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 2.10-2
+- use MySQL 5.1.67-1 on CentOS 6.
+ Reported by wakisuke.ua. Thanks!!!
+
+* Sat Dec 29 2012 HAYASHI Kentaro <hayashi@clear-code.com> - 2.10-0
+- new upstream release.
+
+* Mon Dec 10 2012 HAYASHI Kentaro <hayashi@clear-code.com> - 2.09-1
+- use MySQL 5.1.66-2 on CentOS 6.
+ Reported by wakisuke.ua. Thanks!!!
+
+* Thu Nov 29 2012 HAYASHI Kentaro <hayashi@clear-code.com> - 2.09-0
+- new upstream release.
+- use MySQL 5.5.28 on CentOS 5.
+- use MySQL 5.1.66 on CentOS 6.
+
+* Mon Oct 29 2012 HAYASHI Kentaro <hayashi@clear-code.com> - 2.08-0
+- new upstream release.
+- add missing "DROP FUNCTION mroonga_snippet".
+ Reported by @tokuhy. Thanks!!!
+
+* Sat Sep 29 2012 HAYASHI Kentaro <hayashi@clear-code.com> - 2.07-0
+- new upstream release.
+
+* Wed Aug 29 2012 Kouhei Sutou <kou@clear-code.com> - 2.06-0
+- new upstream release.
+- make MySQL spec file name customizable.
+- make mroonga configure options customizable.
+- add missing mysql-devel BuildRequires. Reported by wing. Thanks!!!
+- use MySQL 5.5.27.
+
+* Sun Jul 29 2012 HAYASHI Kentaro <hayashi@clear-code.com> - 2.05-0
+- new upstream release.
+- use MySQL 5.5.25a.
+
+* Fri Jun 29 2012 Kouhei Sutou <kou@clear-code.com> - 2.04-0
+- new upstream release.
+- ensure deleting mroonga plugin before install.
+ Suggested by Kazuhiro Isobe. Thanks!!!
+- use MySQL 5.5.25.
+
+* Tue May 29 2012 Kouhei Sutou <kou@clear-code.com> - 2.03-0
+- new upstream release.
+- use MySQL 5.5.24.
+- make mysql_* variables customizable
+- require groonga 2.0.3 or later.
+
+* Sun Apr 29 2012 Kouhei Sutou <kou@clear-code.com> - 2.02-0
+- new upstream release.
+- use MySQL 5.5.23.
+- require groonga 2.0.2 or later.
+
+* Thu Mar 29 2012 Kouhei Sutou <kou@clear-code.com> - 2.01-0
+- new upstream release.
+- ensure plugin is uninstalled by closing all tables use mroonga.
+
+* Wed Feb 29 2012 Kouhei Sutou <kou@clear-code.com> - 2.00-0
+- new upstream release.
+- always install/uninstall plugin.
+- use MySQL 5.1.61 and 5.5.21.
+- require groonga 2.0.0 or later.
+
+* Sun Jan 29 2012 Kouhei Sutou <kou@clear-code.com> - 1.20-0
+- new upstream release.
+- require groonga 1.3.0.
+- groonga -> mroonga.
+- use MySQL 5.5.20.
+
+* Thu Dec 29 2011 Kouhei Sutou <kou@clear-code.com> - 1.11-0
+- new upstream release.
+
+* Sat Oct 29 2011 Kouhei Sutou <kou@clear-code.com> - 1.10-0
+- new upstream release.
+- groonga storage engine -> mroonga.
+
+* Thu Sep 29 2011 Kouhei Sutou <kou@clear-code.com> - 1.0.0-0
+- new upstream release.
+
+* Mon Aug 29 2011 Kouhei Sutou <kou@clear-code.com> - 0.9-0
+- new upstream release.
+
+* Fri Jul 29 2011 Kouhei Sutou <kou@clear-code.com> - 0.8-0
+- new upstream release.
+
+* Wed Jun 29 2011 Kouhei Sutou <kou@clear-code.com> - 0.7-0
+- new upstream release.
+
+* Sun May 29 2011 Kouhei Sutou <kou@clear-code.com> - 0.6-0
+- new upstream release.
+
+* Tue May 17 2011 Kouhei Sutou <kou@clear-code.com> - 0.5-2
+- use MySQL 5.5.12.
+
+* Tue Mar 29 2011 Kouhei Sutou <kou@clear-code.com> - 0.5-1
+- new upstream release.
+
+* Sat Jan 29 2011 Kouhei Sutou <kou@clear-code.com> - 0.4-4
+- do not remove plugin on upgrade.
+
+* Wed Jan 12 2011 Kouhei Sutou <kou@clear-code.com> - 0.4-3
+- rebuild without debug symbol.
+
+* Thu Dec 30 2010 Kouhei Sutou <kou@clear-code.com> - 0.4-2
+- use MySQL 5.5.8-1.
+- fix SQL literal notation.
+
+* Mon Nov 29 2010 Kouhei Sutou <kou@clear-code.com> - 0.4-1
+- use the latest MySQL.
+- new upstream release.
+
+* Sun Nov 21 2010 Kouhei Sutou <kou@clear-code.com> - 0.3-2
+- install user define function.
+
+* Fri Oct 29 2010 Kouhei Sutou <kou@clear-code.com> - 0.3-1
+- new upstream release.
+
+* Fri Oct 08 2010 Kouhei Sutou <kou@clear-code.com> - 0.2-2
+- specify target MySQL version.
+- use %{version}.
+
+* Wed Sep 29 2010 Kouhei Sutou <kou@clear-code.com> - 0.2-1
+- new upstream release.
+
+* Sun Sep 12 2010 Kouhei Sutou <kou@clear-code.com> - 0.1-3
+- require MySQL-client-community.
+
+* Fri Sep 10 2010 Kouhei Sutou <kou@clear-code.com> - 0.1-2
+- use MySQL-devel-community.
+
+* Fri Sep 03 2010 Kouhei Sutou <kou@clear-code.com> - 0.1-1
+- initial packaging for CentOS.
diff --git a/storage/mroonga/packages/rpm/centos/mysql55-mroonga.spec.in b/storage/mroonga/packages/rpm/centos/mysql55-mroonga.spec.in
new file mode 100644
index 00000000000..f1f5b2f4692
--- /dev/null
+++ b/storage/mroonga/packages/rpm/centos/mysql55-mroonga.spec.in
@@ -0,0 +1,218 @@
+%{?scl:%scl_package mroonga}
+%{!?scl:%global pkg_name %{name}}
+%{!?centos_ver:%define centos_ver 5}
+
+%if %{centos_ver} == 6
+%define mysql_version_default 5.5.41
+%define mysql_release_default 2
+%define mysql_dist_default el6.centos.alt
+%define mysql_download_base_url_default http://vault.centos.org/6.6/SCL/Source/SPackages
+%define mysql_spec_file_default mysql.spec
+%else
+%define mysql_version_default 5.5.40
+%define mysql_release_default 2
+%define mysql_dist_default el5
+%define mysql_download_base_url_default http://vault.centos.org/5.11/updates/SRPMS
+%define mysql_spec_file_default mysql.spec
+%endif
+
+%{!?mysql_version:%define mysql_version %{mysql_version_default}}
+%{!?mysql_release:%define mysql_release %{mysql_release_default}}
+%{!?mysql_dist:%define mysql_dist %{mysql_dist_default}}
+%{!?mysql_download_base_url:%define mysql_download_base_url %{mysql_download_base_url_default}}
+%{!?mysql_spec_file:%define mysql_spec_file %{mysql_spec_file_default}}
+
+%define groonga_required_version @REQUIRED_GROONGA_VERSION@
+
+Name: %{?scl_prefix}mroonga
+Version: @VERSION@
+Release: 1%{?dist}
+Summary: A fast fulltext searchable storage engine for MySQL
+
+Group: Applications/Databases
+License: LGPLv2.1
+URL: http://mroonga.org/
+Source0: http://packages.groonga.org/source/mroonga/mroonga-%{version}.tar.gz
+
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-%(%{__id_u} -n)
+BuildRequires: groonga-devel >= %{groonga_required_version}
+BuildRequires: groonga-normalizer-mysql-devel
+BuildRequires: wget
+BuildRequires: which
+BuildRequires: mysql55-mysql-devel
+BuildRequires: mysql55-build
+Requires: mysql55-mysql-server = %{mysql_version}-%{mysql_release}.%{mysql_dist}
+Requires: mysql55-mysql = %{mysql_version}-%{mysql_release}.%{mysql_dist}
+Requires: groonga-libs >= %{groonga_required_version}
+Requires: groonga-normalizer-mysql
+%{?scl:Requires: %scl_runtime}
+
+%description
+Mroonga is a fast fulltext searchable storage plugin for MySQL.
+It is based on Groonga that is a fast fulltext search engine and
+column store. Groonga is good at real-time update.
+
+%package doc
+Summary: Documentation for Mroonga
+Group: Documentation
+License: LGPLv2.1
+
+%description doc
+Documentation for Mroonga
+
+
+%prep
+%setup -q -n %{pkg_name}-%{version}
+
+mysql_full_version=%{mysql_version}-%{mysql_release}.%{mysql_dist}
+srpm=mysql55-mysql-${mysql_full_version}.src.rpm
+if [ ! -f ../../SRPMS/$srpm ]; then
+ wget --continue -O ../../SRPMS/$srpm %{mysql_download_base_url}/$srpm
+ rpm -Uvh ../../SRPMS/$srpm
+fi
+
+%build
+mysql_source=../mysql-%{mysql_version}
+if [ ! -d ${mysql_source} ]; then
+ specs_dir=
+ MYSQL_RPMBUILD_TEST=no rpmbuild -bp \
+ --define 'runselftest 0' \
+ --define 'optflags -O0' \
+ ../../SPECS/%{mysql_spec_file}
+fi
+%configure --disable-static --with-mysql-source=${mysql_source} \
+ --disable-fast-mutexes \
+ --with-mysql-config=`scl enable mysql55 'which mysql_config'` \
+ %{?mroonga_configure_options}
+make %{?_smp_mflags}
+
+%install
+rm -rf $RPM_BUILD_ROOT
+make install DESTDIR=$RPM_BUILD_ROOT
+rm $RPM_BUILD_ROOT%{_libdir}/mysql/plugin/*.la
+mv $RPM_BUILD_ROOT%{_datadir}/doc/mroonga/ mysql-mroonga-doc/
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+mysql_command=`scl enable mysql55 'which mysql'`
+password_option=""
+$mysql_command -u root -e "quit"
+if [ $? -ne 0 ]; then
+ password_option="-p"
+fi
+current_version=0
+version=`echo %{groonga_required_version} | sed -e 's/\.//g'`
+required_version=`expr $version`
+version=`$mysql_command -e "SHOW VARIABLES LIKE 'mroonga_libgroonga_version'" | \
+ grep mroonga | cut -f 2 | sed -e 's/\.//g'`
+if [ -n "$version" ]; then
+ current_version=`expr $version`
+fi
+install_sql=%{_datadir}/mroonga/install.sql
+uninstall_sql=%{_datadir}/mroonga/uninstall.sql
+
+if [ "$1" = 2 ] ; then
+ if [ $current_version -lt $required_version ]; then
+ command="$mysql_command -u root $password_option"
+ echo "run the following command after restarting MySQL server:";
+ echo " $command < ${uninstall_sql}"
+ echo " $command < ${install_sql}"
+ exit 0
+ else
+ command="$mysql_command -u root $password_option < ${uninstall_sql}"
+ echo $command
+ eval $command || \
+ (echo "run the following command to unregister Mroonga:"; \
+ echo " $command")
+ fi
+fi
+command="$mysql_command -u root $password_option < ${install_sql}"
+echo $command
+eval $command || \
+ (echo "run the following command to register Mroonga:"; \
+ echo " $command")
+
+%preun
+uninstall_sql=%{_datadir}/mroonga/uninstall.sql
+mysql_command=`scl enable mysql55 'which mysql'`
+if $mysql_command -u root -e "quit"; then
+ password_option=""
+else
+ password_option="-p"
+fi
+if [ "$1" = 0 ]; then
+ command="$mysql_command -u root $password_option < ${uninstall_sql}"
+ echo $command
+ eval $command || \
+ (echo "run the following command to unregister Mroonga:"; \
+ echo " $command")
+fi
+
+%files
+%defattr(-,root,root,-)
+%{_libdir}/mysql/plugin/
+%{_datadir}/mroonga/*
+%{_datadir}/man/man1/*
+%{_datadir}/man/*/man1/*
+
+%files doc
+%defattr(-,root,root,-)
+%doc README COPYING
+%doc mysql-mroonga-doc/*
+
+%changelog
+* Mon Feb 09 2015 <hayashi@clear-code.com> - 5.00-1
+- new upstream release.
+
+* Thu Jan 29 2015 HAYASHI Kentaro <hayashi@clear-code.com> - 4.10-1
+- new upstream release.
+
+* Mon Dec 29 2014 Kouhei Sutou <kou@cozmixng.org> - 4.09-1
+- new upstream release.
+
+* Sat Nov 29 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.08-1
+- new upstream release.
+
+* Wed Oct 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.07-1
+- new upstream release.
+
+* Mon Sep 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.06-1
+- new upstream release.
+
+* Fri Aug 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.05-1
+- new upstream release.
+
+* Tue Jul 29 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.04-1
+- new upstream release.
+
+* Thu May 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.03-2
+- build against MySQL 5.6.37. Reported by YOSHIDA Mitsuo. Thanks!!!
+
+* Thu May 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.03-1
+- new upstream release.
+
+* Tue Apr 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.02-1
+- new upstream release.
+
+* Sat Mar 29 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.01-1
+- new upstream release.
+
+* Thu Mar 06 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.00-2
+- use MySQL 5.5.36 on CentOS 5.
+
+* Sun Feb 09 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.00-1
+- new upstream release.
+
+* Wed Jan 29 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 3.12-1
+- new upstream release.
+
+* Sun Dec 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.11-1
+- new upstream release.
+
+* Fri Nov 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.10-1
+- new upstream release.
+
+* Tue Oct 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.09-1
+- initial packaging for MySQL 5.5 on CentOS 5.
diff --git a/storage/mroonga/packages/rpm/centos/mysql56-community-mroonga.spec.in b/storage/mroonga/packages/rpm/centos/mysql56-community-mroonga.spec.in
new file mode 100644
index 00000000000..37ae5d41b2f
--- /dev/null
+++ b/storage/mroonga/packages/rpm/centos/mysql56-community-mroonga.spec.in
@@ -0,0 +1,222 @@
+%{!?centos_ver:%define centos_ver 6}
+
+%if %{centos_ver} == 7
+%define mysql_version_default 5.6.23
+%define mysql_release_default 2
+%define mysql_dist_default el7
+%define mysql_download_base_url_default http://repo.mysql.com/yum/mysql-5.6-community/el/7/SRPMS
+%define mysql_spec_file_default mysql.spec
+%else
+%define mysql_version_default 5.6.23
+%define mysql_release_default 2
+%define mysql_dist_default el6
+%define mysql_download_base_url_default http://repo.mysql.com/yum/mysql-5.6-community/el/6/SRPMS
+%define mysql_spec_file_default mysql.spec
+%endif
+
+%{!?mysql_version:%define mysql_version %{mysql_version_default}}
+%{!?mysql_release:%define mysql_release %{mysql_release_default}}
+%{!?mysql_dist:%define mysql_dist %{mysql_dist_default}}
+%{!?mysql_download_base_url:%define mysql_download_base_url %{mysql_download_base_url_default}}
+%{!?mysql_spec_file:%define mysql_spec_file %{mysql_spec_file_default}}
+
+%define groonga_required_version @REQUIRED_GROONGA_VERSION@
+
+Name: mysql-community-mroonga
+Version: @VERSION@
+Release: 1%{?dist}
+Summary: A fast fulltext searchable storage engine for MySQL
+
+Group: Applications/Databases
+License: LGPLv2.1
+URL: http://mroonga.org/
+Source0: http://packages.groonga.org/source/mroonga/mroonga-%{version}.tar.gz
+
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-%(%{__id_u} -n)
+BuildRequires: groonga-devel >= %{groonga_required_version}
+BuildRequires: groonga-normalizer-mysql-devel
+BuildRequires: wget
+BuildRequires: which
+BuildRequires: gcc, gcc-c++
+BuildRequires: mysql-community-devel
+Requires: mysql-community-server = %{mysql_version}-%{mysql_release}.%{mysql_dist}
+Requires: mysql-community-client = %{mysql_version}-%{mysql_release}.%{mysql_dist}
+Requires: groonga-libs >= %{groonga_required_version}
+Requires: groonga-normalizer-mysql
+
+%description
+Mroonga is a fast fulltext searchable storage plugin for MySQL.
+It is based on Groonga that is a fast fulltext search engine and
+column store. Groonga is good at real-time update.
+
+%package doc
+Summary: Documentation for Mroonga
+Group: Documentation
+License: LGPLv2.1
+
+%description doc
+Documentation for Mroonga
+
+
+%prep
+%setup -q -n mroonga-%{version}
+
+mysql_full_version=%{mysql_version}-%{mysql_release}.%{mysql_dist}
+srpm=mysql-community-${mysql_full_version}.src.rpm
+if [ ! -f ../../SRPMS/$srpm ]; then
+ wget --continue -O ../../SRPMS/$srpm %{mysql_download_base_url}/$srpm
+ rpm -Uvh ../../SRPMS/$srpm
+fi
+
+%build
+mysql_source=../mysql-%{mysql_version}/mysql-%{mysql_version}
+if [ ! -d ${mysql_source} ]; then
+ specs_dir=
+ MYSQL_RPMBUILD_TEST=no rpmbuild -bp \
+ --define 'runselftest 0' \
+ --define 'optflags -O0' \
+ ../../SPECS/%{mysql_spec_file}
+fi
+%configure --disable-static --with-mysql-source=${mysql_source} \
+ %{?mroonga_configure_options}
+make %{?_smp_mflags}
+
+%install
+rm -rf $RPM_BUILD_ROOT
+make install DESTDIR=$RPM_BUILD_ROOT
+rm $RPM_BUILD_ROOT%{_libdir}/mysql/plugin/*.la
+mv $RPM_BUILD_ROOT%{_datadir}/doc/mroonga/ mysql-mroonga-doc/
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+mysql_command=`which mysql`
+password_option=""
+$mysql_command -u root -e "quit"
+if [ $? -ne 0 ]; then
+ password_option="-p"
+fi
+current_version=0
+version=`echo %{groonga_required_version} | sed -e 's/\.//g'`
+required_version=`expr $version`
+version=`$mysql_command -e "SHOW VARIABLES LIKE 'mroonga_libgroonga_version'" | \
+ grep mroonga | cut -f 2 | sed -e 's/\.//g'`
+if [ -n "$version" ]; then
+ current_version=`expr $version`
+fi
+install_sql=%{_datadir}/mroonga/install.sql
+uninstall_sql=%{_datadir}/mroonga/uninstall.sql
+
+if [ "$1" = 2 ] ; then
+ if [ $current_version -lt $required_version ]; then
+ command="$mysql_command -u root $password_option"
+ echo "run the following command after restarting MySQL server:";
+ echo " $command < ${uninstall_sql}"
+ echo " $command < ${install_sql}"
+ exit 0
+ else
+ command="$mysql_command -u root $password_option < ${uninstall_sql}"
+ echo $command
+ eval $command || \
+ (echo "run the following command to unregister Mroonga:"; \
+ echo " $command")
+ fi
+fi
+command="$mysql_command -u root $password_option < ${install_sql}"
+echo $command
+eval $command || \
+ (echo "run the following command to register Mroonga:"; \
+ echo " $command")
+
+%preun
+uninstall_sql=%{_datadir}/mroonga/uninstall.sql
+mysql_command=`which mysql`
+if $mysql_command -u root -e "quit"; then
+ password_option=""
+else
+ password_option="-p"
+fi
+if [ "$1" = 0 ]; then
+ command="$mysql_command -u root $password_option < ${uninstall_sql}"
+ echo $command
+ eval $command || \
+ (echo "run the following command to unregister Mroonga:"; \
+ echo " $command")
+fi
+
+%files
+%defattr(-,root,root,-)
+%{_libdir}/mysql/plugin/
+%{_datadir}/mroonga/*
+%{_datadir}/man/man1/*
+%{_datadir}/man/*/man1/*
+
+%files doc
+%defattr(-,root,root,-)
+%doc README COPYING
+%doc mysql-mroonga-doc/*
+
+%changelog
+* Mon Feb 09 2015 <hayashi@clear-code.com> - 5.00-1
+- new upstream release.
+
+* Wed Feb 04 2015 HAYASHI Kentaro <hayashi@clear-code.com> - 4.10-2
+- build against MySQL 5.6.23-2 on MySQL yum repository.
+
+* Thu Jan 29 2015 HAYASHI Kentaro <hayashi@clear-code.com> - 4.10-1
+- new upstream release.
+
+* Mon Dec 29 2014 Kouhei Sutou <kou@cozmixng.org> - 4.09-1
+- new upstream release.
+
+* Sat Nov 29 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.08-1
+- new upstream release.
+
+* Wed Oct 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.07-1
+- new upstream release.
+
+* Mon Sep 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.06-1
+- new upstream release.
+
+* Sat Sep 27 2014 Eiichi Sato <miko@cafelounge.net> - 4.05-2
+- build against MySQL 5.6.21-2 on MySQL yum repository.
+
+* Fri Aug 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.05-1
+- new upstream release.
+
+* Sat Aug 09 2014 Eiichi Sato <miko@cafelounge.net> - 4.04-2
+- build against MySQL 5.6.20-4 on MySQL yum repository.
+
+* Tue Jul 29 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.04-1
+- new upstream release.
+
+* Thu May 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.03-2
+- build against MySQL 5.6.37. Reported by YOSHIDA Mitsuo. Thanks!!!
+
+* Thu May 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.03-1
+- new upstream release.
+
+* Tue Apr 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.02-1
+- new upstream release.
+
+* Sat Mar 29 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.01-1
+- new upstream release.
+
+* Thu Mar 06 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.00-2
+- use MySQL 5.5.36 on CentOS 5.
+
+* Sun Feb 09 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.00-1
+- new upstream release.
+
+* Wed Jan 29 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 3.12-1
+- new upstream release.
+
+* Sun Dec 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.11-1
+- new upstream release.
+
+* Fri Nov 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.10-1
+- new upstream release.
+
+* Tue Oct 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.09-1
+- initial packaging for MySQL 5.5 on CentOS 5.
diff --git a/storage/mroonga/packages/source/Makefile.am b/storage/mroonga/packages/source/Makefile.am
new file mode 100644
index 00000000000..30721406f0b
--- /dev/null
+++ b/storage/mroonga/packages/source/Makefile.am
@@ -0,0 +1,123 @@
+MROONGA_BASE = $(PACKAGE)-$(VERSION)
+MROONGA_TAR_GZ = $(MROONGA_BASE).tar.gz
+
+GROONGA_VERSION = 5.0.0
+GROONGA_BASE = groonga-$(GROONGA_VERSION)
+GROONGA_TAR_GZ = $(GROONGA_BASE).tar.gz
+
+GROONGA_NORMALIZER_MYSQL_VERSION = 1.0.8
+GROONGA_NORMALIZER_MYSQL_BASE = \
+ groonga-normalizer-mysql-$(GROONGA_NORMALIZER_MYSQL_VERSION)
+GROONGA_NORMALIZER_MYSQL_TAR_GZ = \
+ $(GROONGA_NORMALIZER_MYSQL_BASE).tar.gz
+
+MARIADB_VERSION = 10.0.16
+MARIADB_BASE = mariadb-$(MARIADB_VERSION)
+MARIADB_TAR_GZ = $(MARIADB_BASE).tar.gz
+
+MARIADB_WITH_MROONGA_BASE = $(MARIADB_BASE)-with-$(MROONGA_BASE)
+MARIADB_WITH_MROONGA_FOR_WINDOWS_BASE = $(MARIADB_WITH_MROONGA_BASE)-for-windows
+
+GROONGA_PROJECT_DOWNLOAD_BASE = http://packages.groonga.org/source
+GROONGA_DOWNLOAD_BASE = $(GROONGA_PROJECT_DOWNLOAD_BASE)/groonga
+GROONGA_NORMALIZER_MYSQL_DOWNLOAD_BASE = \
+ $(GROONGA_PROJECT_DOWNLOAD_BASE)/groonga-normalizer-mysql
+MARIADB_DOWNLOAD_BASE = http://ftp.yz.yamagata-u.ac.jp/pub/dbms/mariadb
+
+
+CURL = curl --fail --silent --show-error
+
+all:
+
+release: archive upload
+
+ensure-rsync-path:
+ @if test -z "$(RSYNC_PATH)"; then \
+ echo "--with-rsync-path configure option must be specified."; \
+ false; \
+ fi
+
+download: ensure-rsync-path
+ rsync -avz --progress --delete $(RSYNC_PATH)/source/mroonga/ files
+
+ARCHIVES = \
+ files/$(MROONGA_TAR_GZ) \
+ files/$(MARIADB_WITH_MROONGA_BASE).tar.gz \
+ files/$(MARIADB_WITH_MROONGA_FOR_WINDOWS_BASE).zip
+
+archive: $(ARCHIVES)
+
+upload: ensure-rsync-path
+ rsync -avz --progress --delete files/ $(RSYNC_PATH)/source/mroonga
+
+files/$(MROONGA_TAR_GZ): $(top_builddir)/$(MROONGA_TAR_GZ)
+ mkdir -p files
+ cp -p $< $@
+
+tmp/$(GROONGA_TAR_GZ):
+ mkdir -p tmp
+ $(CURL) --output $@ $(GROONGA_DOWNLOAD_BASE)/$(GROONGA_TAR_GZ)
+
+tmp/$(GROONGA_NORMALIZER_MYSQL_TAR_GZ):
+ mkdir -p tmp
+ $(CURL) --output $@ $(GROONGA_NORMALIZER_MYSQL_DOWNLOAD_BASE)/$(GROONGA_NORMALIZER_MYSQL_TAR_GZ)
+
+tmp/$(MARIADB_TAR_GZ):
+ mkdir -p tmp
+ $(CURL) --output $@ $(MARIADB_DOWNLOAD_BASE)/mariadb-$(MARIADB_VERSION)/source/$(MARIADB_TAR_GZ)
+
+MARIADB_WITH_MROONGA_ARCHIVES = \
+ tmp/$(GROONGA_TAR_GZ) \
+ tmp/$(GROONGA_NORMALIZER_MYSQL_TAR_GZ) \
+ tmp/$(MARIADB_TAR_GZ) \
+ $(top_builddir)/$(MROONGA_TAR_GZ)
+
+BUNDLED_MROONGA_PATH = $(MARIADB_BASE)/storage/$(PACKAGE)
+BUNDLED_GROONGA_PATH = $(BUNDLED_MROONGA_PATH)/vendor/groonga
+BUNDLED_GROONGA_NORMALIZER_MYSQL_PATH = \
+ $(BUNDLED_GROONGA_PATH)/vendor/plugins/groonga-normalizer-mysql
+
+tmp/$(MARIADB_WITH_MROONGA_BASE).stamp: $(MARIADB_WITH_MROONGA_ARCHIVES)
+ rm -rf $(MARIADB_BASE)
+ tar xf tmp/$(MARIADB_TAR_GZ)
+
+ rm -fr $(MARIADB_BASE)/storage/mroonga
+ tar xf $(top_builddir)/$(MROONGA_TAR_GZ)
+ mv $(MROONGA_BASE) $(BUNDLED_MROONGA_PATH)
+
+ mkdir -p $$(dirname $(BUNDLED_GROONGA_PATH))
+ tar xf tmp/$(GROONGA_TAR_GZ)
+ rm -rf $(GROONGA_BASE)/test
+ mv $(GROONGA_BASE) $(BUNDLED_GROONGA_PATH)
+
+ tar xf tmp/$(GROONGA_NORMALIZER_MYSQL_TAR_GZ)
+ rm -rf $(GROONGA_NORMALIZER_MYSQL_BASE)/test
+ mv $(GROONGA_NORMALIZER_MYSQL_BASE) $(BUNDLED_GROONGA_NORMALIZER_MYSQL_PATH)
+
+ rm -rf tmp/$(MARIADB_WITH_MROONGA_BASE)
+ mv $(MARIADB_BASE) tmp/$(MARIADB_WITH_MROONGA_BASE)
+
+ touch $@
+
+files/$(MARIADB_WITH_MROONGA_BASE).tar.gz: tmp/$(MARIADB_WITH_MROONGA_BASE).stamp
+ mkdir -p files/
+ (cd tmp && tar czf ../$@ $(MARIADB_WITH_MROONGA_BASE))
+
+PATCHES = \
+ patches/mariadb-10.0.3-windows-build.diff
+
+tmp/$(MARIADB_WITH_MROONGA_FOR_WINDOWS_BASE).stamp: tmp/$(MARIADB_WITH_MROONGA_BASE).stamp $(PATCHES)
+ rm -rf tmp/$(MARIADB_WITH_MROONGA_FOR_WINDOWS_BASE)
+ cp -a \
+ tmp/$(MARIADB_WITH_MROONGA_BASE) \
+ tmp/$(MARIADB_WITH_MROONGA_FOR_WINDOWS_BASE)
+ for patch in $(PATCHES); do \
+ (cd tmp/$(MARIADB_WITH_MROONGA_FOR_WINDOWS_BASE) && \
+ patch -p1 < $(abs_srcdir)/$${patch}); \
+ done
+
+ touch $@
+
+files/$(MARIADB_WITH_MROONGA_FOR_WINDOWS_BASE).zip: tmp/$(MARIADB_WITH_MROONGA_FOR_WINDOWS_BASE).stamp
+ mkdir -p files/
+ (cd tmp && zip -q -r ../$@ $(MARIADB_WITH_MROONGA_FOR_WINDOWS_BASE))
diff --git a/storage/mroonga/packages/source/patches/mariadb-10.0.3-windows-build.diff b/storage/mroonga/packages/source/patches/mariadb-10.0.3-windows-build.diff
new file mode 100644
index 00000000000..c135088b8cc
--- /dev/null
+++ b/storage/mroonga/packages/source/patches/mariadb-10.0.3-windows-build.diff
@@ -0,0 +1,9 @@
+diff -ur mariadb-10.0.2.orig/sql/sql_locale.cc mariadb-10.0.2/sql/sql_locale.cc
+--- mariadb-10.0.2.orig/sql/sql_locale.cc 2013-04-23 13:13:59.000000000 +0900
++++ mariadb-10.0.2/sql/sql_locale.cc 2013-05-19 12:55:27.590366542 +0900
+@@ -1,4 +1,4 @@
+-/* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
++/* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
diff --git a/storage/mroonga/packages/ubuntu/Makefile.am b/storage/mroonga/packages/ubuntu/Makefile.am
new file mode 100644
index 00000000000..493419275b3
--- /dev/null
+++ b/storage/mroonga/packages/ubuntu/Makefile.am
@@ -0,0 +1,24 @@
+CODE_NAMES = precise,trusty,utopic
+SOURCE = ../$(PACKAGE)-$(VERSION).tar.gz
+
+all:
+
+ensure-launchpad-configuration:
+ @if test -z "$(LAUNCHPAD_UPLOADER_PGP_KEY)"; then \
+ echo "--with-launchpad-uploader-pgp-key configure option must be specified."; \
+ false; \
+ fi
+
+upload: source ensure-launchpad-configuration
+ ./upload.rb \
+ --package '$(PACKAGE)' \
+ --version '$(VERSION)' \
+ --source-archive '$(SOURCE)' \
+ --code-names '$(CODE_NAMES)' \
+ --debian-directory '$(srcdir)/../debian/' \
+ --pgp-sign-key '$(LAUNCHPAD_UPLOADER_PGP_KEY)'
+
+source: $(SOURCE)
+
+$(SOURCE):
+ ln -s $(abs_top_builddir)/$(PACKAGE)-$(VERSION).tar.gz $(SOURCE)
diff --git a/storage/mroonga/packages/ubuntu/upload.rb b/storage/mroonga/packages/ubuntu/upload.rb
new file mode 100755
index 00000000000..3331de6d5eb
--- /dev/null
+++ b/storage/mroonga/packages/ubuntu/upload.rb
@@ -0,0 +1,168 @@
+#!/usr/bin/env ruby
+#
+# Copyright(C) 2014 Kouhei Sutou <kou@clear-code.com>
+# Copyright(C) 2014 HAYASHI Kentaro <hayashi@clear-code.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1 as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+require "optparse"
+require "fileutils"
+require "pathname"
+require "open-uri"
+
+class Uploader
+ def initialize
+ @dput_configuration_name = "groonga-ppa"
+ end
+
+ def run
+ ensure_dput_configuration
+
+ parse_command_line!
+
+ ensure_mysql_version
+
+ @required_groonga_version = required_groonga_version
+
+ @code_names.each do |code_name|
+ upload(code_name)
+ end
+ end
+
+ private
+ def ensure_dput_configuration
+ dput_cf_path = Pathname.new("~/.dput.cf").expand_path
+ if dput_cf_path.exist?
+ dput_cf_content = dput_cf_path.read
+ else
+ dput_cf_content = ""
+ end
+ dput_cf_content.each_line do |line|
+ return if line.chomp == "[#{@dput_configuration_name}]"
+ end
+
+ dput_cf_path.open("w") do |dput_cf|
+ dput_cf.puts(dput_cf_content)
+ dput_cf.puts(<<-CONFIGURATION)
+[#{@dput_configuration_name}]
+fqdn = ppa.launchpad.net
+method = ftp
+incoming = ~groonga/ppa/ubuntu/
+login = anonymous
+allow_unsigned_uploads = 0
+ CONFIGURATION
+ end
+ end
+
+ def ensure_mysql_version
+ @mysql_version = {}
+ @code_names.each do |code_name|
+ open("http://packages.ubuntu.com/#{code_name}/allpackages?format=txt.gz") do |file|
+ file.each_line do |line|
+ @mysql_version[code_name] = $1 if line =~ /\Amysql-server \((.+?)\).+/
+ end
+ end
+ end
+ end
+
+ def parse_command_line!
+
+ parser = OptionParser.new
+ parser.on("--package=NAME",
+ "The package name") do |name|
+ @package = name
+ end
+ parser.on("--version=VERSION",
+ "The version") do |version|
+ @version = version
+ end
+ parser.on("--source-archive=ARCHIVE",
+ "The source archive") do |source_archive|
+ @source_archive = Pathname.new(source_archive).expand_path
+ end
+ parser.on("--code-names=CODE_NAME1,CODE_NAME2,CODE_NAME3,...", Array,
+ "The target code names") do |code_names|
+ @code_names = code_names
+ end
+ parser.on("--debian-directory=DIRECTORY",
+ "The debian/ directory") do |debian_directory|
+ @debian_directory = Pathname.new(debian_directory).expand_path
+ end
+ parser.on("--pgp-sign-key=KEY",
+ "The PGP key to sign .changes and .dsc") do |pgp_sign_key|
+ @pgp_sign_key = pgp_sign_key
+ end
+ parser.on("--pbuilder",
+ "Use pbuilder for build check") do |pbuilder|
+ @use_pbuilder = pbuilder
+ end
+
+ parser.parse!
+ end
+
+ def upload(code_name)
+ in_temporary_directory do
+ FileUtils.cp(@source_archive.to_s,
+ "#{@package}_#{@version}.orig.tar.gz")
+ run_command("tar", "xf", @source_archive.to_s)
+ directory_name = "#{@package}-#{@version}"
+ Dir.chdir(directory_name) do
+ FileUtils.cp_r(@debian_directory.to_s, "debian")
+ deb_version = "#{current_deb_version.succ}~#{code_name}1"
+ run_command("dch",
+ "--distribution", code_name,
+ "--newversion", deb_version,
+ "Build for #{code_name}.")
+ run_command("sed",
+ "-i", "-e", "s,MYSQL_VERSION,#{@mysql_version[code_name]},",
+ "debian/control")
+ run_command("debuild", "-S", "-sa", "-pgpg2", "-k#{@pgp_sign_key}")
+ if @use_pbuilder
+ run_command("pbuilder-dist", code_name, "build",
+ "../#{@package}_#{deb_version}.dsc")
+ else
+ run_command("dput", @dput_configuration_name,
+ "../#{@package}_#{deb_version}_source.changes")
+ end
+ end
+ end
+ end
+
+ def required_groonga_version
+ File.read("../../required_groonga_version").lines.first.chomp
+ end
+
+ def current_deb_version
+ /\((.+)\)/ =~ File.read("debian/changelog").lines.first
+ $1
+ end
+
+ def in_temporary_directory
+ name = "tmp"
+ FileUtils.rm_rf(name)
+ FileUtils.mkdir_p(name)
+ Dir.chdir(name) do
+ yield
+ end
+ end
+
+ def run_command(*command_line)
+ unless system(*command_line)
+ raise "failed to run command: #{command_line.join(' ')}"
+ end
+ end
+end
+
+uploader = Uploader.new
+uploader.run
diff --git a/storage/mroonga/packages/windows/Makefile.am b/storage/mroonga/packages/windows/Makefile.am
new file mode 100644
index 00000000000..a2ff8f59792
--- /dev/null
+++ b/storage/mroonga/packages/windows/Makefile.am
@@ -0,0 +1,12 @@
+EXTRA_DIST = \
+ README.md \
+ build-vc2010.bat \
+ build-vc2010-zip-32.bat \
+ build-vc2010-zip-64.bat \
+ build-vc2010-msi-32.bat \
+ build-vc2010-msi-64.bat \
+ build-vc2013.bat \
+ build-vc2013-zip-32.bat \
+ build-vc2013-zip-64.bat \
+ build-vc2013-msi-32.bat \
+ build-vc2013-msi-64.bat
diff --git a/storage/mroonga/packages/windows/README.md b/storage/mroonga/packages/windows/README.md
new file mode 100644
index 00000000000..f7788ffe26b
--- /dev/null
+++ b/storage/mroonga/packages/windows/README.md
@@ -0,0 +1,20 @@
+# How to build Windows binaries
+
+## Preparation
+
+TODO...
+
+## Build with Visual C++ Express
+
+You need to use Visual C++ 2012 or later to build Mroonga with Express
+edition. `build-vc2013.bat` is a build batch script to build with
+Visual C++ Express 2013.
+
+Note that you can't build MSI file with Express edition. You need to
+use Professional edition or upper editions to build MSI file.
+
+## Build with Visual C++ Professional
+
+You can build both zip file MSI file with Professional edition.
+`build-vc2010.bat` is a build batch script to build with Visual C++
+Professional 2010.
diff --git a/storage/mroonga/packages/windows/build-vc2010-msi-32.bat b/storage/mroonga/packages/windows/build-vc2010-msi-32.bat
new file mode 100644
index 00000000000..15185eaba92
--- /dev/null
+++ b/storage/mroonga/packages/windows/build-vc2010-msi-32.bat
@@ -0,0 +1,8 @@
+rmdir /S /Q build-vc2010-msi-32
+mkdir build-vc2010-msi-32
+cd build-vc2010-msi-32
+cmake ..\source -G "Visual Studio 10" > config.log
+cmake --build . --config RelWithDebInfo > build.log
+cmake --build . --config RelWithDebInfo --target msi > msi.log
+move *.msi ..\
+cd ..
diff --git a/storage/mroonga/packages/windows/build-vc2010-msi-64.bat b/storage/mroonga/packages/windows/build-vc2010-msi-64.bat
new file mode 100644
index 00000000000..ea0b7f07eb3
--- /dev/null
+++ b/storage/mroonga/packages/windows/build-vc2010-msi-64.bat
@@ -0,0 +1,8 @@
+rmdir /S /Q build-vc2010-msi-64
+mkdir build-vc2010-msi-64
+cd build-vc2010-msi-64
+cmake ..\source -G "Visual Studio 10 Win64" > config.log
+cmake --build . --config RelWithDebInfo > build.log
+cmake --build . --config RelWithDebInfo --target msi > msi.log
+move *.msi ..\
+cd ..
diff --git a/storage/mroonga/packages/windows/build-vc2010-zip-32.bat b/storage/mroonga/packages/windows/build-vc2010-zip-32.bat
new file mode 100644
index 00000000000..013080755d4
--- /dev/null
+++ b/storage/mroonga/packages/windows/build-vc2010-zip-32.bat
@@ -0,0 +1,8 @@
+rmdir /S /Q build-vc2010-zip-32
+mkdir build-vc2010-zip-32
+cd build-vc2010-zip-32
+cmake ..\source -G "Visual Studio 10" -DMRN_GROONGA_EMBED=OFF -DMRN_GROONGA_NORMALIZER_MYSQL_EMBED=OFF > config.log
+cmake --build . --config RelWithDebInfo > build.log
+cmake --build . --config RelWithDebInfo --target package > zip.log
+move *.zip ..\
+cd ..
diff --git a/storage/mroonga/packages/windows/build-vc2010-zip-64.bat b/storage/mroonga/packages/windows/build-vc2010-zip-64.bat
new file mode 100644
index 00000000000..040c921fcef
--- /dev/null
+++ b/storage/mroonga/packages/windows/build-vc2010-zip-64.bat
@@ -0,0 +1,8 @@
+rmdir /S /Q build-vc2010-zip-64
+mkdir build-vc2010-zip-64
+cd build-vc2010-zip-64
+cmake ..\source -G "Visual Studio 10 Win64" -DMRN_GROONGA_EMBED=OFF -DMRN_GROONGA_NORMALIZER_MYSQL_EMBED=OFF > config.log
+cmake --build . --config RelWithDebInfo > build.log
+cmake --build . --config RelWithDebInfo --target package > zip.log
+move *.zip ..\
+cd ..
diff --git a/storage/mroonga/packages/windows/build-vc2010.bat b/storage/mroonga/packages/windows/build-vc2010.bat
new file mode 100644
index 00000000000..5fcf0639412
--- /dev/null
+++ b/storage/mroonga/packages/windows/build-vc2010.bat
@@ -0,0 +1,4 @@
+build-vc2010-zip-32.bat
+build-vc2010-zip-64.bat
+build-vc2010-msi-32.bat
+build-vc2010-msi-64.bat
diff --git a/storage/mroonga/packages/windows/build-vc2013-msi-32.bat b/storage/mroonga/packages/windows/build-vc2013-msi-32.bat
new file mode 100644
index 00000000000..22b29972885
--- /dev/null
+++ b/storage/mroonga/packages/windows/build-vc2013-msi-32.bat
@@ -0,0 +1,8 @@
+rmdir /S /Q build-vc2013-msi-32
+mkdir build-vc2013-msi-32
+cd build-vc2013-msi-32
+cmake ..\source -G "Visual Studio 12" > config.log
+cmake --build . --config RelWithDebInfo > build.log
+cmake --build . --config RelWithDebInfo --target msi > msi.log
+move *.msi ..\
+cd ..
diff --git a/storage/mroonga/packages/windows/build-vc2013-msi-64.bat b/storage/mroonga/packages/windows/build-vc2013-msi-64.bat
new file mode 100644
index 00000000000..c83a376cdb9
--- /dev/null
+++ b/storage/mroonga/packages/windows/build-vc2013-msi-64.bat
@@ -0,0 +1,8 @@
+rmdir /S /Q build-vc2013-msi-64
+mkdir build-vc2013-msi-64
+cd build-vc2013-msi-64
+cmake ..\source -G "Visual Studio 12 Win64" > config.log
+cmake --build . --config RelWithDebInfo > build.log
+cmake --build . --config RelWithDebInfo --target msi > msi.log
+move *.msi ..\
+cd ..
diff --git a/storage/mroonga/packages/windows/build-vc2013-zip-32.bat b/storage/mroonga/packages/windows/build-vc2013-zip-32.bat
new file mode 100644
index 00000000000..d3e0e4f8b8e
--- /dev/null
+++ b/storage/mroonga/packages/windows/build-vc2013-zip-32.bat
@@ -0,0 +1,8 @@
+rmdir /S /Q build-vc2013-zip-32
+mkdir build-vc2013-zip-32
+cd build-vc2013-zip-32
+cmake ..\source -G "Visual Studio 12" -DMRN_GROONGA_EMBED=OFF -DMRN_GROONGA_NORMALIZER_MYSQL_EMBED=OFF > config.log
+cmake --build . --config RelWithDebInfo > build.log
+cmake --build . --config RelWithDebInfo --target package > zip.log
+move *.zip ..\
+cd ..
diff --git a/storage/mroonga/packages/windows/build-vc2013-zip-64.bat b/storage/mroonga/packages/windows/build-vc2013-zip-64.bat
new file mode 100644
index 00000000000..6ca288b6a8b
--- /dev/null
+++ b/storage/mroonga/packages/windows/build-vc2013-zip-64.bat
@@ -0,0 +1,8 @@
+rmdir /S /Q build-vc2013-zip-64
+mkdir build-vc2013-zip-64
+cd build-vc2013-zip-64
+cmake ..\source -G "Visual Studio 12 Win64" -DMRN_GROONGA_EMBED=OFF -DMRN_GROONGA_NORMALIZER_MYSQL_EMBED=OFF > config.log
+cmake --build . --config RelWithDebInfo > build.log
+cmake --build . --config RelWithDebInfo --target package > zip.log
+move *.zip ..\
+cd ..
diff --git a/storage/mroonga/packages/windows/build-vc2013.bat b/storage/mroonga/packages/windows/build-vc2013.bat
new file mode 100644
index 00000000000..99d7e4042c5
--- /dev/null
+++ b/storage/mroonga/packages/windows/build-vc2013.bat
@@ -0,0 +1,4 @@
+build-vc2013-zip-32.bat
+build-vc2013-zip-64.bat
+REM build-vc2013-msi-32.bat
+REM build-vc2013-msi-64.bat
diff --git a/storage/mroonga/packages/yum/Makefile.am b/storage/mroonga/packages/yum/Makefile.am
new file mode 100644
index 00000000000..b110b478a14
--- /dev/null
+++ b/storage/mroonga/packages/yum/Makefile.am
@@ -0,0 +1,63 @@
+REPOSITORIES_PATH = repositories
+DISTRIBUTIONS = centos
+ARCHITECTURES = i386 x86_64
+MYSQL_VARIANTS = mysql55 mysql56-community mariadb
+SPEC_DIR = $(builddir)/../rpm/centos
+
+all:
+
+release: download build sign-packages update-repository upload
+
+remove-existing-packages:
+ for distribution in $(DISTRIBUTIONS); do \
+ find $${distribution} -name "*.rpm" -delete; \
+ done
+
+ensure-rsync-path:
+ @if test -z "$(RSYNC_PATH)"; then \
+ echo "--with-rsync-path configure option must be specified."; \
+ false; \
+ fi
+
+sign-packages:
+ ./sign-rpm.sh '$(GPG_UID)' '$(REPOSITORIES_PATH)/' '$(DISTRIBUTIONS)'
+
+update-repository:
+ ./update-repository.sh '$(REPOSITORIES_PATH)/' '$(DISTRIBUTIONS)'
+
+upload: ensure-rsync-path
+ for distribution in $(DISTRIBUTIONS); do \
+ rsync -avz --progress --delete --exclude .gitignore \
+ $(REPOSITORIES_PATH)/$${distribution}/ \
+ $(RSYNC_PATH)/$${distribution}; \
+ done
+
+download: ensure-rsync-path
+ mkdir -p $(REPOSITORIES_PATH)
+ for distribution in $(DISTRIBUTIONS); do \
+ rsync -avz --progress --delete \
+ $(RSYNC_PATH)/$${distribution}/ \
+ $(REPOSITORIES_PATH)/$${distribution}; \
+ done
+
+build: build-in-vm
+
+build-in-vm: source specs env.sh
+ ./build-in-vm.sh \
+ "$(PACKAGE)" \
+ "$(SPEC_DIR)" \
+ "$(MYSQL_VARIANTS)" \
+ "$(ARCHITECTURES)"
+
+source: tmp/$(PACKAGE)-$(VERSION).tar.gz
+
+tmp/$(PACKAGE)-$(VERSION).tar.gz: $(abs_top_builddir)/$(PACKAGE)-$(VERSION).tar.gz
+ mkdir -p tmp/
+ cp $(abs_top_builddir)/$(PACKAGE)-$(VERSION).tar.gz tmp/
+
+$(abs_top_builddir)/$(PACKAGE)-$(VERSION).tar.gz:
+ cd $(abs_top_builddir) && $(MAKE) dist
+
+specs: $(SPEC_DIR)/mysql55-$(PACKAGE).spec
+specs: $(SPEC_DIR)/mysql56-community-$(PACKAGE).spec
+specs: $(SPEC_DIR)/mariadb-$(PACKAGE).spec
diff --git a/storage/mroonga/packages/yum/Vagrantfile b/storage/mroonga/packages/yum/Vagrantfile
new file mode 100644
index 00000000000..1a9e4584ee4
--- /dev/null
+++ b/storage/mroonga/packages/yum/Vagrantfile
@@ -0,0 +1,50 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+
+# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
+VAGRANTFILE_API_VERSION = "2"
+
+Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
+ vms = [
+ {
+ :id => "centos-5-i386",
+ :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-5.11-i386_chef-provisionerless.box",
+ },
+ {
+ :id => "centos-5-x86_64",
+ :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-5.11_chef-provisionerless.box",
+ },
+ {
+ :id => "centos-6-i386",
+ :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.6-i386_chef-provisionerless.box",
+ },
+ {
+ :id => "centos-6-x86_64",
+ :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.6_chef-provisionerless.box",
+ },
+ {
+ :id => "centos-7-x86_64",
+ :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-7.0_chef-provisionerless.box",
+ },
+ ]
+
+ vms.each do |vm|
+ config.vm.define(vm[:id]) do |node|
+ node.vm.box = vm[:id]
+ node.vm.box_url = vm[:box_url]
+ node.vm.provision(:shell, :path => "build-rpm.sh")
+ node.vm.provider("virtualbox") do |virtual_box|
+ system_n_cpus = 1
+ if File.exist?("/proc/cpuinfo")
+ system_n_cpus = File.readlines("/proc/cpuinfo").grep(/^processor/).size
+ end
+ if system_n_cpus > 1
+ vm_n_cpus = system_n_cpus / 2
+ else
+ vm_n_cpus = 1
+ end
+ virtual_box.cpus = vm_n_cpus
+ end
+ end
+ end
+end
diff --git a/storage/mroonga/packages/yum/build-in-vm.sh b/storage/mroonga/packages/yum/build-in-vm.sh
new file mode 100755
index 00000000000..5dc27ec38dd
--- /dev/null
+++ b/storage/mroonga/packages/yum/build-in-vm.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+if [ $# != 4 ]; then
+ echo "Usage: $0 PACKAGE SPEC_DIR MYSQL_VARIANTS ARCHITECTURES"
+ echo " e.g.: $0 mroonga ../rpm/centos 'mysql55 mariadb' 'i386 x86_64'"
+ exit 1
+fi
+
+PACKAGE="$1"
+SPEC_DIR="$2"
+MYSQL_VARIANTS="$3"
+ARCHITECTURES="$4"
+
+run()
+{
+ "$@"
+ if test $? -ne 0; then
+ echo "Failed $@"
+ exit 1
+ fi
+}
+
+run vagrant destroy --force
+
+for mysql_variant in ${MYSQL_VARIANTS}; do
+ rm -rf tmp/centos/
+ mkdir -p tmp/centos/
+ cp ${SPEC_DIR}/${mysql_variant}-${PACKAGE}.spec tmp/centos/
+
+ architectures="${ARCHITECTURES}"
+ case ${mysql_variant} in
+ mysql55)
+ centos_versions="5 6"
+ ;;
+ mysql56-community)
+ centos_versions="6 7"
+ ;;
+ mariadb)
+ centos_versions="7"
+ ;;
+ esac
+
+ for architecture in ${architectures}; do
+ for centos_version in ${centos_versions}; do
+ if [ ${mysql_variant} = mysql55 -a ${centos_version} = 6 -a ${architecture} = i386 ]; then
+ continue
+ fi
+ if [ ${centos_version} = 7 -a ${architecture} = i386 ]; then
+ continue
+ fi
+ id=centos-${centos_version}-${architecture}
+ vagrant up ${id}
+ build_status=$?
+ if [ $build_status -ne 0 ]; then
+ exit $build_status
+ fi
+ vagrant destroy --force ${id}
+ done
+ done
+done
diff --git a/storage/mroonga/packages/yum/build-rpm.sh b/storage/mroonga/packages/yum/build-rpm.sh
new file mode 100755
index 00000000000..6eaa2cce02a
--- /dev/null
+++ b/storage/mroonga/packages/yum/build-rpm.sh
@@ -0,0 +1,108 @@
+#!/bin/sh
+
+LANG=C
+
+run()
+{
+ "$@"
+ if test $? -ne 0; then
+ echo "Failed $@"
+ exit 1
+ fi
+}
+
+rpmbuild_options=
+
+. /vagrant/env.sh
+
+distribution=$(cut -d " " -f 1 /etc/redhat-release | tr "A-Z" "a-z")
+if grep -q Linux /etc/redhat-release; then
+ distribution_version=$(cut -d " " -f 4 /etc/redhat-release)
+else
+ distribution_version=$(cut -d " " -f 3 /etc/redhat-release)
+fi
+distribution_version=$(echo ${distribution_version} | sed -e 's/\..*$//g')
+
+architecture="$(arch)"
+case "${architecture}" in
+ i*86)
+ architecture=i386
+ ;;
+esac
+
+run yum groupinstall -y "Development Tools"
+run yum install -y rpm-build rpmdevtools tar wget
+
+if [ -x /usr/bin/rpmdev-setuptree ]; then
+ rm -rf .rpmmacros
+ run rpmdev-setuptree
+else
+ run cat <<EOM > ~/.rpmmacros
+%_topdir ${HOME}/rpmbuild
+EOM
+ run mkdir -p ~/rpmbuild/SOURCES
+ run mkdir -p ~/rpmbuild/SPECS
+ run mkdir -p ~/rpmbuild/BUILD
+ run mkdir -p ~/rpmbuild/RPMS
+ run mkdir -p ~/rpmbuild/SRPMS
+fi
+
+repository="/vagrant/repositories/${distribution}/${distribution_version}"
+rpm_dir="${repository}/${architecture}/Packages"
+srpm_dir="${repository}/source/SRPMS"
+run mkdir -p "${rpm_dir}" "${srpm_dir}"
+
+rpmbuild_options=""
+
+# for debug
+# rpmbuild_options="${rpmbuild_options} --define 'optflags -O0 -g3'"
+
+cd
+
+run cp /vagrant/tmp/${PACKAGE}-${VERSION}.* rpmbuild/SOURCES/
+run cp /vagrant/tmp/${distribution}/*.spec rpmbuild/SPECS/
+
+package_name=$(cd rpmbuild/SPECS; echo *.spec | sed -e 's/\.spec$//g')
+
+case ${distribution} in
+ fedora)
+ USE_MYSQLSERVICES_COMPAT=yes
+ run yum install -y mariadb-devel
+ ;;
+ centos)
+ case ${package_name} in
+ mysql55-${PACKAGE})
+ USE_MYSQLSERVICES_COMPAT=yes
+ run yum install -y scl-utils-build
+ if [ ${distribution_version} = 6 ]; then
+ run yum install -y centos-release-SCL
+ fi
+ run yum install -y mysql55-mysql-devel mysql55-build
+ ;;
+ mysql56-community-${PACKAGE})
+ release_rpm=mysql-community-release-el${distribution_version}-5.noarch.rpm
+ run yum -y install http://repo.mysql.com/${release_rpm}
+ run yum -y install mysql-community-devel
+ ;;
+ mariadb-${PACKAGE})
+ run yum -y install mariadb-devel
+ ;;
+ esac
+
+ release_rpm=groonga-release-1.1.0-1.noarch.rpm
+ wget http://packages.groonga.org/${distribution}/${release_rpm}
+ run rpm -U ${release_rpm}
+ rm -f ${release_rpm}
+ run yum makecache
+ ;;
+esac
+run yum install -y ${DEPENDED_PACKAGES}
+
+if [ "${USE_MYSQLSERVICES_COMPAT}" = "yes" ]; then
+ rpmbuild_options="$rpmbuild_options --define 'mroonga_configure_options --with-libmysqlservices-compat'"
+fi
+
+run eval rpmbuild -ba ${rpmbuild_options} rpmbuild/SPECS/${package_name}.spec
+
+run mv rpmbuild/RPMS/*/* "${rpm_dir}/"
+run mv rpmbuild/SRPMS/* "${srpm_dir}/"
diff --git a/storage/mroonga/packages/yum/env.sh.in b/storage/mroonga/packages/yum/env.sh.in
new file mode 100644
index 00000000000..90e701ec89e
--- /dev/null
+++ b/storage/mroonga/packages/yum/env.sh.in
@@ -0,0 +1,27 @@
+PACKAGE=@PACKAGE@
+VERSION=@VERSION@
+DEPENDED_PACKAGES="
+intltool
+libtool
+gcc
+gcc-c++
+make
+gperf
+readline-devel
+openssl-devel
+time
+wget
+ncurses-devel
+sudo
+pkgconfig
+tar
+cmake
+libaio-devel
+systemtap-sdt-devel
+perl-Time-HiRes
+perl-Env
+perl-Test-Simple
+pam-devel
+groonga-devel
+groonga-normalizer-mysql-devel
+"
diff --git a/storage/mroonga/packages/yum/sign-rpm.sh b/storage/mroonga/packages/yum/sign-rpm.sh
new file mode 100755
index 00000000000..b3a45afe7f5
--- /dev/null
+++ b/storage/mroonga/packages/yum/sign-rpm.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+script_base_dir=`dirname $0`
+
+if [ $# != 3 ]; then
+ echo "Usage: $0 GPG_UID DESTINATION DISTRIBUTIONS"
+ echo " e.g.: $0 'F10399C0' repositories/ 'fedora centos'"
+ exit 1
+fi
+
+GPG_UID=$1
+DESTINATION=$2
+DISTRIBUTIONS=$3
+
+run()
+{
+ "$@"
+ if test $? -ne 0; then
+ echo "Failed $@"
+ exit 1
+ fi
+}
+
+unsigned_rpms()
+{
+ while read rpm; do
+ rpm --checksig "$rpm" | grep -v 'gpg OK' | cut -d":" -f1
+ done
+}
+
+if ! gpg --list-keys "${GPG_UID}" > /dev/null 2>&1; then
+ run gpg --keyserver keyserver.ubuntu.com --recv-key "${GPG_UID}"
+fi
+run mkdir -p tmp
+run gpg --armor --export "${GPG_UID}" > tmp/sign-key
+run rpm --import tmp/sign-key
+run rm -rf tmp/sign-key
+
+rpms=""
+for distribution in ${DISTRIBUTIONS}; do
+ rpms="${rpms} $(find ${DESTINATION}${distribution} -name '*.rpm' | unsigned_rpms)"
+done
+
+echo "NOTE: YOU JUST ENTER! YOU DON'T NEED TO INPUT PASSWORD!"
+echo " IT'S JUST FOR rpm COMMAND RESTRICTION!"
+run echo $rpms | xargs rpm \
+ -D "_gpg_name ${GPG_UID}" \
+ -D "_gpg_digest_algo sha1" \
+ -D "__gpg /usr/bin/gpg2" \
+ -D "__gpg_check_password_cmd /bin/true true" \
+ -D "__gpg_sign_cmd %{__gpg} gpg --batch --no-verbose --no-armor %{?_gpg_digest_algo:--digest-algo %{_gpg_digest_algo}} --no-secmem-warning -u \"%{_gpg_name}\" -sbo %{__signature_filename} %{__plaintext_filename}" \
+ --resign
diff --git a/storage/mroonga/packages/yum/update-repository.sh b/storage/mroonga/packages/yum/update-repository.sh
new file mode 100755
index 00000000000..630b6c87422
--- /dev/null
+++ b/storage/mroonga/packages/yum/update-repository.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+script_base_dir=`dirname $0`
+
+if [ $# != 2 ]; then
+ echo "Usage: $0 DESTINATION DISTRIBUTIONS"
+ echo " e.g.: $0 repositories/ 'fedora centos'"
+ exit 1
+fi
+
+DESTINATION=$1
+DISTRIBUTIONS=$2
+
+run()
+{
+ "$@"
+ if test $? -ne 0; then
+ echo "Failed $@"
+ exit 1
+ fi
+}
+
+for distribution in ${DISTRIBUTIONS}; do
+ for dir in ${DESTINATION}${distribution}/*/*; do
+ # "--checksum sha" is for CentOS 5. If we drop CentOS 5 support,
+ # we can remove the option.
+ test -d $dir && run createrepo --checksum sha $dir
+ done;
+done
diff --git a/storage/mroonga/plugin_version b/storage/mroonga/plugin_version
index be9fc83102e..6e636605163 100644
--- a/storage/mroonga/plugin_version
+++ b/storage/mroonga/plugin_version
@@ -1 +1 @@
-4.6 \ No newline at end of file
+5.0 \ No newline at end of file
diff --git a/storage/mroonga/required_groonga_version b/storage/mroonga/required_groonga_version
index fcdb2e109f6..43beb4001b8 100644
--- a/storage/mroonga/required_groonga_version
+++ b/storage/mroonga/required_groonga_version
@@ -1 +1 @@
-4.0.0
+4.0.7
diff --git a/storage/mroonga/tools/travis/install.sh b/storage/mroonga/tools/travis/install.sh
index fd3d2187914..95b8b23ba19 100755
--- a/storage/mroonga/tools/travis/install.sh
+++ b/storage/mroonga/tools/travis/install.sh
@@ -21,8 +21,8 @@ set -e
mariadb_download_base=http://mirror.jmu.edu/pub/mariadb
-export GROONGA_MASTER=yes
-export GROONGA_NORMALIZER_MYSQL_MASTER=yes
+# export GROONGA_MASTER=yes
+# export GROONGA_NORMALIZER_MYSQL_MASTER=yes
curl --silent --location https://github.com/groonga/groonga/raw/master/data/travis/setup.sh | sh
curl --silent --location https://github.com/groonga/groonga-normalizer-mysql/raw/master/data/travis/setup.sh | sh
@@ -43,6 +43,7 @@ if [ "${MROONGA_BUNDLED}" = "yes" ]; then
curl -O ${download_base}/source/${tar_gz}
tar xzf $tar_gz
mv ${MYSQL_VERSION}/* ./
+ rm -rf storage/mroonga
mv .mroonga storage/mroonga
rm -rf ${MYSQL_VERSION}
else
@@ -57,7 +58,8 @@ else
sudo apt-get -qq -y build-dep mysql-server
if [ "$version" = "system" ]; then
sudo apt-get -qq -y install \
- mysql-server mysql-testsuite libmysqld-dev
+ mysql-server mysql-server-5.5 mysql-server-core-5.5 \
+ mysql-testsuite libmysqld-dev
apt-get -qq source mysql-server
ln -s $(find . -maxdepth 1 -type d | sort | tail -1) mysql
else
diff --git a/storage/mroonga/udf/mrn_udf_command.cpp b/storage/mroonga/udf/mrn_udf_command.cpp
index ba92e8daa26..172f64896a2 100644
--- a/storage/mroonga/udf/mrn_udf_command.cpp
+++ b/storage/mroonga/udf/mrn_udf_command.cpp
@@ -26,10 +26,10 @@
#include <mrn_macro.hpp>
#include <mrn_database_manager.hpp>
-extern mrn::DatabaseManager *mrn_db_manager;
-
MRN_BEGIN_DECLS
+extern mrn::DatabaseManager *mrn_db_manager;
+
struct CommandInfo
{
grn_ctx ctx;
@@ -100,7 +100,7 @@ error:
grn_obj_close(&(info->ctx), info->db);
}
grn_ctx_fin(&(info->ctx));
- my_free(info, MYF(0));
+ my_free(info);
}
return TRUE;
}
@@ -164,7 +164,7 @@ MRN_API void mroonga_command_deinit(UDF_INIT *initid)
}
grn_ctx_fin(&(info->ctx));
info->result.free();
- my_free(info, MYF(0));
+ my_free(info);
}
}
diff --git a/storage/mroonga/udf/mrn_udf_escape.cpp b/storage/mroonga/udf/mrn_udf_escape.cpp
index ff997e7581f..36179788596 100644
--- a/storage/mroonga/udf/mrn_udf_escape.cpp
+++ b/storage/mroonga/udf/mrn_udf_escape.cpp
@@ -81,7 +81,7 @@ MRN_API my_bool mroonga_escape_init(UDF_INIT *initid, UDF_ARGS *args,
error:
if (info) {
grn_ctx_fin(&(info->ctx));
- my_free(info, MYF(0));
+ my_free(info);
}
return TRUE;
}
@@ -147,7 +147,7 @@ MRN_API void mroonga_escape_deinit(UDF_INIT *initid)
grn_obj_unlink(&(info->ctx), &(info->target_characters));
grn_obj_unlink(&(info->ctx), &(info->escaped_query));
grn_ctx_fin(&(info->ctx));
- my_free(info, MYF(0));
+ my_free(info);
}
}
diff --git a/storage/mroonga/udf/mrn_udf_snippet.cpp b/storage/mroonga/udf/mrn_udf_snippet.cpp
index 84166a36f16..3eaf05eed95 100644
--- a/storage/mroonga/udf/mrn_udf_snippet.cpp
+++ b/storage/mroonga/udf/mrn_udf_snippet.cpp
@@ -198,7 +198,7 @@ error:
if (snip_info) {
grn_obj_close(&snip_info->ctx, grn_ctx_db(&snip_info->ctx));
grn_ctx_fin(&snip_info->ctx);
- my_free(snip_info, MYF(0));
+ my_free(snip_info);
}
return TRUE;
}
@@ -295,7 +295,7 @@ MRN_API void mroonga_snippet_deinit(UDF_INIT *initid)
snip_info->result_str.free();
grn_obj_close(&snip_info->ctx, grn_ctx_db(&snip_info->ctx));
grn_ctx_fin(&snip_info->ctx);
- my_free(snip_info, MYF(0));
+ my_free(snip_info);
}
}
diff --git a/storage/mroonga/vendor/groonga/CMakeLists.txt b/storage/mroonga/vendor/groonga/CMakeLists.txt
index abaa9911fd6..cddb3df28f6 100644
--- a/storage/mroonga/vendor/groonga/CMakeLists.txt
+++ b/storage/mroonga/vendor/groonga/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright(C) 2012-2014 Brazil
+# Copyright(C) 2012-2015 Brazil
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -20,12 +20,19 @@ cmake_minimum_required(VERSION 2.6.2)
set(GRN_PROJECT_NAME "groonga")
project("${GRN_PROJECT_NAME}")
+if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ set(CMAKE_COMPILER_IS_CLANGC ON)
+endif()
+if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+ set(CMAKE_COMPILER_IS_CLANGCXX ON)
+endif()
+
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/base_version" VERSION)
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/version.sh")
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/version.sh" GRN_VERSION)
else()
if(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/version.sh")
- if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git")
+ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git" AND EXISTS "/bin/sh")
execute_process(COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/version-gen.sh")
file(READ "${CMAKE_CURRENT_BINARY_DIR}/version.sh" GRN_VERSION)
else()
@@ -44,6 +51,15 @@ include(CheckCXXCompilerFlag)
include(FindPkgConfig)
include(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake_modules/ReadFileList.cmake)
+if(DEFINED GRN_EMBED)
+ set(GRN_EMBED_DEFAULT ${GRN_EMBED})
+else()
+ set(GRN_EMBED_DEFAULT OFF)
+endif()
+option(GRN_EMBED
+ "Build as a static library to embed into an application"
+ ${GRN_EMBED_DEFAULT})
+
set(BIN_DIR "bin")
set(SBIN_DIR "sbin")
set(LIB_DIR "lib")
@@ -53,10 +69,14 @@ set(DATA_DIR "share")
set(GRN_DATA_DIR "${DATA_DIR}/${GRN_PROJECT_NAME}")
set(CONFIG_DIR "etc")
set(GRN_CONFIG_DIR "${CONFIG_DIR}/${GRN_PROJECT_NAME}")
+set(GRN_CONFIG_PATH "${CMAKE_INSTALL_PREFIX}/${GRN_CONFIG_DIR}/groonga.conf")
set(GRN_LOG_PATH
"${CMAKE_INSTALL_PREFIX}/var/log/${GRN_PROJECT_NAME}/${GRN_PROJECT_NAME}.log"
CACHE FILEPATH "log file path")
+set(GRN_DEFAULT_ENCODING
+ "utf8"
+ CACHE STRING "Groonga's default encoding")
set(GRN_DEFAULT_MATCH_ESCALATION_THRESHOLD
0
CACHE STRING "groonga default match escalation threshold")
@@ -69,6 +89,9 @@ set(GRN_DEFAULT_RELATIVE_DOCUMENT_ROOT
set(GRN_DEFAULT_DOCUMENT_ROOT
"${CMAKE_INSTALL_PREFIX}/${GRN_DATA_DIR}/${GRN_DEFAULT_DOCUMENT_ROOT_BASE}"
CACHE PATH "groonga default document root")
+set(GRN_DEFAULT_DB_KEY
+ "auto"
+ CACHE STRING "Groonga's default DB key management algorithm")
set(GRN_STACK_SIZE
1024
CACHE STRING
@@ -97,15 +120,21 @@ set(GRN_RUBY_SCRIPTS_DIR
"${CMAKE_INSTALL_PREFIX}/${GRN_RELATIVE_RUBY_SCRIPTS_DIR}")
macro(check_cflag flag)
- check_c_compiler_flag(${flag} "HAVE_C_${flag}")
- if(HAVE_C_${flag})
+ string(REGEX REPLACE "[-=]" "_" temporary_variable_name ${flag})
+ string(TOUPPER "${temporary_variable_name}" temporary_variable_name)
+ set(temporary_variable_name "CFLAG${temporary_variable_name}")
+ check_c_compiler_flag(${flag} ${temporary_variable_name})
+ if(${temporary_variable_name})
set(GRN_C_COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS} ${flag}")
endif()
endmacro()
macro(check_cxxflag flag)
- check_cxx_compiler_flag(${flag} "HAVE_CXX_${flag}")
- if(HAVE_CXX_${flag})
+ string(REGEX REPLACE "[-=]" "_" temporary_variable_name ${flag})
+ string(TOUPPER "${temporary_variable_name}" temporary_variable_name)
+ set(temporary_variable_name "CXXFLAG${temporary_variable_name}")
+ check_cxx_compiler_flag(${flag} ${temporary_variable_name})
+ if(${temporary_variable_name})
set(GRN_CXX_COMPILE_FLAGS "${GRN_CXX_COMPILE_FLAGS} ${flag}")
endif()
endmacro()
@@ -137,7 +166,10 @@ if(CMAKE_COMPILER_IS_GNUCXX)
check_cxxflag("-fexceptions")
check_cxxflag("-fimplicit-templates")
check_build_flag("-Wno-clobbered")
- if(MRN_GROONGA_BUNDLED)
+endif()
+
+if(GRN_EMBED)
+ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGCXX)
check_build_flag("-fPIC")
endif()
endif()
@@ -154,17 +186,15 @@ add_definitions(
-DHAVE_CONFIG_H
)
-if(CMAKE_COMPILER_IS_GNUC OR
- CMAKE_COMPILER_IS_GNUCXX OR
- CMAKE_C_COMPILER_ID STREQUAL "Clang")
+if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGCXX)
set(_GNU_SOURCE TRUE)
endif()
include_directories(
BEFORE
${CMAKE_CURRENT_BINARY_DIR}
- ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
+ ${CMAKE_CURRENT_SOURCE_DIR}/lib
)
macro(ac_check_headers header)
@@ -202,6 +232,7 @@ include(build/ac_macros/check_headers.m4)
include(build/ac_macros/check_functions.m4)
ac_check_symbols(fpclassify math.h)
+ac_check_lib(m fpclassify)
ac_check_lib(dl dlopen)
ac_check_lib(execinfo backtrace)
@@ -214,8 +245,7 @@ ac_check_lib(rt clock_gettime)
if(HAVE_LIBRT)
set(HAVE_CLOCK_GETTIME TRUE)
endif()
-if(MRN_GROONGA_BUNDLED)
- ac_check_lib(m sincos)
+if(GRN_EMBED)
check_library_exists(stdc++ __cxa_begin_catch "${ARG2}"
STDCPP)
if(STDCPP)
@@ -293,19 +323,29 @@ else()
endif()
endif()
-option(GRN_WITH_ZLIB "use zlib for data compression." OFF)
-if(GRN_WITH_ZLIB)
+set(GRN_WITH_ZLIB "auto"
+ CACHE STRING "Support data compression by zlib.")
+if(NOT ${GRN_WITH_ZLIB} STREQUAL "no")
ac_check_lib(z compress)
if(NOT HAVE_LIBZ)
- message(FATAL_ERROR "No libz found")
+ if(${GRN_WITH_ZLIB} STREQUAL "yes")
+ message(FATAL_ERROR "No libz found")
+ endif()
+ set(GRN_WITH_ZLIB "no")
endif()
endif()
-option(GRN_WITH_LZO "use LZO for data compression." OFF)
-if(GRN_WITH_LZO)
- ac_check_lib(lzo2 lzo1_compress)
- if(NOT HAVE_LIBLZO2)
- message(FATAL_ERROR "No liblzo2 found")
+set(GRN_WITH_LZ4 "auto"
+ CACHE STRING "Support data compression by LZ4.")
+if(NOT ${GRN_WITH_LZ4} STREQUAL "no")
+ pkg_check_modules(LIBLZ4 liblz4)
+ if(LIBLZ4_FOUND)
+ set(GRN_WITH_LZ4 TRUE)
+ else()
+ if(${GRN_WITH_LZ4} STREQUAL "yes")
+ message(FATAL_ERROR "No LZ4 found")
+ endif()
+ set(GRN_WITH_LZ4 FALSE)
endif()
endif()
@@ -362,6 +402,38 @@ else()
set(GRN_WITH_KYTEA FALSE)
endif()
+set(GRN_WITH_LIBSTEMMER "auto"
+ CACHE STRING "use libstemmer for stemming token filter")
+if(NOT ${GRN_WITH_LIBSTEMMER} STREQUAL "no")
+ if(NOT ("${GRN_WITH_LIBSTEMMER}" STREQUAL "yes" OR
+ "${GRN_WITH_LIBSTEMMER}" STREQUAL "auto"))
+ if("${LIBSTEMMER_INCLUDE_DIRS}" STREQUAL "")
+ set(LIBSTEMMER_INCLUDE_DIRS "${GRN_WITH_LIBSTEMMER}/include")
+ endif()
+ if("${LIBSTEMMER_LIBRARY_DIRS}" STREQUAL "")
+ set(LIBSTEMMER_LIBRARY_DIRS "${GRN_WITH_LIBSTEMMER}/lib")
+ endif()
+ endif()
+ set(CMAKE_REQUIRED_INCLUDES_SAVE ${CMAKE_REQUIRED_INCLUDES})
+ set(CMAKE_REQUIRED_INCLUDES
+ ${CMAKE_REQUIRED_INCLUDES}
+ ${LIBSTEMMER_INCLUDE_DIRS})
+ ac_check_headers(libstemmer.h)
+ ac_check_lib(stemmer sb_stemmer_list "${LIBSTEMMER_LIBRARY_DIRS}")
+ set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES_SAVE})
+ if(HAVE_LIBSTEMMER_H AND HAVE_LIBSTEMMER)
+ set(LIBSTEMMER_LIBRARIES "stemmer")
+ set(GRN_WITH_LIBSTEMMER TRUE)
+ else()
+ if(${GRN_WITH_LIBSTEMMER} STREQUAL "yes")
+ message(FATAL_ERROR "No libstemmer found")
+ endif()
+ set(GRN_WITH_LIBSTEMMER FALSE)
+ endif()
+else()
+ set(GRN_WITH_LIBSTEMMER FALSE)
+endif()
+
set(GRN_WITH_ZEROMQ "auto"
CACHE STRING "use ZeroMQ for suggestion")
if(NOT ${GRN_WITH_ZEROMQ} STREQUAL "no")
@@ -447,12 +519,16 @@ else()
set(MRUBY_LIBS "")
endif()
-#add_subdirectory(vendor)
+if(NOT GRN_EMBED)
+ add_subdirectory(vendor)
+endif()
add_subdirectory(lib)
-add_subdirectory(src)
-#add_subdirectory(plugins)
-add_subdirectory(include)
-#add_subdirectory(data)
+if(NOT GRN_EMBED)
+ add_subdirectory(src)
+ add_subdirectory(plugins)
+ add_subdirectory(include)
+ add_subdirectory(data)
+endif()
configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
@@ -476,10 +552,10 @@ set(GRN_EXPANDED_DEFAULT_DOCUMENT_ROOT "${GRN_DEFAULT_DOCUMENT_ROOT}")
set(EXEEXT "${CMAKE_EXECUTABLE_SUFFIX}")
configure_file(groonga.pc.in "${CMAKE_CURRENT_BINARY_DIR}/groonga.pc" @ONLY)
-if(NOT MRN_GROONGA_BUNDLED)
+if(NOT GRN_EMBED)
install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/groonga.pc"
DESTINATION "${LIB_DIR}/pkgconfig/")
endif()
-#add_subdirectory(vendor/plugins)
+add_subdirectory(vendor/plugins)
diff --git a/storage/mroonga/vendor/groonga/Makefile.am b/storage/mroonga/vendor/groonga/Makefile.am
index a5bf404d471..65b7c928770 100644
--- a/storage/mroonga/vendor/groonga/Makefile.am
+++ b/storage/mroonga/vendor/groonga/Makefile.am
@@ -69,7 +69,6 @@ update-latest-release: misc
misc/update-latest-release.rb \
$(PACKAGE) $(OLD_RELEASE) $(OLD_RELEASE_DATE) \
$(VERSION) $(NEW_RELEASE_DATE) \
- packages/rpm/fedora/groonga.spec.in \
packages/rpm/centos/groonga.spec.in \
packages/debian/changelog \
doc/source/install.rst \
diff --git a/storage/mroonga/vendor/groonga/appveyor.yml b/storage/mroonga/vendor/groonga/appveyor.yml
new file mode 100644
index 00000000000..aa4b65fb24e
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/appveyor.yml
@@ -0,0 +1,17 @@
+version: "{build}"
+clone_depth: 10
+build_script:
+ - cmake . -G "Visual Studio 12 Win64"
+ - cmake --build . --config RelWithDebInfo
+
+notifications:
+ - provider: Email
+ to:
+ - kou@clear-code.com
+ - groonga-commit@lists.sourceforge.jp
+ on_build_status_changed: true
+
+before_test:
+ - gem install grntest
+test_script:
+ - grntest --groonga src\groonga.exe --base-directory test\command test\command\suite
diff --git a/storage/mroonga/vendor/groonga/autogen.sh b/storage/mroonga/vendor/groonga/autogen.sh
index 9b3a98eab5d..66184bf13be 100755
--- a/storage/mroonga/vendor/groonga/autogen.sh
+++ b/storage/mroonga/vendor/groonga/autogen.sh
@@ -18,4 +18,9 @@ FreeBSD)
;;
esac
+if [ ! -e vendor/mruby-source/.git ]; then
+ rm -rf vendor/mruby-source
+fi
+git submodule update --init
+
${AUTORECONF:-autoreconf} --force --install
diff --git a/storage/mroonga/vendor/groonga/base_version b/storage/mroonga/vendor/groonga/base_version
index 9eefef7bd65..28cbf7c0aae 100644
--- a/storage/mroonga/vendor/groonga/base_version
+++ b/storage/mroonga/vendor/groonga/base_version
@@ -1 +1 @@
-4.0.6 \ No newline at end of file
+5.0.0 \ No newline at end of file
diff --git a/storage/mroonga/vendor/groonga/benchmark/bench-geo-distance.c b/storage/mroonga/vendor/groonga/benchmark/bench-geo-distance.c
index 8e1d819538b..72d1d79b73f 100644
--- a/storage/mroonga/vendor/groonga/benchmark/bench-geo-distance.c
+++ b/storage/mroonga/vendor/groonga/benchmark/bench-geo-distance.c
@@ -49,7 +49,7 @@
#include <string.h>
-#include <db.h>
+#include <grn_db.h>
#include <groonga.h>
#include "lib/benchmark.h"
diff --git a/storage/mroonga/vendor/groonga/benchmark/bench-geo-select.c b/storage/mroonga/vendor/groonga/benchmark/bench-geo-select.c
index b934f225330..7b57eaaffdc 100644
--- a/storage/mroonga/vendor/groonga/benchmark/bench-geo-select.c
+++ b/storage/mroonga/vendor/groonga/benchmark/bench-geo-select.c
@@ -58,7 +58,7 @@
#include <string.h>
-#include <db.h>
+#include <grn_db.h>
#include <groonga.h>
#include "lib/benchmark.h"
diff --git a/storage/mroonga/vendor/groonga/benchmark/bench-range-select.c b/storage/mroonga/vendor/groonga/benchmark/bench-range-select.c
index 4c0b500aae2..d45d453cba6 100644
--- a/storage/mroonga/vendor/groonga/benchmark/bench-range-select.c
+++ b/storage/mroonga/vendor/groonga/benchmark/bench-range-select.c
@@ -53,7 +53,7 @@
#include <stdio.h>
#include <string.h>
-#include <db.h>
+#include <grn_db.h>
#include <groonga.h>
#include "lib/benchmark.h"
diff --git a/storage/mroonga/vendor/groonga/build/ac_macros/check_functions.m4 b/storage/mroonga/vendor/groonga/build/ac_macros/check_functions.m4
index 5046e8ce6ab..72e3a9a545d 100644
--- a/storage/mroonga/vendor/groonga/build/ac_macros/check_functions.m4
+++ b/storage/mroonga/vendor/groonga/build/ac_macros/check_functions.m4
@@ -1,5 +1,8 @@
# -*- autoconf -*-
+AC_CHECK_FUNCS(_gmtime64_s)
+AC_CHECK_FUNCS(_localtime64_s)
+AC_CHECK_FUNCS(_stricmp)
AC_CHECK_FUNCS(_strnicmp)
AC_CHECK_FUNCS(_strtoui64)
AC_CHECK_FUNCS(close)
@@ -8,6 +11,8 @@ AC_CHECK_FUNCS(localtime_r)
AC_CHECK_FUNCS(mkostemp)
AC_CHECK_FUNCS(open)
AC_CHECK_FUNCS(read)
+AC_CHECK_FUNCS(strcasecmp)
AC_CHECK_FUNCS(strncasecmp)
AC_CHECK_FUNCS(strtoull)
+AC_CHECK_FUNCS(unlink)
AC_CHECK_FUNCS(write)
diff --git a/storage/mroonga/vendor/groonga/build/ac_macros/check_headers.m4 b/storage/mroonga/vendor/groonga/build/ac_macros/check_headers.m4
index 513f61afac4..17de74c11a5 100644
--- a/storage/mroonga/vendor/groonga/build/ac_macros/check_headers.m4
+++ b/storage/mroonga/vendor/groonga/build/ac_macros/check_headers.m4
@@ -1,9 +1,11 @@
# -*- autoconf -*-
+AC_CHECK_HEADERS(dirent.h)
AC_CHECK_HEADERS(dlfcn.h)
AC_CHECK_HEADERS(errno.h)
AC_CHECK_HEADERS(execinfo.h)
AC_CHECK_HEADERS(inttypes.h)
+AC_CHECK_HEADERS(io.h)
AC_CHECK_HEADERS(netdb.h)
AC_CHECK_HEADERS(netinet/in.h)
AC_CHECK_HEADERS(netinet/tcp.h)
diff --git a/storage/mroonga/vendor/groonga/config.h.cmake b/storage/mroonga/vendor/groonga/config.h.cmake
index d172bc36dba..e6482f070c7 100644
--- a/storage/mroonga/vendor/groonga/config.h.cmake
+++ b/storage/mroonga/vendor/groonga/config.h.cmake
@@ -83,8 +83,7 @@
#cmakedefine GRN_WITH_BENCHMARK
#cmakedefine GRN_WITH_CUTTER
#cmakedefine GRN_WITH_KYTEA
-#cmakedefine GRN_WITH_LIBMEMCACHED
-#cmakedefine GRN_WITH_LZO
+#cmakedefine GRN_WITH_LZ4
#cmakedefine GRN_WITH_MECAB
#cmakedefine GRN_WITH_MESSAGE_PACK
#cmakedefine GRN_WITH_MRUBY
@@ -93,10 +92,12 @@
#cmakedefine GRN_WITH_ZLIB
/* headers */
+#cmakedefine HAVE_DIRENT_H
#cmakedefine HAVE_DLFCN_H
#cmakedefine HAVE_ERRNO_H
#cmakedefine HAVE_EXECINFO_H
#cmakedefine HAVE_INTTYPES_H
+#cmakedefine HAVE_IO_H
#cmakedefine HAVE_LINUX_FUTEX_H
#cmakedefine HAVE_MEMORY_H
#cmakedefine HAVE_NETDB_H
@@ -133,6 +134,9 @@
#cmakedefine HAVE_MECAB_DICTIONARY_INFO_T
/* functions */
+#cmakedefine HAVE__GMTIME64_S
+#cmakedefine HAVE__LOCALTIME64_S
+#cmakedefine HAVE__STRICMP
#cmakedefine HAVE__STRNICMP
#cmakedefine HAVE__STRTOUI64
#cmakedefine HAVE_BACKTRACE
@@ -145,8 +149,10 @@
#cmakedefine HAVE_MKOSTEMP
#cmakedefine HAVE_OPEN
#cmakedefine HAVE_READ
+#cmakedefine HAVE_STRCASECMP
#cmakedefine HAVE_STRNCASECMP
#cmakedefine HAVE_STRTOULL
+#cmakedefine HAVE_UNLINK
#cmakedefine HAVE_WRITE
#cmakedefine HAVE_PTHREAD_MUTEXATTR_SETPSHARED
#cmakedefine HAVE_PTHREAD_CONDATTR_SETPSHARED
diff --git a/storage/mroonga/vendor/groonga/config.sh.in b/storage/mroonga/vendor/groonga/config.sh.in
index b4cec3caba1..d15e5e366e7 100644
--- a/storage/mroonga/vendor/groonga/config.sh.in
+++ b/storage/mroonga/vendor/groonga/config.sh.in
@@ -4,3 +4,4 @@ export GROONGA="@GROONGA@"
export GROONGA_HTTPD="@GROONGA_HTTPD@"
export GROONGA_SUGGEST_CREATE_DATASET="@GROONGA_SUGGEST_CREATE_DATASET@"
export GROONGA_BENCHMARK="@GROONGA_BENCHMARK@"
+export GROONGA_MRUBY="@GROONGA_MRUBY@"
diff --git a/storage/mroonga/vendor/groonga/configure.ac b/storage/mroonga/vendor/groonga/configure.ac
index 2be82a165e2..1d74bac30f4 100644
--- a/storage/mroonga/vendor/groonga/configure.ac
+++ b/storage/mroonga/vendor/groonga/configure.ac
@@ -75,7 +75,8 @@ AC_MSG_RESULT([$solaris])
AC_C_BIGENDIAN
AC_PROG_CXX
AC_PROG_CC
-AC_PROG_CC_C99
+m4_ifdef([AC_PROG_CC_C99],
+ [AC_PROG_CC_C99])
AM_PROG_CC_C_O
m4_ifdef([PKG_PROG_PKG_CONFIG],
[PKG_PROG_PKG_CONFIG([0.19])
@@ -160,7 +161,6 @@ if test "$GCC" = "yes"; then
CHECK_BUILD_FLAG([-Wdisabled-optimization])
CHECK_BUILD_FLAG([-Wfloat-equal])
CHECK_BUILD_FLAG([-Wpointer-arith])
- CHECK_CFLAG([-Wdeclaration-after-statement])
CHECK_CFLAG([-Wbad-function-cast])
if test "$CLANG" = "no"; then
CHECK_BUILD_FLAG([-Wcast-align])
@@ -235,6 +235,7 @@ AC_CONFIG_FILES([
plugins/query_expanders/Makefile
plugins/ruby/Makefile
plugins/token_filters/Makefile
+ plugins/sharding/Makefile
examples/Makefile
examples/dictionary/Makefile
examples/dictionary/edict/Makefile
@@ -246,7 +247,6 @@ AC_CONFIG_FILES([
packages/ubuntu/Makefile
packages/rpm/Makefile
packages/rpm/centos/Makefile
- packages/rpm/fedora/Makefile
packages/yum/Makefile
packages/source/Makefile
packages/windows/Makefile
@@ -684,6 +684,10 @@ AC_SUBST(GROONGA_BENCHMARK)
GROONGA_SUGGEST_CREATE_DATASET="${ac_pwd}/src/suggest/groonga-suggest-create-dataset"
AC_SUBST(GROONGA_SUGGEST_CREATE_DATASET)
+# groonga-mruby binary path
+GROONGA_MRUBY="${ac_pwd}/src/groonga-mruby"
+AC_SUBST(GROONGA_MRUBY)
+
# check Cutter with GLib support if available
REQUIRED_MINIMUM_CUTTER_VERSION=1.1.6
REQUIRED_MINIMUM_CPPCUTTER_VERSION=1.2.0
@@ -867,28 +871,64 @@ fi
# zlib
AC_ARG_WITH(zlib,
[AS_HELP_STRING([--with-zlib],
- [use zlib for data compression. [default=no]])],
+ [Support data compression by zlib. [default=auto]])],
[with_zlib="$withval"],
- [with_zlib="no"])
+ [with_zlib="auto"])
GRN_WITH_ZLIB=no
-if test "x$with_zlib" = "xyes"; then
- AC_DEFINE(GRN_WITH_ZLIB, [1], [with zlib])
- AC_SEARCH_LIBS(compress, z, [GRN_WITH_ZLIB=yes],
- [AC_MSG_ERROR("No libz found")])
-else
- AC_SEARCH_LIBS(compress, z, [GRN_WITH_ZLIB=yes], [])
+if test "x$with_zlib" != "xno"; then
+ # TODO: Support custom zlib include and lib directory by --with-zlib.
+ AC_SEARCH_LIBS(compress, z,
+ [
+ GRN_WITH_ZLIB=yes
+ AC_DEFINE(GRN_WITH_ZLIB, [1],
+ [Support data compression by zlib.])
+ ],
+ [
+ if test "x$with_zlib" != "xauto"; then
+ AC_MSG_ERROR("No libz found")
+ fi
+ ])
fi
AC_SUBST(GRN_WITH_ZLIB)
-# LZO
-AC_ARG_WITH(lzo,
- [AS_HELP_STRING([--with-lzo],
- [use LZO for data compression. [default=no]])],
- [with_lzo="$withval"],
- [with_lzo="no"])
-if test "x$with_lzo" = "xyes"; then
- AC_DEFINE(GRN_WITH_LZO, [1], [with lzo])
- AC_SEARCH_LIBS(lzo1_compress, lzo2, [], [AC_MSG_ERROR("No liblzo2 found")])
+# LZ4
+AC_ARG_WITH(lz4,
+ [AS_HELP_STRING([--with-lz4],
+ [Support data compression by LZ4. [default=auto]])],
+ [with_lz4="$withval"],
+ [with_lz4="auto"])
+if test "x$with_lz4" != "xno"; then
+ m4_ifdef([PKG_CHECK_MODULES], [
+ PKG_CHECK_MODULES([LIBLZ4],
+ [liblz4],
+ [GRN_WITH_LZ4=yes],
+ [GRN_WITH_LZ4=no])
+ ],
+ [GRN_WITH_LZ4=no])
+ if test "$GRN_WITH_LZ4" = "yes"; then
+ AC_DEFINE(GRN_WITH_LZ4, [1],
+ [Support data compression by LZ4.])
+ else
+ if test "x$with_lz4" != "xauto"; then
+ AC_MSG_ERROR("No liblz4 found")
+ fi
+ fi
+fi
+
+# jemalloc
+AC_ARG_WITH(jemalloc,
+ [AS_HELP_STRING([--with-jemalloc],
+ [Use jemalloc for memory allocation. [default=no]])],
+ [with_jemalloc="$withval"],
+ [with_jemalloc="no"])
+jemalloc_available="no"
+if test "x$with_jemalloc" != "xno"; then
+ if test "x$with_jemalloc" != "xyes"; then
+ LDFLAGS="-L$with_jemalloc $LDFLAGS"
+ fi
+ AC_SEARCH_LIBS(malloc_conf, jemalloc,
+ [jemalloc_available="yes"],
+ [AC_MSG_ERROR("No libjemalloc found")])
fi
# MeCab
@@ -973,6 +1013,63 @@ if test "x$with_kytea" = "xyes"; then
fi
AM_CONDITIONAL(WITH_KYTEA, test "x$with_kytea" = "xyes")
+# libstemmer
+AC_ARG_WITH(libstemmer,
+ [AS_HELP_STRING([--with-libstemmer],
+ [use libstemmer for stemming. [default=auto]])],
+ [with_libstemmer="$withval"],
+ [with_libstemmer="auto"])
+AC_ARG_WITH(libstemmer-include,
+ [AS_HELP_STRING([--with-libstemmer-include],
+ [path to libstemmer.h. [default=auto]])])
+AC_ARG_WITH(libstemmer-lib,
+ [AS_HELP_STRING([--with-libstemmer-lib],
+ [path to libstemmer.so. [default=auto]])])
+AC_MSG_CHECKING([whether enable libstemmer])
+AC_MSG_RESULT($with_libstemmer)
+if test "x$with_libstemmer" != "xno"; then
+ LIBSTEMMER_CFLAGS=""
+ LIBSTEMMER_LDFLAGS=""
+ LIBSTEMMER_LIBS=""
+
+ CFLAGS_save="${CFLAGS}"
+ LDFLAGS_save="${LDFLAGS}"
+ if test "x$with_libstemmer" != "xauto"; then
+ if test -z "${with_libstemmer_include}"; then
+ with_libstemmer_include="${with_libstemmer}/include"
+ fi
+ LIBSTEMMER_CFLAGS="-I${with_libstemmer_include}"
+ if test -z "${with_libstemmer_lib}"; then
+ with_libstemmer_lib="${with_libstemmer}/lib"
+ fi
+ LIBSTEMMER_LDFLAGS="-L${with_libstemmer_lib}"
+ CFLAGS="${CFLAGS} ${LIBSTEMMER_CFLAGS}"
+ LDFLAGS="${LDFLAGS} ${LIBSTEMMER_LDFLAGS}"
+ fi
+ AC_CHECK_HEADERS(libstemmer.h,
+ [libstemmer_exists=yes],
+ [libstemmer_exists=no])
+ if test "$libstemmer_exists" = "yes"; then
+ AC_CHECK_LIB(stemmer, sb_stemmer_list,
+ [LIBSTEMMER_LIBS="-lstemmer"],
+ [libstemmer_exists=no])
+ fi
+ CFLAGS="${CFLAGS_save}"
+ LDFLAGS="${LDFLAGS_save}"
+
+ if test "$libstemmer_exists" = "no" -a "x$with_libstemmer" != "xauto"; then
+ AC_MSG_ERROR("No libstemmer found at ${with_libstemmer_include} and ${with_libstemmer_lib}.")
+ fi
+ with_libstemmer="$libstemmer_exists"
+fi
+if test "x$with_libstemmer" = "xyes"; then
+ AC_SUBST(LIBSTEMMER_CFLAGS)
+ AC_SUBST(LIBSTEMMER_LDFLAGS)
+ AC_SUBST(LIBSTEMMER_LIBS)
+ AC_DEFINE(GRN_WITH_LIBSTEMMER, [1], [use libstemmer])
+fi
+AM_CONDITIONAL(WITH_LIBSTEMMER, test "x$with_libstemmer" = "xyes")
+
# futex check
AC_ARG_ENABLE(futex,
[AS_HELP_STRING([--enable-futex],
@@ -1136,15 +1233,15 @@ Install it and try again.
How to install sphinx-build:
For Debian GNU/Linux based system like Ubuntu:
- % sudo apt-get install -y python-pip
- % sudo pip install sphinx
+ % sudo apt-get install -y python-sphinx
For Red Hat based system like CentOS:
% sudo yum install -y python-pip
% sudo pip install sphinx
For OS X with Homebrew:
- % brew install pip
+ % brew install python
+ % brew install gettext
% export PATH="`brew --prefix gettext`/bin:\$PATH"
% pip install sphinx])
fi
@@ -1247,6 +1344,9 @@ AC_SUBST(ruby_pluginsdir)
token_filter_pluginsdir="\${pluginsdir}/token_filters"
AC_SUBST(token_filter_pluginsdir)
+sharding_pluginsdir="\${pluginsdir}/sharding"
+AC_SUBST(sharding_pluginsdir)
+
AC_MSG_CHECKING(for the suffix of plugin shared libraries)
shrext_cmds=$(./libtool --config | grep '^shrext_cmds=')
eval $shrext_cmds
@@ -1361,15 +1461,10 @@ if test "$enable_mruby" = "yes"; then
fi
AC_DEFINE(GRN_WITH_MRUBY, [1], [Define to 1 if mruby is enabled.])
MRUBY_CFLAGS="-I\$(top_srcdir)/vendor/mruby-source/include"
- MRUBY_LIBS="\$(top_builddir)/vendor/mruby/libmruby.la"
- MRUBY_LIBS="${MRUBY_LIBS} \$(top_builddir)/vendor/onigmo-source/libonig.la"
- AC_CONFIG_SUBDIRS([vendor/onigmo])
else
- MRUBY_CFLAGS=
- MRUBY_LIBS=
+ MRUBY_CFLAGS=""
fi
AC_SUBST(MRUBY_CFLAGS)
-AC_SUBST(MRUBY_LIBS)
AM_CONDITIONAL(WITH_MRUBY, test "$enable_mruby" = "yes")
# This option is used in vendor/onigmo/configure
@@ -1380,12 +1475,20 @@ AC_ARG_ENABLE(shared-onigmo,
[enable_shared_onigmo="no"])
AM_CONDITIONAL(WITH_SHARED_ONIGMO, test "$enable_shared_onigmo" = "yes")
+AC_DEFINE(GRN_WITH_ONIGMO, [1], [Use Onigmo.])
+AC_CONFIG_SUBDIRS([vendor/onigmo])
+
+ONIGMO_CFLAGS="-I\$(top_srcdir)/vendor/onigmo-source"
+ONIGMO_LIBS="\$(top_builddir)/vendor/onigmo-source/libonig.la"
+AC_SUBST(ONIGMO_CFLAGS)
+AC_SUBST(ONIGMO_LIBS)
+
# PCRE
GRN_WITH_PCRE=no
AC_ARG_WITH(pcre,
[AS_HELP_STRING([--without-pcre],
- [use PCRE for groonga-httpd. [default=auto-detect]])],
- [with_pcre="$witheval"],
+ [Don't use PCRE for groonga-httpd. [default=auto-detect]])],
+ [with_pcre="$withval"],
[with_pcre="auto"])
if test "x$with_pcre" != "xno"; then
m4_ifdef([PKG_CHECK_MODULES], [
@@ -1446,7 +1549,6 @@ AC_SUBST(GROONGA_HTTPD_DEFAULT_DATABASE_PATH)
AC_OUTPUT([
packages/rpm/centos/groonga.spec
- packages/rpm/fedora/groonga.spec
packages/apt/debian/groonga-keyring.postrm
packages/apt/env.sh
packages/yum/env.sh
@@ -1489,6 +1591,14 @@ if test "x$with_kytea" = "xyes"; then
fi
echo
+echo "Token filters:"
+echo " libstemmer: $with_libstemmer"
+if test "x$with_libstemmer" = "xyes"; then
+ echo " CFLAGS: $LIBSTEMMER_CFLAGS"
+ echo " LIBS: $LIBSTEMMER_LIBS"
+fi
+echo
+
echo "Libraries:"
echo " ZeroMQ: $zeromq_available"
if test "x$zeromq_available" = "xyes"; then
@@ -1506,6 +1616,7 @@ if test "x$message_pack_available" = "xyes"; then
echo " LIBS: ${MESSAGE_PACK_LIBS}"
fi
echo " mruby: $enable_mruby"
+echo " jemalloc: $jemalloc_available"
echo
echo "groonga-httpd:"
diff --git a/storage/mroonga/vendor/groonga/examples/Makefile.am b/storage/mroonga/vendor/groonga/examples/Makefile.am
new file mode 100644
index 00000000000..f436342d053
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = dictionary
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/Makefile.am b/storage/mroonga/vendor/groonga/examples/dictionary/Makefile.am
new file mode 100644
index 00000000000..ee618a213bd
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/Makefile.am
@@ -0,0 +1,34 @@
+SUBDIRS = \
+ edict \
+ eijiro \
+ gene95 \
+ jmdict
+
+dist_examples_dictionary_SCRIPTS = \
+ init-db.sh
+
+nobase_dist_examples_dictionary_DATA = \
+ readme.txt \
+ $(html_files)
+
+# find html -type f | sort | sed -e 's,^,\t,g'
+html_files = \
+ html/css/dictionary.css \
+ html/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png \
+ html/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png \
+ html/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png \
+ html/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png \
+ html/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png \
+ html/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png \
+ html/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png \
+ html/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png \
+ html/css/smoothness/images/ui-icons_222222_256x240.png \
+ html/css/smoothness/images/ui-icons_2e83ff_256x240.png \
+ html/css/smoothness/images/ui-icons_454545_256x240.png \
+ html/css/smoothness/images/ui-icons_888888_256x240.png \
+ html/css/smoothness/images/ui-icons_cd0a0a_256x240.png \
+ html/css/smoothness/jquery-ui-1.8.12.custom.css \
+ html/index.html \
+ html/js/dictionary.js \
+ html/js/jquery-1.7.2.js \
+ html/js/jquery-ui-1.8.18.custom.js
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/edict/Makefile.am b/storage/mroonga/vendor/groonga/examples/dictionary/edict/Makefile.am
new file mode 100644
index 00000000000..376f9d520ab
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/edict/Makefile.am
@@ -0,0 +1,4 @@
+edictdir = $(examples_dictionarydir)/edict
+dist_edict_SCRIPTS = \
+ edict2grn.rb \
+ edict-import.sh
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/edict/edict-import.sh b/storage/mroonga/vendor/groonga/examples/dictionary/edict/edict-import.sh
new file mode 100755
index 00000000000..b98397be05a
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/edict/edict-import.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+base_dir=$(dirname $0)
+
+if [ 1 != $# -a 2 != $# ]; then
+ echo "usage: $0 db_path [edict.gz_path]"
+ exit 1
+fi
+
+if [ -z $2 ]; then
+ edict_gz=edict.gz
+ if [ ! -f $edict_gz ]; then
+ wget -O $edict_gz http://ftp.monash.edu.au/pub/nihongo/edict.gz
+ fi
+else
+ edict_gz=$2
+fi
+
+if zcat $edict_gz | ${base_dir}/edict2grn.rb | groonga $1 > /dev/null; then
+ echo "edict data loaded."
+fi
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/edict/edict2grn.rb b/storage/mroonga/vendor/groonga/examples/dictionary/edict/edict2grn.rb
new file mode 100755
index 00000000000..664b12c2148
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/edict/edict2grn.rb
@@ -0,0 +1,56 @@
+#!/usr/bin/env ruby
+# -*- coding: utf-8 -*-
+
+$KCODE = 'u'
+
+require 'English'
+require 'kconv'
+
+class String
+ def to_json
+ a = split(//).map {|char|
+ case char
+ when '"' then '\\"'
+ when '\\' then '\\\\'
+ when "\b" then '\b'
+ when "\f" then '\f'
+ when "\n" then '\n'
+ when "\r" then ''
+ when "\t" then '\t'
+ else char
+ end
+ }
+ "\"#{a.join('')}\""
+ end
+end
+
+class Array
+ def to_json
+ '[' + map {|element|
+ element.to_json
+ }.join(',') + ']'
+ end
+end
+
+puts <<END
+column_create item_dictionary edict_desc COLUMN_SCALAR ShortText
+column_create bigram item_dictionary_edict_desc COLUMN_INDEX|WITH_POSITION item_dictionary edict_desc
+load --table item_dictionary
+[["_key","edict_desc","kana"],
+END
+
+while !STDIN.eof?
+ line = Kconv.toutf8(gets)
+ key, body = line.strip.split('/', 2)
+ key = key.strip
+ if /\s*\[(.+)\]\z/ =~ key
+ key = $PREMATCH
+ reading = $1
+ body = "[#{reading}] #{body}"
+ kana = NKF.nkf("-Ww --katakana", reading)
+ else
+ kana = NKF.nkf("-Ww --katakana", key)
+ end
+ puts [key, body, kana].to_json
+end
+puts ']'
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/eijiro/Makefile.am b/storage/mroonga/vendor/groonga/examples/dictionary/eijiro/Makefile.am
new file mode 100644
index 00000000000..4059a529cef
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/eijiro/Makefile.am
@@ -0,0 +1,4 @@
+eijirodir = $(examples_dictionarydir)/eijiro
+dist_eijiro_SCRIPTS = \
+ eijiro2grn.rb \
+ eijiro-import.sh
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/eijiro/eijiro-import.sh b/storage/mroonga/vendor/groonga/examples/dictionary/eijiro/eijiro-import.sh
new file mode 100755
index 00000000000..4042d7fbf56
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/eijiro/eijiro-import.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+base_dir=$(dirname $0)
+
+if [ 2 != $# ]; then
+ echo "usage: $0 db_path eijiro.csv_path"
+ exit 1
+fi
+
+if iconv -f UCS2 -t UTF8 $2 | ${base_dir}/eijiro2grn.rb | groonga $1 > /dev/null; then
+ echo "eijiro data loaded."
+fi
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/eijiro/eijiro2grn.rb b/storage/mroonga/vendor/groonga/examples/dictionary/eijiro/eijiro2grn.rb
new file mode 100755
index 00000000000..62c1e1309bf
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/eijiro/eijiro2grn.rb
@@ -0,0 +1,61 @@
+#!/usr/bin/env ruby
+# -*- coding: utf-8 -*-
+
+$KCODE = 'u'
+
+require 'rubygems'
+require 'fastercsv'
+
+class String
+ def to_json
+ a = split(//).map {|char|
+ case char
+ when '"' then '\\"'
+ when '\\' then '\\\\'
+ when "\b" then '\b'
+ when "\f" then '\f'
+ when "\n" then '\n'
+ when "\r" then ''
+ when "\t" then '\t'
+ else char
+ end
+ }
+ "\"#{a.join('')}\""
+ end
+end
+
+class Array
+ def to_json
+ '[' + map {|element|
+ element.to_json
+ }.join(',') + ']'
+ end
+end
+
+puts <<END
+column_create item_dictionary eijiro_trans COLUMN_SCALAR ShortText
+column_create item_dictionary eijiro_exp COLUMN_SCALAR ShortText
+column_create item_dictionary eijiro_level COLUMN_SCALAR Int32
+column_create item_dictionary eijiro_memory COLUMN_SCALAR Int32
+column_create item_dictionary eijiro_modify COLUMN_SCALAR Int32
+column_create item_dictionary eijiro_pron COLUMN_SCALAR ShortText
+column_create item_dictionary eijiro_filelink COLUMN_SCALAR ShortText
+column_create bigram item_dictionary_eijiro_trans COLUMN_INDEX|WITH_POSITION item_dictionary eijiro_trans
+load --table item_dictionary
+[["_key","norm","eijiro_trans","eijiro_exp","eijiro_level","eijiro_memory","eijiro_modify","eijiro_pron","eijiro_filelink","kana"],
+END
+
+n = 0
+FasterCSV.new(ARGF, :row_sep => "\r\n").each {|l|
+ if n > 0
+ keyword,word,trans,exp,level,memory,modify,pron,filelink = l
+ kana = ''
+ if trans =~ /ã€ï¼ ã€‘(.*?)(ã€|$)/
+ kana = $1.split("ã€")
+ end
+ puts [word,keyword,trans,exp,level,memory,modify,pron,filelink,kana].map{|e| e || ''}.to_json
+ end
+ n += 1
+}
+
+puts "]"
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/gene95/Makefile.am b/storage/mroonga/vendor/groonga/examples/dictionary/gene95/Makefile.am
new file mode 100644
index 00000000000..e89f13f595c
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/gene95/Makefile.am
@@ -0,0 +1,4 @@
+gene95dir = $(examples_dictionarydir)/gene95
+dist_gene95_SCRIPTS = \
+ gene2grn.rb \
+ gene-import.sh
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/gene95/gene-import.sh b/storage/mroonga/vendor/groonga/examples/dictionary/gene95/gene-import.sh
new file mode 100755
index 00000000000..488d6c83adc
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/gene95/gene-import.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+base_dir=$(dirname $0)
+
+if [ 1 != $# -a 2 != $# ]; then
+ echo "usage: $0 db_path [gene.txt_path]"
+ exit 1
+fi
+
+if [ -z $2 ]; then
+ dictionary_dir=gene95-dictionary
+ gene_txt=${dictionary_dir}/gene.txt
+ if [ ! -f $gene_txt ]; then
+ gene95_tar_gz=gene95.tar.gz
+ wget -O $gene95_tar_gz \
+ http://www.namazu.org/~tsuchiya/sdic/data/gene95.tar.gz
+ mkdir -p ${dictionary_dir}
+ tar xvzf ${gene95_tar_gz} -C ${dictionary_dir}
+ fi
+else
+ gene_txt=$2
+fi
+
+if cat $gene_txt | ${base_dir}/gene2grn.rb | groonga $1 > /dev/null; then
+ echo "gene95 data loaded."
+fi
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/gene95/gene2grn.rb b/storage/mroonga/vendor/groonga/examples/dictionary/gene95/gene2grn.rb
new file mode 100755
index 00000000000..0d10cfd1085
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/gene95/gene2grn.rb
@@ -0,0 +1,46 @@
+#!/usr/bin/env ruby
+# -*- coding: utf-8 -*-
+
+$KCODE = 'u'
+
+require 'kconv'
+
+class String
+ def to_json
+ a = split(//).map {|char|
+ case char
+ when '"' then '\\"'
+ when '\\' then '\\\\'
+ when "\b" then '\b'
+ when "\f" then '\f'
+ when "\n" then '\n'
+ when "\r" then ''
+ when "\t" then '\t'
+ else char
+ end
+ }
+ "\"#{a.join('')}\""
+ end
+end
+
+class Array
+ def to_json
+ '[' + map {|element|
+ element.to_json
+ }.join(',') + ']'
+ end
+end
+
+puts <<END
+column_create item_dictionary gene95_desc COLUMN_SCALAR ShortText
+column_create bigram item_dictionary_gene95_desc COLUMN_INDEX|WITH_POSITION item_dictionary gene95_desc
+load --table item_dictionary
+[["_key","gene95_desc"],
+END
+
+while !STDIN.eof?
+ key = Kconv.toutf8(gets.strip)
+ body = Kconv.toutf8(gets.strip)
+ puts [key, body].to_json
+end
+puts ']'
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/dictionary.css b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/dictionary.css
new file mode 100644
index 00000000000..72b5a6749b3
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/dictionary.css
@@ -0,0 +1,3 @@
+#result {
+ margin-top: 7em;
+}
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png
new file mode 100644
index 00000000000..5b5dab2ab7b
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png
Binary files differ
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png
new file mode 100644
index 00000000000..ac8b229af95
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png
Binary files differ
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
new file mode 100644
index 00000000000..ad3d6346e00
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
Binary files differ
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png
new file mode 100644
index 00000000000..42ccba269b6
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png
Binary files differ
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png
new file mode 100644
index 00000000000..5a46b47cb16
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png
Binary files differ
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
new file mode 100644
index 00000000000..86c2baa655e
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
Binary files differ
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
new file mode 100644
index 00000000000..4443fdc1a15
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
Binary files differ
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
new file mode 100644
index 00000000000..7c9fa6c6edc
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
Binary files differ
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_222222_256x240.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_222222_256x240.png
new file mode 100644
index 00000000000..b273ff111d2
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_222222_256x240.png
Binary files differ
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_2e83ff_256x240.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_2e83ff_256x240.png
new file mode 100644
index 00000000000..09d1cdc856c
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_2e83ff_256x240.png
Binary files differ
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_454545_256x240.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_454545_256x240.png
new file mode 100644
index 00000000000..59bd45b907c
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_454545_256x240.png
Binary files differ
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_888888_256x240.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_888888_256x240.png
new file mode 100644
index 00000000000..6d02426c114
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_888888_256x240.png
Binary files differ
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_cd0a0a_256x240.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_cd0a0a_256x240.png
new file mode 100644
index 00000000000..2ab019b73ec
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_cd0a0a_256x240.png
Binary files differ
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/jquery-ui-1.8.12.custom.css b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/jquery-ui-1.8.12.custom.css
new file mode 100644
index 00000000000..c85aabaec06
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/jquery-ui-1.8.12.custom.css
@@ -0,0 +1,578 @@
+/*
+ * jQuery UI CSS Framework 1.8.12
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Theming/API
+ */
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden { display: none; }
+.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
+.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
+.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
+.ui-helper-clearfix { display: inline-block; }
+/* required comment for clearfix to work in Opera \*/
+* html .ui-helper-clearfix { height:1%; }
+.ui-helper-clearfix { display:block; }
+/* end clearfix */
+.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled { cursor: default !important; }
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
+
+
+/*
+ * jQuery UI CSS Framework 1.8.12
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Theming/API
+ *
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
+ */
+
+
+/* Component containers
+----------------------------------*/
+.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; }
+.ui-widget .ui-widget { font-size: 1em; }
+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
+.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }
+.ui-widget-content a { color: #222222; }
+.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
+.ui-widget-header a { color: #222222; }
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; }
+.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; }
+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
+.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; }
+.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
+.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; }
+.ui-widget :active { outline: none; }
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
+.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
+.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
+.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
+.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
+.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
+.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); }
+.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
+.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
+.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
+.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
+
+/* positioning */
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-off { background-position: -96px -144px; }
+.ui-icon-radio-on { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-start { background-position: -80px -160px; }
+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; }
+.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; }
+.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
+.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
+.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; }
+.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
+.ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
+.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
+.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; }
+
+/* Overlays */
+.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
+.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*
+ * jQuery UI Resizable 1.8.12
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Resizable#theming
+ */
+.ui-resizable { position: relative;}
+.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;
+ /* http://bugs.jqueryui.com/ticket/7233
+ - Resizable: resizable handles fail to work in IE if transparent and content overlaps
+ */
+ background-image:url(data:);
+}
+.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
+.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
+.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
+.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
+.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
+.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*
+ * jQuery UI Selectable 1.8.12
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Selectable#theming
+ */
+.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
+/*
+ * jQuery UI Accordion 1.8.12
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Accordion#theming
+ */
+/* IE/Win - Fix animation bug - #4615 */
+.ui-accordion { width: 100%; }
+.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
+.ui-accordion .ui-accordion-li-fix { display: inline; }
+.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
+.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
+.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
+.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
+.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
+.ui-accordion .ui-accordion-content-active { display: block; }
+/*
+ * jQuery UI Autocomplete 1.8.12
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Autocomplete#theming
+ */
+.ui-autocomplete { position: absolute; cursor: default; }
+
+/* workarounds */
+* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
+
+/*
+ * jQuery UI Menu 1.8.12
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Menu#theming
+ */
+.ui-menu {
+ list-style:none;
+ padding: 2px;
+ margin: 0;
+ display:block;
+ float: left;
+}
+.ui-menu .ui-menu {
+ margin-top: -3px;
+}
+.ui-menu .ui-menu-item {
+ margin:0;
+ padding: 0;
+ zoom: 1;
+ float: left;
+ clear: left;
+ width: 100%;
+}
+.ui-menu .ui-menu-item a {
+ text-decoration:none;
+ display:block;
+ padding:.2em .4em;
+ line-height:1.5;
+ zoom:1;
+}
+.ui-menu .ui-menu-item a.ui-state-hover,
+.ui-menu .ui-menu-item a.ui-state-active {
+ font-weight: normal;
+ margin: -1px;
+}
+/*
+ * jQuery UI Button 1.8.12
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Button#theming
+ */
+.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
+.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
+button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
+.ui-button-icons-only { width: 3.4em; }
+button.ui-button-icons-only { width: 3.7em; }
+
+/*button text element */
+.ui-button .ui-button-text { display: block; line-height: 1.4; }
+.ui-button-text-only .ui-button-text { padding: .4em 1em; }
+.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
+.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
+.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
+.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
+/* no icon support for input elements, provide padding by default */
+input.ui-button { padding: .4em 1em; }
+
+/*button icon element(s) */
+.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
+.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
+.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
+.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
+.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
+
+/*button sets*/
+.ui-buttonset { margin-right: 7px; }
+.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
+
+/* workarounds */
+button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
+/*
+ * jQuery UI Dialog 1.8.12
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Dialog#theming
+ */
+.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
+.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
+.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
+.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
+.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
+.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
+.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
+.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
+.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
+.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
+.ui-draggable .ui-dialog-titlebar { cursor: move; }
+/*
+ * jQuery UI Slider 1.8.12
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Slider#theming
+ */
+.ui-slider { position: relative; text-align: left; }
+.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
+.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
+
+.ui-slider-horizontal { height: .8em; }
+.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
+.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
+.ui-slider-horizontal .ui-slider-range-min { left: 0; }
+.ui-slider-horizontal .ui-slider-range-max { right: 0; }
+
+.ui-slider-vertical { width: .8em; height: 100px; }
+.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
+.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
+.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
+.ui-slider-vertical .ui-slider-range-max { top: 0; }/*
+ * jQuery UI Tabs 1.8.12
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Tabs#theming
+ */
+.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
+.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
+.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
+.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
+.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
+.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
+.ui-tabs .ui-tabs-hide { display: none !important; }
+/*
+ * jQuery UI Datepicker 1.8.12
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Datepicker#theming
+ */
+.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
+.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
+.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
+.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
+.ui-datepicker .ui-datepicker-prev { left:2px; }
+.ui-datepicker .ui-datepicker-next { right:2px; }
+.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
+.ui-datepicker .ui-datepicker-next-hover { right:1px; }
+.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
+.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
+.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
+.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
+.ui-datepicker select.ui-datepicker-month,
+.ui-datepicker select.ui-datepicker-year { width: 49%;}
+.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
+.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
+.ui-datepicker td { border: 0; padding: 1px; }
+.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
+.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
+.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi { width:auto; }
+.ui-datepicker-multi .ui-datepicker-group { float:left; }
+.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
+.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
+.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
+.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
+.ui-datepicker-row-break { clear:both; width:100%; }
+
+/* RTL support */
+.ui-datepicker-rtl { direction: rtl; }
+.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+
+/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
+.ui-datepicker-cover {
+ display: none; /*sorry for IE5*/
+ display/**/: block; /*sorry for IE5*/
+ position: absolute; /*must have*/
+ z-index: -1; /*must have*/
+ filter: mask(); /*must have*/
+ top: -4px; /*must have*/
+ left: -4px; /*must have*/
+ width: 200px; /*must have*/
+ height: 200px; /*must have*/
+}/*
+ * jQuery UI Progressbar 1.8.12
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Progressbar#theming
+ */
+.ui-progressbar { height:2em; text-align: left; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; } \ No newline at end of file
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/index.html b/storage/mroonga/vendor/groonga/examples/dictionary/html/index.html
new file mode 100644
index 00000000000..aaad128a290
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/index.html
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
+<head>
+<meta http-equiv="Content-Language" content="ja" />
+<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+<title>groonga dictionary search</title>
+<meta http-equiv="content-style-type" content="text/css" />
+<meta http-equiv="content-script-type" content="text/javascript" />
+<link type="text/css" href="css/smoothness/jquery-ui-1.8.12.custom.css" rel="stylesheet" />
+<link type="text/css" rel="stylesheet" href="css/dictionary.css" />
+</head>
+<body>
+<form action="javascript:(function(){$('.search').blur()})()" name="search" id="search">
+<input type="text" size="60" maxlength="60" name="key" class="search" />
+<input type="submit" value="検索"/>
+</form>
+<script type="text/javascript" src="js/jquery-1.7.2.js"></script>
+<script type="text/javascript" src="js/jquery-ui-1.8.18.custom.min.js"></script>
+<script type="text/javascript" src="js/dictionary.js"></script>
+<script type="text/javascript">
+$(document).ready(function(){
+ $(".search").autocomplete({source: dictionarySource("http://" + location.host + "/d/suggest")});
+});
+</script>
+<div id="result"></div>
+</body>
+</html>
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/js/dictionary.js b/storage/mroonga/vendor/groonga/examples/dictionary/html/js/dictionary.js
new file mode 100644
index 00000000000..850c64cc667
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/js/dictionary.js
@@ -0,0 +1,82 @@
+function dictionarySource(url) {
+ function displayItems(items) {
+ var results = $("<dl />");
+ $.each(items,
+ function(i, val) {
+ results.append($("<dt />")
+ .append($("<span />")
+ .text(val[0])
+ .click(function() {
+ $(".search").val($(this).text());
+ $("#search").submit();
+ })));
+ results.append($("<dd />")
+ .append($("<span />").text(val[1]))
+ .append($("<span />").text(val[2]))
+ );
+ });
+ $("#result")
+ .empty()
+ .append(results);
+ };
+
+ var request_index = 0;
+ var columns = "_key,gene95_desc,edict_desc";
+ var xhr;
+ function source(request, response) {
+ function onSuccess(data, status) {
+ if (this.autocomplete_request != request_index) {
+ return;
+ }
+ var completions = data[1]["complete"];
+ var items = [];
+ if (completions && completions.length > 2) {
+ completions.shift();
+ completions.shift();
+ $.each(completions,
+ function(i, item) {
+ var key = item[0];
+ items.push(key);
+ if (items.length >= 3) {
+ return false;
+ }
+ return true;
+ });
+ }
+ if (completions.length > 0) {
+ displayItems(completions);
+ }
+ response(items);
+ }
+
+ function onError() {
+ if (this.autocomplete_request != request_index) {
+ return;
+ }
+ response([]);
+ }
+
+ if (xhr) {
+ xhr.abort();
+ }
+ xhr = $.ajax(url,
+ {
+ data: {
+ query: request.term,
+ types: 'complete',
+ table: 'item_dictionary',
+ column: 'kana',
+ limit: 25,
+ output_columns: columns,
+ frequency_threshold: 1,
+ prefix_search: "yes"
+ },
+ dataType: "jsonp",
+ autocomplete_request: ++request_index,
+ success: onSuccess,
+ error: onError
+ });
+ };
+
+ return source;
+}
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-1.7.2.js b/storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-1.7.2.js
new file mode 100644
index 00000000000..3774ff98613
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-1.7.2.js
@@ -0,0 +1,9404 @@
+/*!
+ * jQuery JavaScript Library v1.7.2
+ * http://jquery.com/
+ *
+ * Copyright 2011, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2011, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Wed Mar 21 12:46:34 2012 -0700
+ */
+(function( window, undefined ) {
+
+// Use the correct document accordingly with window argument (sandbox)
+var document = window.document,
+ navigator = window.navigator,
+ location = window.location;
+var jQuery = (function() {
+
+// Define a local copy of jQuery
+var jQuery = function( selector, context ) {
+ // The jQuery object is actually just the init constructor 'enhanced'
+ return new jQuery.fn.init( selector, context, rootjQuery );
+ },
+
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
+
+ // Map over the $ in case of overwrite
+ _$ = window.$,
+
+ // A central reference to the root jQuery(document)
+ rootjQuery,
+
+ // A simple way to check for HTML strings or ID strings
+ // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+ quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
+
+ // Check if a string has a non-whitespace character in it
+ rnotwhite = /\S/,
+
+ // Used for trimming whitespace
+ trimLeft = /^\s+/,
+ trimRight = /\s+$/,
+
+ // Match a standalone tag
+ rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
+
+ // JSON RegExp
+ rvalidchars = /^[\],:{}\s]*$/,
+ rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
+ rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
+ rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
+
+ // Useragent RegExp
+ rwebkit = /(webkit)[ \/]([\w.]+)/,
+ ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
+ rmsie = /(msie) ([\w.]+)/,
+ rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
+
+ // Matches dashed string for camelizing
+ rdashAlpha = /-([a-z]|[0-9])/ig,
+ rmsPrefix = /^-ms-/,
+
+ // Used by jQuery.camelCase as callback to replace()
+ fcamelCase = function( all, letter ) {
+ return ( letter + "" ).toUpperCase();
+ },
+
+ // Keep a UserAgent string for use with jQuery.browser
+ userAgent = navigator.userAgent,
+
+ // For matching the engine and version of the browser
+ browserMatch,
+
+ // The deferred used on DOM ready
+ readyList,
+
+ // The ready event handler
+ DOMContentLoaded,
+
+ // Save a reference to some core methods
+ toString = Object.prototype.toString,
+ hasOwn = Object.prototype.hasOwnProperty,
+ push = Array.prototype.push,
+ slice = Array.prototype.slice,
+ trim = String.prototype.trim,
+ indexOf = Array.prototype.indexOf,
+
+ // [[Class]] -> type pairs
+ class2type = {};
+
+jQuery.fn = jQuery.prototype = {
+ constructor: jQuery,
+ init: function( selector, context, rootjQuery ) {
+ var match, elem, ret, doc;
+
+ // Handle $(""), $(null), or $(undefined)
+ if ( !selector ) {
+ return this;
+ }
+
+ // Handle $(DOMElement)
+ if ( selector.nodeType ) {
+ this.context = this[0] = selector;
+ this.length = 1;
+ return this;
+ }
+
+ // The body element only exists once, optimize finding it
+ if ( selector === "body" && !context && document.body ) {
+ this.context = document;
+ this[0] = document.body;
+ this.selector = selector;
+ this.length = 1;
+ return this;
+ }
+
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ // Are we dealing with HTML string or an ID?
+ if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+ // Assume that strings that start and end with <> are HTML and skip the regex check
+ match = [ null, selector, null ];
+
+ } else {
+ match = quickExpr.exec( selector );
+ }
+
+ // Verify a match, and that no context was specified for #id
+ if ( match && (match[1] || !context) ) {
+
+ // HANDLE: $(html) -> $(array)
+ if ( match[1] ) {
+ context = context instanceof jQuery ? context[0] : context;
+ doc = ( context ? context.ownerDocument || context : document );
+
+ // If a single string is passed in and it's a single tag
+ // just do a createElement and skip the rest
+ ret = rsingleTag.exec( selector );
+
+ if ( ret ) {
+ if ( jQuery.isPlainObject( context ) ) {
+ selector = [ document.createElement( ret[1] ) ];
+ jQuery.fn.attr.call( selector, context, true );
+
+ } else {
+ selector = [ doc.createElement( ret[1] ) ];
+ }
+
+ } else {
+ ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
+ selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
+ }
+
+ return jQuery.merge( this, selector );
+
+ // HANDLE: $("#id")
+ } else {
+ elem = document.getElementById( match[2] );
+
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( elem.id !== match[2] ) {
+ return rootjQuery.find( selector );
+ }
+
+ // Otherwise, we inject the element directly into the jQuery object
+ this.length = 1;
+ this[0] = elem;
+ }
+
+ this.context = document;
+ this.selector = selector;
+ return this;
+ }
+
+ // HANDLE: $(expr, $(...))
+ } else if ( !context || context.jquery ) {
+ return ( context || rootjQuery ).find( selector );
+
+ // HANDLE: $(expr, context)
+ // (which is just equivalent to: $(context).find(expr)
+ } else {
+ return this.constructor( context ).find( selector );
+ }
+
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction( selector ) ) {
+ return rootjQuery.ready( selector );
+ }
+
+ if ( selector.selector !== undefined ) {
+ this.selector = selector.selector;
+ this.context = selector.context;
+ }
+
+ return jQuery.makeArray( selector, this );
+ },
+
+ // Start with an empty selector
+ selector: "",
+
+ // The current version of jQuery being used
+ jquery: "1.7.2",
+
+ // The default length of a jQuery object is 0
+ length: 0,
+
+ // The number of elements contained in the matched element set
+ size: function() {
+ return this.length;
+ },
+
+ toArray: function() {
+ return slice.call( this, 0 );
+ },
+
+ // Get the Nth element in the matched element set OR
+ // Get the whole matched element set as a clean array
+ get: function( num ) {
+ return num == null ?
+
+ // Return a 'clean' array
+ this.toArray() :
+
+ // Return just the object
+ ( num < 0 ? this[ this.length + num ] : this[ num ] );
+ },
+
+ // Take an array of elements and push it onto the stack
+ // (returning the new matched element set)
+ pushStack: function( elems, name, selector ) {
+ // Build a new jQuery matched element set
+ var ret = this.constructor();
+
+ if ( jQuery.isArray( elems ) ) {
+ push.apply( ret, elems );
+
+ } else {
+ jQuery.merge( ret, elems );
+ }
+
+ // Add the old object onto the stack (as a reference)
+ ret.prevObject = this;
+
+ ret.context = this.context;
+
+ if ( name === "find" ) {
+ ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
+ } else if ( name ) {
+ ret.selector = this.selector + "." + name + "(" + selector + ")";
+ }
+
+ // Return the newly-formed element set
+ return ret;
+ },
+
+ // Execute a callback for every element in the matched set.
+ // (You can seed the arguments with an array of args, but this is
+ // only used internally.)
+ each: function( callback, args ) {
+ return jQuery.each( this, callback, args );
+ },
+
+ ready: function( fn ) {
+ // Attach the listeners
+ jQuery.bindReady();
+
+ // Add the callback
+ readyList.add( fn );
+
+ return this;
+ },
+
+ eq: function( i ) {
+ i = +i;
+ return i === -1 ?
+ this.slice( i ) :
+ this.slice( i, i + 1 );
+ },
+
+ first: function() {
+ return this.eq( 0 );
+ },
+
+ last: function() {
+ return this.eq( -1 );
+ },
+
+ slice: function() {
+ return this.pushStack( slice.apply( this, arguments ),
+ "slice", slice.call(arguments).join(",") );
+ },
+
+ map: function( callback ) {
+ return this.pushStack( jQuery.map(this, function( elem, i ) {
+ return callback.call( elem, i, elem );
+ }));
+ },
+
+ end: function() {
+ return this.prevObject || this.constructor(null);
+ },
+
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: push,
+ sort: [].sort,
+ splice: [].splice
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+jQuery.extend = jQuery.fn.extend = function() {
+ var options, name, src, copy, copyIsArray, clone,
+ target = arguments[0] || {},
+ i = 1,
+ length = arguments.length,
+ deep = false;
+
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+ target = arguments[1] || {};
+ // skip the boolean and the target
+ i = 2;
+ }
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+ target = {};
+ }
+
+ // extend jQuery itself if only one argument is passed
+ if ( length === i ) {
+ target = this;
+ --i;
+ }
+
+ for ( ; i < length; i++ ) {
+ // Only deal with non-null/undefined values
+ if ( (options = arguments[ i ]) != null ) {
+ // Extend the base object
+ for ( name in options ) {
+ src = target[ name ];
+ copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy ) {
+ continue;
+ }
+
+ // Recurse if we're merging plain objects or arrays
+ if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+ if ( copyIsArray ) {
+ copyIsArray = false;
+ clone = src && jQuery.isArray(src) ? src : [];
+
+ } else {
+ clone = src && jQuery.isPlainObject(src) ? src : {};
+ }
+
+ // Never move original objects, clone them
+ target[ name ] = jQuery.extend( deep, clone, copy );
+
+ // Don't bring in undefined values
+ } else if ( copy !== undefined ) {
+ target[ name ] = copy;
+ }
+ }
+ }
+ }
+
+ // Return the modified object
+ return target;
+};
+
+jQuery.extend({
+ noConflict: function( deep ) {
+ if ( window.$ === jQuery ) {
+ window.$ = _$;
+ }
+
+ if ( deep && window.jQuery === jQuery ) {
+ window.jQuery = _jQuery;
+ }
+
+ return jQuery;
+ },
+
+ // Is the DOM ready to be used? Set to true once it occurs.
+ isReady: false,
+
+ // A counter to track how many items to wait for before
+ // the ready event fires. See #6781
+ readyWait: 1,
+
+ // Hold (or release) the ready event
+ holdReady: function( hold ) {
+ if ( hold ) {
+ jQuery.readyWait++;
+ } else {
+ jQuery.ready( true );
+ }
+ },
+
+ // Handle when the DOM is ready
+ ready: function( wait ) {
+ // Either a released hold or an DOMready/load event and not yet ready
+ if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+ if ( !document.body ) {
+ return setTimeout( jQuery.ready, 1 );
+ }
+
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If a normal DOM Ready event fired, decrement, and wait if need be
+ if ( wait !== true && --jQuery.readyWait > 0 ) {
+ return;
+ }
+
+ // If there are functions bound, to execute
+ readyList.fireWith( document, [ jQuery ] );
+
+ // Trigger any bound ready events
+ if ( jQuery.fn.trigger ) {
+ jQuery( document ).trigger( "ready" ).off( "ready" );
+ }
+ }
+ },
+
+ bindReady: function() {
+ if ( readyList ) {
+ return;
+ }
+
+ readyList = jQuery.Callbacks( "once memory" );
+
+ // Catch cases where $(document).ready() is called after the
+ // browser event has already occurred.
+ if ( document.readyState === "complete" ) {
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
+ return setTimeout( jQuery.ready, 1 );
+ }
+
+ // Mozilla, Opera and webkit nightlies currently support this event
+ if ( document.addEventListener ) {
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", jQuery.ready, false );
+
+ // If IE event model is used
+ } else if ( document.attachEvent ) {
+ // ensure firing before onload,
+ // maybe late but safe also for iframes
+ document.attachEvent( "onreadystatechange", DOMContentLoaded );
+
+ // A fallback to window.onload, that will always work
+ window.attachEvent( "onload", jQuery.ready );
+
+ // If IE and not a frame
+ // continually check to see if the document is ready
+ var toplevel = false;
+
+ try {
+ toplevel = window.frameElement == null;
+ } catch(e) {}
+
+ if ( document.documentElement.doScroll && toplevel ) {
+ doScrollCheck();
+ }
+ }
+ },
+
+ // See test/unit/core.js for details concerning isFunction.
+ // Since version 1.3, DOM methods and functions like alert
+ // aren't supported. They return false on IE (#2968).
+ isFunction: function( obj ) {
+ return jQuery.type(obj) === "function";
+ },
+
+ isArray: Array.isArray || function( obj ) {
+ return jQuery.type(obj) === "array";
+ },
+
+ isWindow: function( obj ) {
+ return obj != null && obj == obj.window;
+ },
+
+ isNumeric: function( obj ) {
+ return !isNaN( parseFloat(obj) ) && isFinite( obj );
+ },
+
+ type: function( obj ) {
+ return obj == null ?
+ String( obj ) :
+ class2type[ toString.call(obj) ] || "object";
+ },
+
+ isPlainObject: function( obj ) {
+ // Must be an Object.
+ // Because of IE, we also have to check the presence of the constructor property.
+ // Make sure that DOM nodes and window objects don't pass through, as well
+ if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ try {
+ // Not own constructor property must be Object
+ if ( obj.constructor &&
+ !hasOwn.call(obj, "constructor") &&
+ !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+ return false;
+ }
+ } catch ( e ) {
+ // IE8,9 Will throw exceptions on certain host objects #9897
+ return false;
+ }
+
+ // Own properties are enumerated firstly, so to speed up,
+ // if last one is own, then all properties are own.
+
+ var key;
+ for ( key in obj ) {}
+
+ return key === undefined || hasOwn.call( obj, key );
+ },
+
+ isEmptyObject: function( obj ) {
+ for ( var name in obj ) {
+ return false;
+ }
+ return true;
+ },
+
+ error: function( msg ) {
+ throw new Error( msg );
+ },
+
+ parseJSON: function( data ) {
+ if ( typeof data !== "string" || !data ) {
+ return null;
+ }
+
+ // Make sure leading/trailing whitespace is removed (IE can't handle it)
+ data = jQuery.trim( data );
+
+ // Attempt to parse using the native JSON parser first
+ if ( window.JSON && window.JSON.parse ) {
+ return window.JSON.parse( data );
+ }
+
+ // Make sure the incoming data is actual JSON
+ // Logic borrowed from http://json.org/json2.js
+ if ( rvalidchars.test( data.replace( rvalidescape, "@" )
+ .replace( rvalidtokens, "]" )
+ .replace( rvalidbraces, "")) ) {
+
+ return ( new Function( "return " + data ) )();
+
+ }
+ jQuery.error( "Invalid JSON: " + data );
+ },
+
+ // Cross-browser xml parsing
+ parseXML: function( data ) {
+ if ( typeof data !== "string" || !data ) {
+ return null;
+ }
+ var xml, tmp;
+ try {
+ if ( window.DOMParser ) { // Standard
+ tmp = new DOMParser();
+ xml = tmp.parseFromString( data , "text/xml" );
+ } else { // IE
+ xml = new ActiveXObject( "Microsoft.XMLDOM" );
+ xml.async = "false";
+ xml.loadXML( data );
+ }
+ } catch( e ) {
+ xml = undefined;
+ }
+ if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
+ jQuery.error( "Invalid XML: " + data );
+ }
+ return xml;
+ },
+
+ noop: function() {},
+
+ // Evaluates a script in a global context
+ // Workarounds based on findings by Jim Driscoll
+ // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
+ globalEval: function( data ) {
+ if ( data && rnotwhite.test( data ) ) {
+ // We use execScript on Internet Explorer
+ // We use an anonymous function so that context is window
+ // rather than jQuery in Firefox
+ ( window.execScript || function( data ) {
+ window[ "eval" ].call( window, data );
+ } )( data );
+ }
+ },
+
+ // Convert dashed to camelCase; used by the css and data modules
+ // Microsoft forgot to hump their vendor prefix (#9572)
+ camelCase: function( string ) {
+ return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+ },
+
+ nodeName: function( elem, name ) {
+ return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
+ },
+
+ // args is for internal usage only
+ each: function( object, callback, args ) {
+ var name, i = 0,
+ length = object.length,
+ isObj = length === undefined || jQuery.isFunction( object );
+
+ if ( args ) {
+ if ( isObj ) {
+ for ( name in object ) {
+ if ( callback.apply( object[ name ], args ) === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( ; i < length; ) {
+ if ( callback.apply( object[ i++ ], args ) === false ) {
+ break;
+ }
+ }
+ }
+
+ // A special, fast, case for the most common use of each
+ } else {
+ if ( isObj ) {
+ for ( name in object ) {
+ if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( ; i < length; ) {
+ if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
+ break;
+ }
+ }
+ }
+ }
+
+ return object;
+ },
+
+ // Use native String.trim function wherever possible
+ trim: trim ?
+ function( text ) {
+ return text == null ?
+ "" :
+ trim.call( text );
+ } :
+
+ // Otherwise use our own trimming functionality
+ function( text ) {
+ return text == null ?
+ "" :
+ text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
+ },
+
+ // results is for internal usage only
+ makeArray: function( array, results ) {
+ var ret = results || [];
+
+ if ( array != null ) {
+ // The window, strings (and functions) also have 'length'
+ // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
+ var type = jQuery.type( array );
+
+ if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
+ push.call( ret, array );
+ } else {
+ jQuery.merge( ret, array );
+ }
+ }
+
+ return ret;
+ },
+
+ inArray: function( elem, array, i ) {
+ var len;
+
+ if ( array ) {
+ if ( indexOf ) {
+ return indexOf.call( array, elem, i );
+ }
+
+ len = array.length;
+ i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
+
+ for ( ; i < len; i++ ) {
+ // Skip accessing in sparse arrays
+ if ( i in array && array[ i ] === elem ) {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+ },
+
+ merge: function( first, second ) {
+ var i = first.length,
+ j = 0;
+
+ if ( typeof second.length === "number" ) {
+ for ( var l = second.length; j < l; j++ ) {
+ first[ i++ ] = second[ j ];
+ }
+
+ } else {
+ while ( second[j] !== undefined ) {
+ first[ i++ ] = second[ j++ ];
+ }
+ }
+
+ first.length = i;
+
+ return first;
+ },
+
+ grep: function( elems, callback, inv ) {
+ var ret = [], retVal;
+ inv = !!inv;
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( var i = 0, length = elems.length; i < length; i++ ) {
+ retVal = !!callback( elems[ i ], i );
+ if ( inv !== retVal ) {
+ ret.push( elems[ i ] );
+ }
+ }
+
+ return ret;
+ },
+
+ // arg is for internal usage only
+ map: function( elems, callback, arg ) {
+ var value, key, ret = [],
+ i = 0,
+ length = elems.length,
+ // jquery objects are treated as arrays
+ isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
+
+ // Go through the array, translating each of the items to their
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
+ }
+
+ // Go through every key on the object,
+ } else {
+ for ( key in elems ) {
+ value = callback( elems[ key ], key, arg );
+
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
+ }
+ }
+
+ // Flatten any nested arrays
+ return ret.concat.apply( [], ret );
+ },
+
+ // A global GUID counter for objects
+ guid: 1,
+
+ // Bind a function to a context, optionally partially applying any
+ // arguments.
+ proxy: function( fn, context ) {
+ if ( typeof context === "string" ) {
+ var tmp = fn[ context ];
+ context = fn;
+ fn = tmp;
+ }
+
+ // Quick check to determine if target is callable, in the spec
+ // this throws a TypeError, but we will just return undefined.
+ if ( !jQuery.isFunction( fn ) ) {
+ return undefined;
+ }
+
+ // Simulated bind
+ var args = slice.call( arguments, 2 ),
+ proxy = function() {
+ return fn.apply( context, args.concat( slice.call( arguments ) ) );
+ };
+
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
+
+ return proxy;
+ },
+
+ // Mutifunctional method to get and set values to a collection
+ // The value/s can optionally be executed if it's a function
+ access: function( elems, fn, key, value, chainable, emptyGet, pass ) {
+ var exec,
+ bulk = key == null,
+ i = 0,
+ length = elems.length;
+
+ // Sets many values
+ if ( key && typeof key === "object" ) {
+ for ( i in key ) {
+ jQuery.access( elems, fn, i, key[i], 1, emptyGet, value );
+ }
+ chainable = 1;
+
+ // Sets one value
+ } else if ( value !== undefined ) {
+ // Optionally, function values get executed if exec is true
+ exec = pass === undefined && jQuery.isFunction( value );
+
+ if ( bulk ) {
+ // Bulk operations only iterate when executing function values
+ if ( exec ) {
+ exec = fn;
+ fn = function( elem, key, value ) {
+ return exec.call( jQuery( elem ), value );
+ };
+
+ // Otherwise they run against the entire set
+ } else {
+ fn.call( elems, value );
+ fn = null;
+ }
+ }
+
+ if ( fn ) {
+ for (; i < length; i++ ) {
+ fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
+ }
+ }
+
+ chainable = 1;
+ }
+
+ return chainable ?
+ elems :
+
+ // Gets
+ bulk ?
+ fn.call( elems ) :
+ length ? fn( elems[0], key ) : emptyGet;
+ },
+
+ now: function() {
+ return ( new Date() ).getTime();
+ },
+
+ // Use of jQuery.browser is frowned upon.
+ // More details: http://docs.jquery.com/Utilities/jQuery.browser
+ uaMatch: function( ua ) {
+ ua = ua.toLowerCase();
+
+ var match = rwebkit.exec( ua ) ||
+ ropera.exec( ua ) ||
+ rmsie.exec( ua ) ||
+ ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
+ [];
+
+ return { browser: match[1] || "", version: match[2] || "0" };
+ },
+
+ sub: function() {
+ function jQuerySub( selector, context ) {
+ return new jQuerySub.fn.init( selector, context );
+ }
+ jQuery.extend( true, jQuerySub, this );
+ jQuerySub.superclass = this;
+ jQuerySub.fn = jQuerySub.prototype = this();
+ jQuerySub.fn.constructor = jQuerySub;
+ jQuerySub.sub = this.sub;
+ jQuerySub.fn.init = function init( selector, context ) {
+ if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
+ context = jQuerySub( context );
+ }
+
+ return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
+ };
+ jQuerySub.fn.init.prototype = jQuerySub.fn;
+ var rootjQuerySub = jQuerySub(document);
+ return jQuerySub;
+ },
+
+ browser: {}
+});
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+browserMatch = jQuery.uaMatch( userAgent );
+if ( browserMatch.browser ) {
+ jQuery.browser[ browserMatch.browser ] = true;
+ jQuery.browser.version = browserMatch.version;
+}
+
+// Deprecated, use jQuery.browser.webkit instead
+if ( jQuery.browser.webkit ) {
+ jQuery.browser.safari = true;
+}
+
+// IE doesn't match non-breaking spaces with \s
+if ( rnotwhite.test( "\xA0" ) ) {
+ trimLeft = /^[\s\xA0]+/;
+ trimRight = /[\s\xA0]+$/;
+}
+
+// All jQuery objects should point back to these
+rootjQuery = jQuery(document);
+
+// Cleanup functions for the document ready method
+if ( document.addEventListener ) {
+ DOMContentLoaded = function() {
+ document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+ jQuery.ready();
+ };
+
+} else if ( document.attachEvent ) {
+ DOMContentLoaded = function() {
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+ if ( document.readyState === "complete" ) {
+ document.detachEvent( "onreadystatechange", DOMContentLoaded );
+ jQuery.ready();
+ }
+ };
+}
+
+// The DOM ready check for Internet Explorer
+function doScrollCheck() {
+ if ( jQuery.isReady ) {
+ return;
+ }
+
+ try {
+ // If IE is used, use the trick by Diego Perini
+ // http://javascript.nwbox.com/IEContentLoaded/
+ document.documentElement.doScroll("left");
+ } catch(e) {
+ setTimeout( doScrollCheck, 1 );
+ return;
+ }
+
+ // and execute any waiting functions
+ jQuery.ready();
+}
+
+return jQuery;
+
+})();
+
+
+// String to Object flags format cache
+var flagsCache = {};
+
+// Convert String-formatted flags into Object-formatted ones and store in cache
+function createFlags( flags ) {
+ var object = flagsCache[ flags ] = {},
+ i, length;
+ flags = flags.split( /\s+/ );
+ for ( i = 0, length = flags.length; i < length; i++ ) {
+ object[ flags[i] ] = true;
+ }
+ return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ * flags: an optional list of space-separated flags that will change how
+ * the callback list behaves
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible flags:
+ *
+ * once: will ensure the callback list can only be fired once (like a Deferred)
+ *
+ * memory: will keep track of previous values and will call any callback added
+ * after the list has been fired right away with the latest "memorized"
+ * values (like a Deferred)
+ *
+ * unique: will ensure a callback can only be added once (no duplicate in the list)
+ *
+ * stopOnFalse: interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( flags ) {
+
+ // Convert flags from String-formatted to Object-formatted
+ // (we check in cache first)
+ flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};
+
+ var // Actual callback list
+ list = [],
+ // Stack of fire calls for repeatable lists
+ stack = [],
+ // Last fire value (for non-forgettable lists)
+ memory,
+ // Flag to know if list was already fired
+ fired,
+ // Flag to know if list is currently firing
+ firing,
+ // First callback to fire (used internally by add and fireWith)
+ firingStart,
+ // End of the loop when firing
+ firingLength,
+ // Index of currently firing callback (modified by remove if needed)
+ firingIndex,
+ // Add one or several callbacks to the list
+ add = function( args ) {
+ var i,
+ length,
+ elem,
+ type,
+ actual;
+ for ( i = 0, length = args.length; i < length; i++ ) {
+ elem = args[ i ];
+ type = jQuery.type( elem );
+ if ( type === "array" ) {
+ // Inspect recursively
+ add( elem );
+ } else if ( type === "function" ) {
+ // Add if not in unique mode and callback is not in
+ if ( !flags.unique || !self.has( elem ) ) {
+ list.push( elem );
+ }
+ }
+ }
+ },
+ // Fire callbacks
+ fire = function( context, args ) {
+ args = args || [];
+ memory = !flags.memory || [ context, args ];
+ fired = true;
+ firing = true;
+ firingIndex = firingStart || 0;
+ firingStart = 0;
+ firingLength = list.length;
+ for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+ if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
+ memory = true; // Mark as halted
+ break;
+ }
+ }
+ firing = false;
+ if ( list ) {
+ if ( !flags.once ) {
+ if ( stack && stack.length ) {
+ memory = stack.shift();
+ self.fireWith( memory[ 0 ], memory[ 1 ] );
+ }
+ } else if ( memory === true ) {
+ self.disable();
+ } else {
+ list = [];
+ }
+ }
+ },
+ // Actual Callbacks object
+ self = {
+ // Add a callback or a collection of callbacks to the list
+ add: function() {
+ if ( list ) {
+ var length = list.length;
+ add( arguments );
+ // Do we need to add the callbacks to the
+ // current firing batch?
+ if ( firing ) {
+ firingLength = list.length;
+ // With memory, if we're not firing then
+ // we should call right away, unless previous
+ // firing was halted (stopOnFalse)
+ } else if ( memory && memory !== true ) {
+ firingStart = length;
+ fire( memory[ 0 ], memory[ 1 ] );
+ }
+ }
+ return this;
+ },
+ // Remove a callback from the list
+ remove: function() {
+ if ( list ) {
+ var args = arguments,
+ argIndex = 0,
+ argLength = args.length;
+ for ( ; argIndex < argLength ; argIndex++ ) {
+ for ( var i = 0; i < list.length; i++ ) {
+ if ( args[ argIndex ] === list[ i ] ) {
+ // Handle firingIndex and firingLength
+ if ( firing ) {
+ if ( i <= firingLength ) {
+ firingLength--;
+ if ( i <= firingIndex ) {
+ firingIndex--;
+ }
+ }
+ }
+ // Remove the element
+ list.splice( i--, 1 );
+ // If we have some unicity property then
+ // we only need to do this once
+ if ( flags.unique ) {
+ break;
+ }
+ }
+ }
+ }
+ }
+ return this;
+ },
+ // Control if a given callback is in the list
+ has: function( fn ) {
+ if ( list ) {
+ var i = 0,
+ length = list.length;
+ for ( ; i < length; i++ ) {
+ if ( fn === list[ i ] ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ },
+ // Remove all callbacks from the list
+ empty: function() {
+ list = [];
+ return this;
+ },
+ // Have the list do nothing anymore
+ disable: function() {
+ list = stack = memory = undefined;
+ return this;
+ },
+ // Is it disabled?
+ disabled: function() {
+ return !list;
+ },
+ // Lock the list in its current state
+ lock: function() {
+ stack = undefined;
+ if ( !memory || memory === true ) {
+ self.disable();
+ }
+ return this;
+ },
+ // Is it locked?
+ locked: function() {
+ return !stack;
+ },
+ // Call all callbacks with the given context and arguments
+ fireWith: function( context, args ) {
+ if ( stack ) {
+ if ( firing ) {
+ if ( !flags.once ) {
+ stack.push( [ context, args ] );
+ }
+ } else if ( !( flags.once && memory ) ) {
+ fire( context, args );
+ }
+ }
+ return this;
+ },
+ // Call all the callbacks with the given arguments
+ fire: function() {
+ self.fireWith( this, arguments );
+ return this;
+ },
+ // To know if the callbacks have already been called at least once
+ fired: function() {
+ return !!fired;
+ }
+ };
+
+ return self;
+};
+
+
+
+
+var // Static reference to slice
+ sliceDeferred = [].slice;
+
+jQuery.extend({
+
+ Deferred: function( func ) {
+ var doneList = jQuery.Callbacks( "once memory" ),
+ failList = jQuery.Callbacks( "once memory" ),
+ progressList = jQuery.Callbacks( "memory" ),
+ state = "pending",
+ lists = {
+ resolve: doneList,
+ reject: failList,
+ notify: progressList
+ },
+ promise = {
+ done: doneList.add,
+ fail: failList.add,
+ progress: progressList.add,
+
+ state: function() {
+ return state;
+ },
+
+ // Deprecated
+ isResolved: doneList.fired,
+ isRejected: failList.fired,
+
+ then: function( doneCallbacks, failCallbacks, progressCallbacks ) {
+ deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );
+ return this;
+ },
+ always: function() {
+ deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );
+ return this;
+ },
+ pipe: function( fnDone, fnFail, fnProgress ) {
+ return jQuery.Deferred(function( newDefer ) {
+ jQuery.each( {
+ done: [ fnDone, "resolve" ],
+ fail: [ fnFail, "reject" ],
+ progress: [ fnProgress, "notify" ]
+ }, function( handler, data ) {
+ var fn = data[ 0 ],
+ action = data[ 1 ],
+ returned;
+ if ( jQuery.isFunction( fn ) ) {
+ deferred[ handler ](function() {
+ returned = fn.apply( this, arguments );
+ if ( returned && jQuery.isFunction( returned.promise ) ) {
+ returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );
+ } else {
+ newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
+ }
+ });
+ } else {
+ deferred[ handler ]( newDefer[ action ] );
+ }
+ });
+ }).promise();
+ },
+ // Get a promise for this deferred
+ // If obj is provided, the promise aspect is added to the object
+ promise: function( obj ) {
+ if ( obj == null ) {
+ obj = promise;
+ } else {
+ for ( var key in promise ) {
+ obj[ key ] = promise[ key ];
+ }
+ }
+ return obj;
+ }
+ },
+ deferred = promise.promise({}),
+ key;
+
+ for ( key in lists ) {
+ deferred[ key ] = lists[ key ].fire;
+ deferred[ key + "With" ] = lists[ key ].fireWith;
+ }
+
+ // Handle state
+ deferred.done( function() {
+ state = "resolved";
+ }, failList.disable, progressList.lock ).fail( function() {
+ state = "rejected";
+ }, doneList.disable, progressList.lock );
+
+ // Call given func if any
+ if ( func ) {
+ func.call( deferred, deferred );
+ }
+
+ // All done!
+ return deferred;
+ },
+
+ // Deferred helper
+ when: function( firstParam ) {
+ var args = sliceDeferred.call( arguments, 0 ),
+ i = 0,
+ length = args.length,
+ pValues = new Array( length ),
+ count = length,
+ pCount = length,
+ deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
+ firstParam :
+ jQuery.Deferred(),
+ promise = deferred.promise();
+ function resolveFunc( i ) {
+ return function( value ) {
+ args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
+ if ( !( --count ) ) {
+ deferred.resolveWith( deferred, args );
+ }
+ };
+ }
+ function progressFunc( i ) {
+ return function( value ) {
+ pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
+ deferred.notifyWith( promise, pValues );
+ };
+ }
+ if ( length > 1 ) {
+ for ( ; i < length; i++ ) {
+ if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {
+ args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );
+ } else {
+ --count;
+ }
+ }
+ if ( !count ) {
+ deferred.resolveWith( deferred, args );
+ }
+ } else if ( deferred !== firstParam ) {
+ deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
+ }
+ return promise;
+ }
+});
+
+
+
+
+jQuery.support = (function() {
+
+ var support,
+ all,
+ a,
+ select,
+ opt,
+ input,
+ fragment,
+ tds,
+ events,
+ eventName,
+ i,
+ isSupported,
+ div = document.createElement( "div" ),
+ documentElement = document.documentElement;
+
+ // Preliminary tests
+ div.setAttribute("className", "t");
+ div.innerHTML = " <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
+
+ all = div.getElementsByTagName( "*" );
+ a = div.getElementsByTagName( "a" )[ 0 ];
+
+ // Can't get basic test support
+ if ( !all || !all.length || !a ) {
+ return {};
+ }
+
+ // First batch of supports tests
+ select = document.createElement( "select" );
+ opt = select.appendChild( document.createElement("option") );
+ input = div.getElementsByTagName( "input" )[ 0 ];
+
+ support = {
+ // IE strips leading whitespace when .innerHTML is used
+ leadingWhitespace: ( div.firstChild.nodeType === 3 ),
+
+ // Make sure that tbody elements aren't automatically inserted
+ // IE will insert them into empty tables
+ tbody: !div.getElementsByTagName("tbody").length,
+
+ // Make sure that link elements get serialized correctly by innerHTML
+ // This requires a wrapper element in IE
+ htmlSerialize: !!div.getElementsByTagName("link").length,
+
+ // Get the style information from getAttribute
+ // (IE uses .cssText instead)
+ style: /top/.test( a.getAttribute("style") ),
+
+ // Make sure that URLs aren't manipulated
+ // (IE normalizes it by default)
+ hrefNormalized: ( a.getAttribute("href") === "/a" ),
+
+ // Make sure that element opacity exists
+ // (IE uses filter instead)
+ // Use a regex to work around a WebKit issue. See #5145
+ opacity: /^0.55/.test( a.style.opacity ),
+
+ // Verify style float existence
+ // (IE uses styleFloat instead of cssFloat)
+ cssFloat: !!a.style.cssFloat,
+
+ // Make sure that if no value is specified for a checkbox
+ // that it defaults to "on".
+ // (WebKit defaults to "" instead)
+ checkOn: ( input.value === "on" ),
+
+ // Make sure that a selected-by-default option has a working selected property.
+ // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+ optSelected: opt.selected,
+
+ // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
+ getSetAttribute: div.className !== "t",
+
+ // Tests for enctype support on a form(#6743)
+ enctype: !!document.createElement("form").enctype,
+
+ // Makes sure cloning an html5 element does not cause problems
+ // Where outerHTML is undefined, this still works
+ html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
+
+ // Will be defined later
+ submitBubbles: true,
+ changeBubbles: true,
+ focusinBubbles: false,
+ deleteExpando: true,
+ noCloneEvent: true,
+ inlineBlockNeedsLayout: false,
+ shrinkWrapBlocks: false,
+ reliableMarginRight: true,
+ pixelMargin: true
+ };
+
+ // jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead
+ jQuery.boxModel = support.boxModel = (document.compatMode === "CSS1Compat");
+
+ // Make sure checked status is properly cloned
+ input.checked = true;
+ support.noCloneChecked = input.cloneNode( true ).checked;
+
+ // Make sure that the options inside disabled selects aren't marked as disabled
+ // (WebKit marks them as disabled)
+ select.disabled = true;
+ support.optDisabled = !opt.disabled;
+
+ // Test to see if it's possible to delete an expando from an element
+ // Fails in Internet Explorer
+ try {
+ delete div.test;
+ } catch( e ) {
+ support.deleteExpando = false;
+ }
+
+ if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
+ div.attachEvent( "onclick", function() {
+ // Cloning a node shouldn't copy over any
+ // bound event handlers (IE does this)
+ support.noCloneEvent = false;
+ });
+ div.cloneNode( true ).fireEvent( "onclick" );
+ }
+
+ // Check if a radio maintains its value
+ // after being appended to the DOM
+ input = document.createElement("input");
+ input.value = "t";
+ input.setAttribute("type", "radio");
+ support.radioValue = input.value === "t";
+
+ input.setAttribute("checked", "checked");
+
+ // #11217 - WebKit loses check when the name is after the checked attribute
+ input.setAttribute( "name", "t" );
+
+ div.appendChild( input );
+ fragment = document.createDocumentFragment();
+ fragment.appendChild( div.lastChild );
+
+ // WebKit doesn't clone checked state correctly in fragments
+ support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+ // Check if a disconnected checkbox will retain its checked
+ // value of true after appended to the DOM (IE6/7)
+ support.appendChecked = input.checked;
+
+ fragment.removeChild( input );
+ fragment.appendChild( div );
+
+ // Technique from Juriy Zaytsev
+ // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
+ // We only care about the case where non-standard event systems
+ // are used, namely in IE. Short-circuiting here helps us to
+ // avoid an eval call (in setAttribute) which can cause CSP
+ // to go haywire. See: https://developer.mozilla.org/en/Security/CSP
+ if ( div.attachEvent ) {
+ for ( i in {
+ submit: 1,
+ change: 1,
+ focusin: 1
+ }) {
+ eventName = "on" + i;
+ isSupported = ( eventName in div );
+ if ( !isSupported ) {
+ div.setAttribute( eventName, "return;" );
+ isSupported = ( typeof div[ eventName ] === "function" );
+ }
+ support[ i + "Bubbles" ] = isSupported;
+ }
+ }
+
+ fragment.removeChild( div );
+
+ // Null elements to avoid leaks in IE
+ fragment = select = opt = div = input = null;
+
+ // Run tests that need a body at doc ready
+ jQuery(function() {
+ var container, outer, inner, table, td, offsetSupport,
+ marginDiv, conMarginTop, style, html, positionTopLeftWidthHeight,
+ paddingMarginBorderVisibility, paddingMarginBorder,
+ body = document.getElementsByTagName("body")[0];
+
+ if ( !body ) {
+ // Return for frameset docs that don't have a body
+ return;
+ }
+
+ conMarginTop = 1;
+ paddingMarginBorder = "padding:0;margin:0;border:";
+ positionTopLeftWidthHeight = "position:absolute;top:0;left:0;width:1px;height:1px;";
+ paddingMarginBorderVisibility = paddingMarginBorder + "0;visibility:hidden;";
+ style = "style='" + positionTopLeftWidthHeight + paddingMarginBorder + "5px solid #000;";
+ html = "<div " + style + "display:block;'><div style='" + paddingMarginBorder + "0;display:block;overflow:hidden;'></div></div>" +
+ "<table " + style + "' cellpadding='0' cellspacing='0'>" +
+ "<tr><td></td></tr></table>";
+
+ container = document.createElement("div");
+ container.style.cssText = paddingMarginBorderVisibility + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px";
+ body.insertBefore( container, body.firstChild );
+
+ // Construct the test element
+ div = document.createElement("div");
+ container.appendChild( div );
+
+ // Check if table cells still have offsetWidth/Height when they are set
+ // to display:none and there are still other visible table cells in a
+ // table row; if so, offsetWidth/Height are not reliable for use when
+ // determining if an element has been hidden directly using
+ // display:none (it is still safe to use offsets if a parent element is
+ // hidden; don safety goggles and see bug #4512 for more information).
+ // (only IE 8 fails this test)
+ div.innerHTML = "<table><tr><td style='" + paddingMarginBorder + "0;display:none'></td><td>t</td></tr></table>";
+ tds = div.getElementsByTagName( "td" );
+ isSupported = ( tds[ 0 ].offsetHeight === 0 );
+
+ tds[ 0 ].style.display = "";
+ tds[ 1 ].style.display = "none";
+
+ // Check if empty table cells still have offsetWidth/Height
+ // (IE <= 8 fail this test)
+ support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
+
+ // Check if div with explicit width and no margin-right incorrectly
+ // gets computed margin-right based on width of container. For more
+ // info see bug #3333
+ // Fails in WebKit before Feb 2011 nightlies
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ if ( window.getComputedStyle ) {
+ div.innerHTML = "";
+ marginDiv = document.createElement( "div" );
+ marginDiv.style.width = "0";
+ marginDiv.style.marginRight = "0";
+ div.style.width = "2px";
+ div.appendChild( marginDiv );
+ support.reliableMarginRight =
+ ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
+ }
+
+ if ( typeof div.style.zoom !== "undefined" ) {
+ // Check if natively block-level elements act like inline-block
+ // elements when setting their display to 'inline' and giving
+ // them layout
+ // (IE < 8 does this)
+ div.innerHTML = "";
+ div.style.width = div.style.padding = "1px";
+ div.style.border = 0;
+ div.style.overflow = "hidden";
+ div.style.display = "inline";
+ div.style.zoom = 1;
+ support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
+
+ // Check if elements with layout shrink-wrap their children
+ // (IE 6 does this)
+ div.style.display = "block";
+ div.style.overflow = "visible";
+ div.innerHTML = "<div style='width:5px;'></div>";
+ support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
+ }
+
+ div.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility;
+ div.innerHTML = html;
+
+ outer = div.firstChild;
+ inner = outer.firstChild;
+ td = outer.nextSibling.firstChild.firstChild;
+
+ offsetSupport = {
+ doesNotAddBorder: ( inner.offsetTop !== 5 ),
+ doesAddBorderForTableAndCells: ( td.offsetTop === 5 )
+ };
+
+ inner.style.position = "fixed";
+ inner.style.top = "20px";
+
+ // safari subtracts parent border width here which is 5px
+ offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );
+ inner.style.position = inner.style.top = "";
+
+ outer.style.overflow = "hidden";
+ outer.style.position = "relative";
+
+ offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );
+ offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );
+
+ if ( window.getComputedStyle ) {
+ div.style.marginTop = "1%";
+ support.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== "1%";
+ }
+
+ if ( typeof container.style.zoom !== "undefined" ) {
+ container.style.zoom = 1;
+ }
+
+ body.removeChild( container );
+ marginDiv = div = container = null;
+
+ jQuery.extend( support, offsetSupport );
+ });
+
+ return support;
+})();
+
+
+
+
+var rbrace = /^(?:\{.*\}|\[.*\])$/,
+ rmultiDash = /([A-Z])/g;
+
+jQuery.extend({
+ cache: {},
+
+ // Please use with caution
+ uuid: 0,
+
+ // Unique for each copy of jQuery on the page
+ // Non-digits removed to match rinlinejQuery
+ expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
+
+ // The following elements throw uncatchable exceptions if you
+ // attempt to add expando properties to them.
+ noData: {
+ "embed": true,
+ // Ban all objects except for Flash (which handle expandos)
+ "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
+ "applet": true
+ },
+
+ hasData: function( elem ) {
+ elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
+ return !!elem && !isEmptyDataObject( elem );
+ },
+
+ data: function( elem, name, data, pvt /* Internal Use Only */ ) {
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var privateCache, thisCache, ret,
+ internalKey = jQuery.expando,
+ getByName = typeof name === "string",
+
+ // We have to handle DOM nodes and JS objects differently because IE6-7
+ // can't GC object references properly across the DOM-JS boundary
+ isNode = elem.nodeType,
+
+ // Only DOM nodes need the global jQuery cache; JS object data is
+ // attached directly to the object so GC can occur automatically
+ cache = isNode ? jQuery.cache : elem,
+
+ // Only defining an ID for JS objects if its cache already exists allows
+ // the code to shortcut on the same path as a DOM node with no cache
+ id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,
+ isEvents = name === "events";
+
+ // Avoid doing any more work than we need to when trying to get data on an
+ // object that has no data at all
+ if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {
+ return;
+ }
+
+ if ( !id ) {
+ // Only DOM nodes need a new unique ID for each element since their data
+ // ends up in the global cache
+ if ( isNode ) {
+ elem[ internalKey ] = id = ++jQuery.uuid;
+ } else {
+ id = internalKey;
+ }
+ }
+
+ if ( !cache[ id ] ) {
+ cache[ id ] = {};
+
+ // Avoids exposing jQuery metadata on plain JS objects when the object
+ // is serialized using JSON.stringify
+ if ( !isNode ) {
+ cache[ id ].toJSON = jQuery.noop;
+ }
+ }
+
+ // An object can be passed to jQuery.data instead of a key/value pair; this gets
+ // shallow copied over onto the existing cache
+ if ( typeof name === "object" || typeof name === "function" ) {
+ if ( pvt ) {
+ cache[ id ] = jQuery.extend( cache[ id ], name );
+ } else {
+ cache[ id ].data = jQuery.extend( cache[ id ].data, name );
+ }
+ }
+
+ privateCache = thisCache = cache[ id ];
+
+ // jQuery data() is stored in a separate object inside the object's internal data
+ // cache in order to avoid key collisions between internal data and user-defined
+ // data.
+ if ( !pvt ) {
+ if ( !thisCache.data ) {
+ thisCache.data = {};
+ }
+
+ thisCache = thisCache.data;
+ }
+
+ if ( data !== undefined ) {
+ thisCache[ jQuery.camelCase( name ) ] = data;
+ }
+
+ // Users should not attempt to inspect the internal events object using jQuery.data,
+ // it is undocumented and subject to change. But does anyone listen? No.
+ if ( isEvents && !thisCache[ name ] ) {
+ return privateCache.events;
+ }
+
+ // Check for both converted-to-camel and non-converted data property names
+ // If a data property was specified
+ if ( getByName ) {
+
+ // First Try to find as-is property data
+ ret = thisCache[ name ];
+
+ // Test for null|undefined property data
+ if ( ret == null ) {
+
+ // Try to find the camelCased property
+ ret = thisCache[ jQuery.camelCase( name ) ];
+ }
+ } else {
+ ret = thisCache;
+ }
+
+ return ret;
+ },
+
+ removeData: function( elem, name, pvt /* Internal Use Only */ ) {
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var thisCache, i, l,
+
+ // Reference to internal data cache key
+ internalKey = jQuery.expando,
+
+ isNode = elem.nodeType,
+
+ // See jQuery.data for more information
+ cache = isNode ? jQuery.cache : elem,
+
+ // See jQuery.data for more information
+ id = isNode ? elem[ internalKey ] : internalKey;
+
+ // If there is already no cache entry for this object, there is no
+ // purpose in continuing
+ if ( !cache[ id ] ) {
+ return;
+ }
+
+ if ( name ) {
+
+ thisCache = pvt ? cache[ id ] : cache[ id ].data;
+
+ if ( thisCache ) {
+
+ // Support array or space separated string names for data keys
+ if ( !jQuery.isArray( name ) ) {
+
+ // try the string as a key before any manipulation
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+
+ // split the camel cased version by spaces unless a key with the spaces exists
+ name = jQuery.camelCase( name );
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+ name = name.split( " " );
+ }
+ }
+ }
+
+ for ( i = 0, l = name.length; i < l; i++ ) {
+ delete thisCache[ name[i] ];
+ }
+
+ // If there is no data left in the cache, we want to continue
+ // and let the cache object itself get destroyed
+ if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
+ return;
+ }
+ }
+ }
+
+ // See jQuery.data for more information
+ if ( !pvt ) {
+ delete cache[ id ].data;
+
+ // Don't destroy the parent cache unless the internal data object
+ // had been the only thing left in it
+ if ( !isEmptyDataObject(cache[ id ]) ) {
+ return;
+ }
+ }
+
+ // Browsers that fail expando deletion also refuse to delete expandos on
+ // the window, but it will allow it on all other JS objects; other browsers
+ // don't care
+ // Ensure that `cache` is not a window object #10080
+ if ( jQuery.support.deleteExpando || !cache.setInterval ) {
+ delete cache[ id ];
+ } else {
+ cache[ id ] = null;
+ }
+
+ // We destroyed the cache and need to eliminate the expando on the node to avoid
+ // false lookups in the cache for entries that no longer exist
+ if ( isNode ) {
+ // IE does not allow us to delete expando properties from nodes,
+ // nor does it have a removeAttribute function on Document nodes;
+ // we must handle all of these cases
+ if ( jQuery.support.deleteExpando ) {
+ delete elem[ internalKey ];
+ } else if ( elem.removeAttribute ) {
+ elem.removeAttribute( internalKey );
+ } else {
+ elem[ internalKey ] = null;
+ }
+ }
+ },
+
+ // For internal use only.
+ _data: function( elem, name, data ) {
+ return jQuery.data( elem, name, data, true );
+ },
+
+ // A method for determining if a DOM node can handle the data expando
+ acceptData: function( elem ) {
+ if ( elem.nodeName ) {
+ var match = jQuery.noData[ elem.nodeName.toLowerCase() ];
+
+ if ( match ) {
+ return !(match === true || elem.getAttribute("classid") !== match);
+ }
+ }
+
+ return true;
+ }
+});
+
+jQuery.fn.extend({
+ data: function( key, value ) {
+ var parts, part, attr, name, l,
+ elem = this[0],
+ i = 0,
+ data = null;
+
+ // Gets all values
+ if ( key === undefined ) {
+ if ( this.length ) {
+ data = jQuery.data( elem );
+
+ if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
+ attr = elem.attributes;
+ for ( l = attr.length; i < l; i++ ) {
+ name = attr[i].name;
+
+ if ( name.indexOf( "data-" ) === 0 ) {
+ name = jQuery.camelCase( name.substring(5) );
+
+ dataAttr( elem, name, data[ name ] );
+ }
+ }
+ jQuery._data( elem, "parsedAttrs", true );
+ }
+ }
+
+ return data;
+ }
+
+ // Sets multiple values
+ if ( typeof key === "object" ) {
+ return this.each(function() {
+ jQuery.data( this, key );
+ });
+ }
+
+ parts = key.split( ".", 2 );
+ parts[1] = parts[1] ? "." + parts[1] : "";
+ part = parts[1] + "!";
+
+ return jQuery.access( this, function( value ) {
+
+ if ( value === undefined ) {
+ data = this.triggerHandler( "getData" + part, [ parts[0] ] );
+
+ // Try to fetch any internally stored data first
+ if ( data === undefined && elem ) {
+ data = jQuery.data( elem, key );
+ data = dataAttr( elem, key, data );
+ }
+
+ return data === undefined && parts[1] ?
+ this.data( parts[0] ) :
+ data;
+ }
+
+ parts[1] = value;
+ this.each(function() {
+ var self = jQuery( this );
+
+ self.triggerHandler( "setData" + part, parts );
+ jQuery.data( this, key, value );
+ self.triggerHandler( "changeData" + part, parts );
+ });
+ }, null, value, arguments.length > 1, null, false );
+ },
+
+ removeData: function( key ) {
+ return this.each(function() {
+ jQuery.removeData( this, key );
+ });
+ }
+});
+
+function dataAttr( elem, key, data ) {
+ // If nothing was found internally, try to fetch any
+ // data from the HTML5 data-* attribute
+ if ( data === undefined && elem.nodeType === 1 ) {
+
+ var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+
+ data = elem.getAttribute( name );
+
+ if ( typeof data === "string" ) {
+ try {
+ data = data === "true" ? true :
+ data === "false" ? false :
+ data === "null" ? null :
+ jQuery.isNumeric( data ) ? +data :
+ rbrace.test( data ) ? jQuery.parseJSON( data ) :
+ data;
+ } catch( e ) {}
+
+ // Make sure we set the data so it isn't changed later
+ jQuery.data( elem, key, data );
+
+ } else {
+ data = undefined;
+ }
+ }
+
+ return data;
+}
+
+// checks a cache object for emptiness
+function isEmptyDataObject( obj ) {
+ for ( var name in obj ) {
+
+ // if the public data object is empty, the private is still empty
+ if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
+ continue;
+ }
+ if ( name !== "toJSON" ) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+
+
+function handleQueueMarkDefer( elem, type, src ) {
+ var deferDataKey = type + "defer",
+ queueDataKey = type + "queue",
+ markDataKey = type + "mark",
+ defer = jQuery._data( elem, deferDataKey );
+ if ( defer &&
+ ( src === "queue" || !jQuery._data(elem, queueDataKey) ) &&
+ ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) {
+ // Give room for hard-coded callbacks to fire first
+ // and eventually mark/queue something else on the element
+ setTimeout( function() {
+ if ( !jQuery._data( elem, queueDataKey ) &&
+ !jQuery._data( elem, markDataKey ) ) {
+ jQuery.removeData( elem, deferDataKey, true );
+ defer.fire();
+ }
+ }, 0 );
+ }
+}
+
+jQuery.extend({
+
+ _mark: function( elem, type ) {
+ if ( elem ) {
+ type = ( type || "fx" ) + "mark";
+ jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );
+ }
+ },
+
+ _unmark: function( force, elem, type ) {
+ if ( force !== true ) {
+ type = elem;
+ elem = force;
+ force = false;
+ }
+ if ( elem ) {
+ type = type || "fx";
+ var key = type + "mark",
+ count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );
+ if ( count ) {
+ jQuery._data( elem, key, count );
+ } else {
+ jQuery.removeData( elem, key, true );
+ handleQueueMarkDefer( elem, type, "mark" );
+ }
+ }
+ },
+
+ queue: function( elem, type, data ) {
+ var q;
+ if ( elem ) {
+ type = ( type || "fx" ) + "queue";
+ q = jQuery._data( elem, type );
+
+ // Speed up dequeue by getting out quickly if this is just a lookup
+ if ( data ) {
+ if ( !q || jQuery.isArray(data) ) {
+ q = jQuery._data( elem, type, jQuery.makeArray(data) );
+ } else {
+ q.push( data );
+ }
+ }
+ return q || [];
+ }
+ },
+
+ dequeue: function( elem, type ) {
+ type = type || "fx";
+
+ var queue = jQuery.queue( elem, type ),
+ fn = queue.shift(),
+ hooks = {};
+
+ // If the fx queue is dequeued, always remove the progress sentinel
+ if ( fn === "inprogress" ) {
+ fn = queue.shift();
+ }
+
+ if ( fn ) {
+ // Add a progress sentinel to prevent the fx queue from being
+ // automatically dequeued
+ if ( type === "fx" ) {
+ queue.unshift( "inprogress" );
+ }
+
+ jQuery._data( elem, type + ".run", hooks );
+ fn.call( elem, function() {
+ jQuery.dequeue( elem, type );
+ }, hooks );
+ }
+
+ if ( !queue.length ) {
+ jQuery.removeData( elem, type + "queue " + type + ".run", true );
+ handleQueueMarkDefer( elem, type, "queue" );
+ }
+ }
+});
+
+jQuery.fn.extend({
+ queue: function( type, data ) {
+ var setter = 2;
+
+ if ( typeof type !== "string" ) {
+ data = type;
+ type = "fx";
+ setter--;
+ }
+
+ if ( arguments.length < setter ) {
+ return jQuery.queue( this[0], type );
+ }
+
+ return data === undefined ?
+ this :
+ this.each(function() {
+ var queue = jQuery.queue( this, type, data );
+
+ if ( type === "fx" && queue[0] !== "inprogress" ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ dequeue: function( type ) {
+ return this.each(function() {
+ jQuery.dequeue( this, type );
+ });
+ },
+ // Based off of the plugin by Clint Helfers, with permission.
+ // http://blindsignals.com/index.php/2009/07/jquery-delay/
+ delay: function( time, type ) {
+ time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+ type = type || "fx";
+
+ return this.queue( type, function( next, hooks ) {
+ var timeout = setTimeout( next, time );
+ hooks.stop = function() {
+ clearTimeout( timeout );
+ };
+ });
+ },
+ clearQueue: function( type ) {
+ return this.queue( type || "fx", [] );
+ },
+ // Get a promise resolved when queues of a certain type
+ // are emptied (fx is the type by default)
+ promise: function( type, object ) {
+ if ( typeof type !== "string" ) {
+ object = type;
+ type = undefined;
+ }
+ type = type || "fx";
+ var defer = jQuery.Deferred(),
+ elements = this,
+ i = elements.length,
+ count = 1,
+ deferDataKey = type + "defer",
+ queueDataKey = type + "queue",
+ markDataKey = type + "mark",
+ tmp;
+ function resolve() {
+ if ( !( --count ) ) {
+ defer.resolveWith( elements, [ elements ] );
+ }
+ }
+ while( i-- ) {
+ if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
+ ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
+ jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
+ jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) {
+ count++;
+ tmp.add( resolve );
+ }
+ }
+ resolve();
+ return defer.promise( object );
+ }
+});
+
+
+
+
+var rclass = /[\n\t\r]/g,
+ rspace = /\s+/,
+ rreturn = /\r/g,
+ rtype = /^(?:button|input)$/i,
+ rfocusable = /^(?:button|input|object|select|textarea)$/i,
+ rclickable = /^a(?:rea)?$/i,
+ rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
+ getSetAttribute = jQuery.support.getSetAttribute,
+ nodeHook, boolHook, fixSpecified;
+
+jQuery.fn.extend({
+ attr: function( name, value ) {
+ return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
+ },
+
+ removeAttr: function( name ) {
+ return this.each(function() {
+ jQuery.removeAttr( this, name );
+ });
+ },
+
+ prop: function( name, value ) {
+ return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
+ },
+
+ removeProp: function( name ) {
+ name = jQuery.propFix[ name ] || name;
+ return this.each(function() {
+ // try/catch handles cases where IE balks (such as removing a property on window)
+ try {
+ this[ name ] = undefined;
+ delete this[ name ];
+ } catch( e ) {}
+ });
+ },
+
+ addClass: function( value ) {
+ var classNames, i, l, elem,
+ setClass, c, cl;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).addClass( value.call(this, j, this.className) );
+ });
+ }
+
+ if ( value && typeof value === "string" ) {
+ classNames = value.split( rspace );
+
+ for ( i = 0, l = this.length; i < l; i++ ) {
+ elem = this[ i ];
+
+ if ( elem.nodeType === 1 ) {
+ if ( !elem.className && classNames.length === 1 ) {
+ elem.className = value;
+
+ } else {
+ setClass = " " + elem.className + " ";
+
+ for ( c = 0, cl = classNames.length; c < cl; c++ ) {
+ if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
+ setClass += classNames[ c ] + " ";
+ }
+ }
+ elem.className = jQuery.trim( setClass );
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ removeClass: function( value ) {
+ var classNames, i, l, elem, className, c, cl;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).removeClass( value.call(this, j, this.className) );
+ });
+ }
+
+ if ( (value && typeof value === "string") || value === undefined ) {
+ classNames = ( value || "" ).split( rspace );
+
+ for ( i = 0, l = this.length; i < l; i++ ) {
+ elem = this[ i ];
+
+ if ( elem.nodeType === 1 && elem.className ) {
+ if ( value ) {
+ className = (" " + elem.className + " ").replace( rclass, " " );
+ for ( c = 0, cl = classNames.length; c < cl; c++ ) {
+ className = className.replace(" " + classNames[ c ] + " ", " ");
+ }
+ elem.className = jQuery.trim( className );
+
+ } else {
+ elem.className = "";
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ toggleClass: function( value, stateVal ) {
+ var type = typeof value,
+ isBool = typeof stateVal === "boolean";
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( i ) {
+ jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
+ });
+ }
+
+ return this.each(function() {
+ if ( type === "string" ) {
+ // toggle individual class names
+ var className,
+ i = 0,
+ self = jQuery( this ),
+ state = stateVal,
+ classNames = value.split( rspace );
+
+ while ( (className = classNames[ i++ ]) ) {
+ // check each className given, space seperated list
+ state = isBool ? state : !self.hasClass( className );
+ self[ state ? "addClass" : "removeClass" ]( className );
+ }
+
+ } else if ( type === "undefined" || type === "boolean" ) {
+ if ( this.className ) {
+ // store className if set
+ jQuery._data( this, "__className__", this.className );
+ }
+
+ // toggle whole className
+ this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
+ }
+ });
+ },
+
+ hasClass: function( selector ) {
+ var className = " " + selector + " ",
+ i = 0,
+ l = this.length;
+ for ( ; i < l; i++ ) {
+ if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
+ return true;
+ }
+ }
+
+ return false;
+ },
+
+ val: function( value ) {
+ var hooks, ret, isFunction,
+ elem = this[0];
+
+ if ( !arguments.length ) {
+ if ( elem ) {
+ hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+ return ret;
+ }
+
+ ret = elem.value;
+
+ return typeof ret === "string" ?
+ // handle most common string cases
+ ret.replace(rreturn, "") :
+ // handle cases where value is null/undef or number
+ ret == null ? "" : ret;
+ }
+
+ return;
+ }
+
+ isFunction = jQuery.isFunction( value );
+
+ return this.each(function( i ) {
+ var self = jQuery(this), val;
+
+ if ( this.nodeType !== 1 ) {
+ return;
+ }
+
+ if ( isFunction ) {
+ val = value.call( this, i, self.val() );
+ } else {
+ val = value;
+ }
+
+ // Treat null/undefined as ""; convert numbers to string
+ if ( val == null ) {
+ val = "";
+ } else if ( typeof val === "number" ) {
+ val += "";
+ } else if ( jQuery.isArray( val ) ) {
+ val = jQuery.map(val, function ( value ) {
+ return value == null ? "" : value + "";
+ });
+ }
+
+ hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+ // If set returns undefined, fall back to normal setting
+ if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
+ this.value = val;
+ }
+ });
+ }
+});
+
+jQuery.extend({
+ valHooks: {
+ option: {
+ get: function( elem ) {
+ // attributes.value is undefined in Blackberry 4.7 but
+ // uses .value. See #6932
+ var val = elem.attributes.value;
+ return !val || val.specified ? elem.value : elem.text;
+ }
+ },
+ select: {
+ get: function( elem ) {
+ var value, i, max, option,
+ index = elem.selectedIndex,
+ values = [],
+ options = elem.options,
+ one = elem.type === "select-one";
+
+ // Nothing was selected
+ if ( index < 0 ) {
+ return null;
+ }
+
+ // Loop through all the selected options
+ i = one ? index : 0;
+ max = one ? index + 1 : options.length;
+ for ( ; i < max; i++ ) {
+ option = options[ i ];
+
+ // Don't return options that are disabled or in a disabled optgroup
+ if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
+ (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
+
+ // Get the specific value for the option
+ value = jQuery( option ).val();
+
+ // We don't need an array for one selects
+ if ( one ) {
+ return value;
+ }
+
+ // Multi-Selects return an array
+ values.push( value );
+ }
+ }
+
+ // Fixes Bug #2551 -- select.val() broken in IE after form.reset()
+ if ( one && !values.length && options.length ) {
+ return jQuery( options[ index ] ).val();
+ }
+
+ return values;
+ },
+
+ set: function( elem, value ) {
+ var values = jQuery.makeArray( value );
+
+ jQuery(elem).find("option").each(function() {
+ this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
+ });
+
+ if ( !values.length ) {
+ elem.selectedIndex = -1;
+ }
+ return values;
+ }
+ }
+ },
+
+ attrFn: {
+ val: true,
+ css: true,
+ html: true,
+ text: true,
+ data: true,
+ width: true,
+ height: true,
+ offset: true
+ },
+
+ attr: function( elem, name, value, pass ) {
+ var ret, hooks, notxml,
+ nType = elem.nodeType;
+
+ // don't get/set attributes on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ if ( pass && name in jQuery.attrFn ) {
+ return jQuery( elem )[ name ]( value );
+ }
+
+ // Fallback to prop when attributes are not supported
+ if ( typeof elem.getAttribute === "undefined" ) {
+ return jQuery.prop( elem, name, value );
+ }
+
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+ // All attributes are lowercase
+ // Grab necessary hook if one is defined
+ if ( notxml ) {
+ name = name.toLowerCase();
+ hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
+ }
+
+ if ( value !== undefined ) {
+
+ if ( value === null ) {
+ jQuery.removeAttr( elem, name );
+ return;
+
+ } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
+ return ret;
+
+ } else {
+ elem.setAttribute( name, "" + value );
+ return value;
+ }
+
+ } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
+ return ret;
+
+ } else {
+
+ ret = elem.getAttribute( name );
+
+ // Non-existent attributes return null, we normalize to undefined
+ return ret === null ?
+ undefined :
+ ret;
+ }
+ },
+
+ removeAttr: function( elem, value ) {
+ var propName, attrNames, name, l, isBool,
+ i = 0;
+
+ if ( value && elem.nodeType === 1 ) {
+ attrNames = value.toLowerCase().split( rspace );
+ l = attrNames.length;
+
+ for ( ; i < l; i++ ) {
+ name = attrNames[ i ];
+
+ if ( name ) {
+ propName = jQuery.propFix[ name ] || name;
+ isBool = rboolean.test( name );
+
+ // See #9699 for explanation of this approach (setting first, then removal)
+ // Do not do this for boolean attributes (see #10870)
+ if ( !isBool ) {
+ jQuery.attr( elem, name, "" );
+ }
+ elem.removeAttribute( getSetAttribute ? name : propName );
+
+ // Set corresponding property to false for boolean attributes
+ if ( isBool && propName in elem ) {
+ elem[ propName ] = false;
+ }
+ }
+ }
+ }
+ },
+
+ attrHooks: {
+ type: {
+ set: function( elem, value ) {
+ // We can't allow the type property to be changed (since it causes problems in IE)
+ if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
+ jQuery.error( "type property can't be changed" );
+ } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
+ // Setting the type on a radio button after the value resets the value in IE6-9
+ // Reset value to it's default in case type is set after value
+ // This is for element creation
+ var val = elem.value;
+ elem.setAttribute( "type", value );
+ if ( val ) {
+ elem.value = val;
+ }
+ return value;
+ }
+ }
+ },
+ // Use the value property for back compat
+ // Use the nodeHook for button elements in IE6/7 (#1954)
+ value: {
+ get: function( elem, name ) {
+ if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
+ return nodeHook.get( elem, name );
+ }
+ return name in elem ?
+ elem.value :
+ null;
+ },
+ set: function( elem, value, name ) {
+ if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
+ return nodeHook.set( elem, value, name );
+ }
+ // Does not return so that setAttribute is also used
+ elem.value = value;
+ }
+ }
+ },
+
+ propFix: {
+ tabindex: "tabIndex",
+ readonly: "readOnly",
+ "for": "htmlFor",
+ "class": "className",
+ maxlength: "maxLength",
+ cellspacing: "cellSpacing",
+ cellpadding: "cellPadding",
+ rowspan: "rowSpan",
+ colspan: "colSpan",
+ usemap: "useMap",
+ frameborder: "frameBorder",
+ contenteditable: "contentEditable"
+ },
+
+ prop: function( elem, name, value ) {
+ var ret, hooks, notxml,
+ nType = elem.nodeType;
+
+ // don't get/set properties on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+ if ( notxml ) {
+ // Fix name and attach hooks
+ name = jQuery.propFix[ name ] || name;
+ hooks = jQuery.propHooks[ name ];
+ }
+
+ if ( value !== undefined ) {
+ if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+ return ret;
+
+ } else {
+ return ( elem[ name ] = value );
+ }
+
+ } else {
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+ return ret;
+
+ } else {
+ return elem[ name ];
+ }
+ }
+ },
+
+ propHooks: {
+ tabIndex: {
+ get: function( elem ) {
+ // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+ // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+ var attributeNode = elem.getAttributeNode("tabindex");
+
+ return attributeNode && attributeNode.specified ?
+ parseInt( attributeNode.value, 10 ) :
+ rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+ 0 :
+ undefined;
+ }
+ }
+ }
+});
+
+// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)
+jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;
+
+// Hook for boolean attributes
+boolHook = {
+ get: function( elem, name ) {
+ // Align boolean attributes with corresponding properties
+ // Fall back to attribute presence where some booleans are not supported
+ var attrNode,
+ property = jQuery.prop( elem, name );
+ return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
+ name.toLowerCase() :
+ undefined;
+ },
+ set: function( elem, value, name ) {
+ var propName;
+ if ( value === false ) {
+ // Remove boolean attributes when set to false
+ jQuery.removeAttr( elem, name );
+ } else {
+ // value is true since we know at this point it's type boolean and not false
+ // Set boolean attributes to the same name and set the DOM property
+ propName = jQuery.propFix[ name ] || name;
+ if ( propName in elem ) {
+ // Only set the IDL specifically if it already exists on the element
+ elem[ propName ] = true;
+ }
+
+ elem.setAttribute( name, name.toLowerCase() );
+ }
+ return name;
+ }
+};
+
+// IE6/7 do not support getting/setting some attributes with get/setAttribute
+if ( !getSetAttribute ) {
+
+ fixSpecified = {
+ name: true,
+ id: true,
+ coords: true
+ };
+
+ // Use this for any attribute in IE6/7
+ // This fixes almost every IE6/7 issue
+ nodeHook = jQuery.valHooks.button = {
+ get: function( elem, name ) {
+ var ret;
+ ret = elem.getAttributeNode( name );
+ return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ?
+ ret.nodeValue :
+ undefined;
+ },
+ set: function( elem, value, name ) {
+ // Set the existing or create a new attribute node
+ var ret = elem.getAttributeNode( name );
+ if ( !ret ) {
+ ret = document.createAttribute( name );
+ elem.setAttributeNode( ret );
+ }
+ return ( ret.nodeValue = value + "" );
+ }
+ };
+
+ // Apply the nodeHook to tabindex
+ jQuery.attrHooks.tabindex.set = nodeHook.set;
+
+ // Set width and height to auto instead of 0 on empty string( Bug #8150 )
+ // This is for removals
+ jQuery.each([ "width", "height" ], function( i, name ) {
+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+ set: function( elem, value ) {
+ if ( value === "" ) {
+ elem.setAttribute( name, "auto" );
+ return value;
+ }
+ }
+ });
+ });
+
+ // Set contenteditable to false on removals(#10429)
+ // Setting to empty string throws an error as an invalid value
+ jQuery.attrHooks.contenteditable = {
+ get: nodeHook.get,
+ set: function( elem, value, name ) {
+ if ( value === "" ) {
+ value = "false";
+ }
+ nodeHook.set( elem, value, name );
+ }
+ };
+}
+
+
+// Some attributes require a special call on IE
+if ( !jQuery.support.hrefNormalized ) {
+ jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+ get: function( elem ) {
+ var ret = elem.getAttribute( name, 2 );
+ return ret === null ? undefined : ret;
+ }
+ });
+ });
+}
+
+if ( !jQuery.support.style ) {
+ jQuery.attrHooks.style = {
+ get: function( elem ) {
+ // Return undefined in the case of empty string
+ // Normalize to lowercase since IE uppercases css property names
+ return elem.style.cssText.toLowerCase() || undefined;
+ },
+ set: function( elem, value ) {
+ return ( elem.style.cssText = "" + value );
+ }
+ };
+}
+
+// Safari mis-reports the default selected property of an option
+// Accessing the parent's selectedIndex property fixes it
+if ( !jQuery.support.optSelected ) {
+ jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
+ get: function( elem ) {
+ var parent = elem.parentNode;
+
+ if ( parent ) {
+ parent.selectedIndex;
+
+ // Make sure that it also works with optgroups, see #5701
+ if ( parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ }
+ return null;
+ }
+ });
+}
+
+// IE6/7 call enctype encoding
+if ( !jQuery.support.enctype ) {
+ jQuery.propFix.enctype = "encoding";
+}
+
+// Radios and checkboxes getter/setter
+if ( !jQuery.support.checkOn ) {
+ jQuery.each([ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = {
+ get: function( elem ) {
+ // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
+ return elem.getAttribute("value") === null ? "on" : elem.value;
+ }
+ };
+ });
+}
+jQuery.each([ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
+ set: function( elem, value ) {
+ if ( jQuery.isArray( value ) ) {
+ return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
+ }
+ }
+ });
+});
+
+
+
+
+var rformElems = /^(?:textarea|input|select)$/i,
+ rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/,
+ rhoverHack = /(?:^|\s)hover(\.\S+)?\b/,
+ rkeyEvent = /^key/,
+ rmouseEvent = /^(?:mouse|contextmenu)|click/,
+ rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
+ rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,
+ quickParse = function( selector ) {
+ var quick = rquickIs.exec( selector );
+ if ( quick ) {
+ // 0 1 2 3
+ // [ _, tag, id, class ]
+ quick[1] = ( quick[1] || "" ).toLowerCase();
+ quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" );
+ }
+ return quick;
+ },
+ quickIs = function( elem, m ) {
+ var attrs = elem.attributes || {};
+ return (
+ (!m[1] || elem.nodeName.toLowerCase() === m[1]) &&
+ (!m[2] || (attrs.id || {}).value === m[2]) &&
+ (!m[3] || m[3].test( (attrs[ "class" ] || {}).value ))
+ );
+ },
+ hoverHack = function( events ) {
+ return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
+ };
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+ add: function( elem, types, handler, data, selector ) {
+
+ var elemData, eventHandle, events,
+ t, tns, type, namespaces, handleObj,
+ handleObjIn, quick, handlers, special;
+
+ // Don't attach events to noData or text/comment nodes (allow plain objects tho)
+ if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
+ return;
+ }
+
+ // Caller can pass in an object of custom data in lieu of the handler
+ if ( handler.handler ) {
+ handleObjIn = handler;
+ handler = handleObjIn.handler;
+ selector = handleObjIn.selector;
+ }
+
+ // Make sure that the handler has a unique ID, used to find/remove it later
+ if ( !handler.guid ) {
+ handler.guid = jQuery.guid++;
+ }
+
+ // Init the element's event structure and main handler, if this is the first
+ events = elemData.events;
+ if ( !events ) {
+ elemData.events = events = {};
+ }
+ eventHandle = elemData.handle;
+ if ( !eventHandle ) {
+ elemData.handle = eventHandle = function( e ) {
+ // Discard the second event of a jQuery.event.trigger() and
+ // when an event is called after a page has unloaded
+ return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
+ jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
+ undefined;
+ };
+ // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
+ eventHandle.elem = elem;
+ }
+
+ // Handle multiple events separated by a space
+ // jQuery(...).bind("mouseover mouseout", fn);
+ types = jQuery.trim( hoverHack(types) ).split( " " );
+ for ( t = 0; t < types.length; t++ ) {
+
+ tns = rtypenamespace.exec( types[t] ) || [];
+ type = tns[1];
+ namespaces = ( tns[2] || "" ).split( "." ).sort();
+
+ // If event changes its type, use the special event handlers for the changed type
+ special = jQuery.event.special[ type ] || {};
+
+ // If selector defined, determine special event api type, otherwise given type
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+
+ // Update special based on newly reset type
+ special = jQuery.event.special[ type ] || {};
+
+ // handleObj is passed to all event handlers
+ handleObj = jQuery.extend({
+ type: type,
+ origType: tns[1],
+ data: data,
+ handler: handler,
+ guid: handler.guid,
+ selector: selector,
+ quick: selector && quickParse( selector ),
+ namespace: namespaces.join(".")
+ }, handleObjIn );
+
+ // Init the event handler queue if we're the first
+ handlers = events[ type ];
+ if ( !handlers ) {
+ handlers = events[ type ] = [];
+ handlers.delegateCount = 0;
+
+ // Only use addEventListener/attachEvent if the special events handler returns false
+ if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+ // Bind the global event handler to the element
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, eventHandle, false );
+
+ } else if ( elem.attachEvent ) {
+ elem.attachEvent( "on" + type, eventHandle );
+ }
+ }
+ }
+
+ if ( special.add ) {
+ special.add.call( elem, handleObj );
+
+ if ( !handleObj.handler.guid ) {
+ handleObj.handler.guid = handler.guid;
+ }
+ }
+
+ // Add to the element's handler list, delegates in front
+ if ( selector ) {
+ handlers.splice( handlers.delegateCount++, 0, handleObj );
+ } else {
+ handlers.push( handleObj );
+ }
+
+ // Keep track of which events have ever been used, for event optimization
+ jQuery.event.global[ type ] = true;
+ }
+
+ // Nullify elem to prevent memory leaks in IE
+ elem = null;
+ },
+
+ global: {},
+
+ // Detach an event or set of events from an element
+ remove: function( elem, types, handler, selector, mappedTypes ) {
+
+ var elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
+ t, tns, type, origType, namespaces, origCount,
+ j, events, special, handle, eventType, handleObj;
+
+ if ( !elemData || !(events = elemData.events) ) {
+ return;
+ }
+
+ // Once for each type.namespace in types; type may be omitted
+ types = jQuery.trim( hoverHack( types || "" ) ).split(" ");
+ for ( t = 0; t < types.length; t++ ) {
+ tns = rtypenamespace.exec( types[t] ) || [];
+ type = origType = tns[1];
+ namespaces = tns[2];
+
+ // Unbind all events (on this namespace, if provided) for the element
+ if ( !type ) {
+ for ( type in events ) {
+ jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+ }
+ continue;
+ }
+
+ special = jQuery.event.special[ type ] || {};
+ type = ( selector? special.delegateType : special.bindType ) || type;
+ eventType = events[ type ] || [];
+ origCount = eventType.length;
+ namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
+
+ // Remove matching events
+ for ( j = 0; j < eventType.length; j++ ) {
+ handleObj = eventType[ j ];
+
+ if ( ( mappedTypes || origType === handleObj.origType ) &&
+ ( !handler || handler.guid === handleObj.guid ) &&
+ ( !namespaces || namespaces.test( handleObj.namespace ) ) &&
+ ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+ eventType.splice( j--, 1 );
+
+ if ( handleObj.selector ) {
+ eventType.delegateCount--;
+ }
+ if ( special.remove ) {
+ special.remove.call( elem, handleObj );
+ }
+ }
+ }
+
+ // Remove generic event handler if we removed something and no more handlers exist
+ // (avoids potential for endless recursion during removal of special event handlers)
+ if ( eventType.length === 0 && origCount !== eventType.length ) {
+ if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
+ jQuery.removeEvent( elem, type, elemData.handle );
+ }
+
+ delete events[ type ];
+ }
+ }
+
+ // Remove the expando if it's no longer used
+ if ( jQuery.isEmptyObject( events ) ) {
+ handle = elemData.handle;
+ if ( handle ) {
+ handle.elem = null;
+ }
+
+ // removeData also checks for emptiness and clears the expando if empty
+ // so use it instead of delete
+ jQuery.removeData( elem, [ "events", "handle" ], true );
+ }
+ },
+
+ // Events that are safe to short-circuit if no handlers are attached.
+ // Native DOM events should not be added, they may have inline handlers.
+ customEvent: {
+ "getData": true,
+ "setData": true,
+ "changeData": true
+ },
+
+ trigger: function( event, data, elem, onlyHandlers ) {
+ // Don't do events on text and comment nodes
+ if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {
+ return;
+ }
+
+ // Event object or event type
+ var type = event.type || event,
+ namespaces = [],
+ cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;
+
+ // focus/blur morphs to focusin/out; ensure we're not firing them right now
+ if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+ return;
+ }
+
+ if ( type.indexOf( "!" ) >= 0 ) {
+ // Exclusive events trigger only for the exact event (no namespaces)
+ type = type.slice(0, -1);
+ exclusive = true;
+ }
+
+ if ( type.indexOf( "." ) >= 0 ) {
+ // Namespaced trigger; create a regexp to match event type in handle()
+ namespaces = type.split(".");
+ type = namespaces.shift();
+ namespaces.sort();
+ }
+
+ if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
+ // No jQuery handlers for this event type, and it can't have inline handlers
+ return;
+ }
+
+ // Caller can pass in an Event, Object, or just an event type string
+ event = typeof event === "object" ?
+ // jQuery.Event object
+ event[ jQuery.expando ] ? event :
+ // Object literal
+ new jQuery.Event( type, event ) :
+ // Just the event type (string)
+ new jQuery.Event( type );
+
+ event.type = type;
+ event.isTrigger = true;
+ event.exclusive = exclusive;
+ event.namespace = namespaces.join( "." );
+ event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
+ ontype = type.indexOf( ":" ) < 0 ? "on" + type : "";
+
+ // Handle a global trigger
+ if ( !elem ) {
+
+ // TODO: Stop taunting the data cache; remove global events and always attach to document
+ cache = jQuery.cache;
+ for ( i in cache ) {
+ if ( cache[ i ].events && cache[ i ].events[ type ] ) {
+ jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );
+ }
+ }
+ return;
+ }
+
+ // Clean up the event in case it is being reused
+ event.result = undefined;
+ if ( !event.target ) {
+ event.target = elem;
+ }
+
+ // Clone any incoming data and prepend the event, creating the handler arg list
+ data = data != null ? jQuery.makeArray( data ) : [];
+ data.unshift( event );
+
+ // Allow special events to draw outside the lines
+ special = jQuery.event.special[ type ] || {};
+ if ( special.trigger && special.trigger.apply( elem, data ) === false ) {
+ return;
+ }
+
+ // Determine event propagation path in advance, per W3C events spec (#9951)
+ // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+ eventPath = [[ elem, special.bindType || type ]];
+ if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+ bubbleType = special.delegateType || type;
+ cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;
+ old = null;
+ for ( ; cur; cur = cur.parentNode ) {
+ eventPath.push([ cur, bubbleType ]);
+ old = cur;
+ }
+
+ // Only add window if we got to document (e.g., not plain obj or detached DOM)
+ if ( old && old === elem.ownerDocument ) {
+ eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);
+ }
+ }
+
+ // Fire handlers on the event path
+ for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {
+
+ cur = eventPath[i][0];
+ event.type = eventPath[i][1];
+
+ handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
+ if ( handle ) {
+ handle.apply( cur, data );
+ }
+ // Note that this is a bare JS function and not a jQuery handler
+ handle = ontype && cur[ ontype ];
+ if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {
+ event.preventDefault();
+ }
+ }
+ event.type = type;
+
+ // If nobody prevented the default action, do it now
+ if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+ if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
+ !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
+
+ // Call a native DOM method on the target with the same name name as the event.
+ // Can't use an .isFunction() check here because IE6/7 fails that test.
+ // Don't do default actions on window, that's where global variables be (#6170)
+ // IE<9 dies on focus/blur to hidden element (#1486)
+ if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {
+
+ // Don't re-trigger an onFOO event when we call its FOO() method
+ old = elem[ ontype ];
+
+ if ( old ) {
+ elem[ ontype ] = null;
+ }
+
+ // Prevent re-triggering of the same event, since we already bubbled it above
+ jQuery.event.triggered = type;
+ elem[ type ]();
+ jQuery.event.triggered = undefined;
+
+ if ( old ) {
+ elem[ ontype ] = old;
+ }
+ }
+ }
+ }
+
+ return event.result;
+ },
+
+ dispatch: function( event ) {
+
+ // Make a writable jQuery.Event from the native event object
+ event = jQuery.event.fix( event || window.event );
+
+ var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []),
+ delegateCount = handlers.delegateCount,
+ args = [].slice.call( arguments, 0 ),
+ run_all = !event.exclusive && !event.namespace,
+ special = jQuery.event.special[ event.type ] || {},
+ handlerQueue = [],
+ i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;
+
+ // Use the fix-ed jQuery.Event rather than the (read-only) native event
+ args[0] = event;
+ event.delegateTarget = this;
+
+ // Call the preDispatch hook for the mapped type, and let it bail if desired
+ if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
+ return;
+ }
+
+ // Determine handlers that should run if there are delegated events
+ // Avoid non-left-click bubbling in Firefox (#3861)
+ if ( delegateCount && !(event.button && event.type === "click") ) {
+
+ // Pregenerate a single jQuery object for reuse with .is()
+ jqcur = jQuery(this);
+ jqcur.context = this.ownerDocument || this;
+
+ for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {
+
+ // Don't process events on disabled elements (#6911, #8165)
+ if ( cur.disabled !== true ) {
+ selMatch = {};
+ matches = [];
+ jqcur[0] = cur;
+ for ( i = 0; i < delegateCount; i++ ) {
+ handleObj = handlers[ i ];
+ sel = handleObj.selector;
+
+ if ( selMatch[ sel ] === undefined ) {
+ selMatch[ sel ] = (
+ handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )
+ );
+ }
+ if ( selMatch[ sel ] ) {
+ matches.push( handleObj );
+ }
+ }
+ if ( matches.length ) {
+ handlerQueue.push({ elem: cur, matches: matches });
+ }
+ }
+ }
+ }
+
+ // Add the remaining (directly-bound) handlers
+ if ( handlers.length > delegateCount ) {
+ handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });
+ }
+
+ // Run delegates first; they may want to stop propagation beneath us
+ for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {
+ matched = handlerQueue[ i ];
+ event.currentTarget = matched.elem;
+
+ for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {
+ handleObj = matched.matches[ j ];
+
+ // Triggered event must either 1) be non-exclusive and have no namespace, or
+ // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
+ if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {
+
+ event.data = handleObj.data;
+ event.handleObj = handleObj;
+
+ ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
+ .apply( matched.elem, args );
+
+ if ( ret !== undefined ) {
+ event.result = ret;
+ if ( ret === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+ }
+ }
+ }
+
+ // Call the postDispatch hook for the mapped type
+ if ( special.postDispatch ) {
+ special.postDispatch.call( this, event );
+ }
+
+ return event.result;
+ },
+
+ // Includes some event props shared by KeyEvent and MouseEvent
+ // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 ***
+ props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
+
+ fixHooks: {},
+
+ keyHooks: {
+ props: "char charCode key keyCode".split(" "),
+ filter: function( event, original ) {
+
+ // Add which for key events
+ if ( event.which == null ) {
+ event.which = original.charCode != null ? original.charCode : original.keyCode;
+ }
+
+ return event;
+ }
+ },
+
+ mouseHooks: {
+ props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
+ filter: function( event, original ) {
+ var eventDoc, doc, body,
+ button = original.button,
+ fromElement = original.fromElement;
+
+ // Calculate pageX/Y if missing and clientX/Y available
+ if ( event.pageX == null && original.clientX != null ) {
+ eventDoc = event.target.ownerDocument || document;
+ doc = eventDoc.documentElement;
+ body = eventDoc.body;
+
+ event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
+ event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
+ }
+
+ // Add relatedTarget, if necessary
+ if ( !event.relatedTarget && fromElement ) {
+ event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
+ }
+
+ // Add which for click: 1 === left; 2 === middle; 3 === right
+ // Note: button is not normalized, so don't use it
+ if ( !event.which && button !== undefined ) {
+ event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+ }
+
+ return event;
+ }
+ },
+
+ fix: function( event ) {
+ if ( event[ jQuery.expando ] ) {
+ return event;
+ }
+
+ // Create a writable copy of the event object and normalize some properties
+ var i, prop,
+ originalEvent = event,
+ fixHook = jQuery.event.fixHooks[ event.type ] || {},
+ copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
+
+ event = jQuery.Event( originalEvent );
+
+ for ( i = copy.length; i; ) {
+ prop = copy[ --i ];
+ event[ prop ] = originalEvent[ prop ];
+ }
+
+ // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
+ if ( !event.target ) {
+ event.target = originalEvent.srcElement || document;
+ }
+
+ // Target should not be a text node (#504, Safari)
+ if ( event.target.nodeType === 3 ) {
+ event.target = event.target.parentNode;
+ }
+
+ // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)
+ if ( event.metaKey === undefined ) {
+ event.metaKey = event.ctrlKey;
+ }
+
+ return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
+ },
+
+ special: {
+ ready: {
+ // Make sure the ready event is setup
+ setup: jQuery.bindReady
+ },
+
+ load: {
+ // Prevent triggered image.load events from bubbling to window.load
+ noBubble: true
+ },
+
+ focus: {
+ delegateType: "focusin"
+ },
+ blur: {
+ delegateType: "focusout"
+ },
+
+ beforeunload: {
+ setup: function( data, namespaces, eventHandle ) {
+ // We only want to do this special case on windows
+ if ( jQuery.isWindow( this ) ) {
+ this.onbeforeunload = eventHandle;
+ }
+ },
+
+ teardown: function( namespaces, eventHandle ) {
+ if ( this.onbeforeunload === eventHandle ) {
+ this.onbeforeunload = null;
+ }
+ }
+ }
+ },
+
+ simulate: function( type, elem, event, bubble ) {
+ // Piggyback on a donor event to simulate a different one.
+ // Fake originalEvent to avoid donor's stopPropagation, but if the
+ // simulated event prevents default then we do the same on the donor.
+ var e = jQuery.extend(
+ new jQuery.Event(),
+ event,
+ { type: type,
+ isSimulated: true,
+ originalEvent: {}
+ }
+ );
+ if ( bubble ) {
+ jQuery.event.trigger( e, null, elem );
+ } else {
+ jQuery.event.dispatch.call( elem, e );
+ }
+ if ( e.isDefaultPrevented() ) {
+ event.preventDefault();
+ }
+ }
+};
+
+// Some plugins are using, but it's undocumented/deprecated and will be removed.
+// The 1.7 special event interface should provide all the hooks needed now.
+jQuery.event.handle = jQuery.event.dispatch;
+
+jQuery.removeEvent = document.removeEventListener ?
+ function( elem, type, handle ) {
+ if ( elem.removeEventListener ) {
+ elem.removeEventListener( type, handle, false );
+ }
+ } :
+ function( elem, type, handle ) {
+ if ( elem.detachEvent ) {
+ elem.detachEvent( "on" + type, handle );
+ }
+ };
+
+jQuery.Event = function( src, props ) {
+ // Allow instantiation without the 'new' keyword
+ if ( !(this instanceof jQuery.Event) ) {
+ return new jQuery.Event( src, props );
+ }
+
+ // Event object
+ if ( src && src.type ) {
+ this.originalEvent = src;
+ this.type = src.type;
+
+ // Events bubbling up the document may have been marked as prevented
+ // by a handler lower down the tree; reflect the correct value.
+ this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
+ src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
+
+ // Event type
+ } else {
+ this.type = src;
+ }
+
+ // Put explicitly provided properties onto the event object
+ if ( props ) {
+ jQuery.extend( this, props );
+ }
+
+ // Create a timestamp if incoming event doesn't have one
+ this.timeStamp = src && src.timeStamp || jQuery.now();
+
+ // Mark it as fixed
+ this[ jQuery.expando ] = true;
+};
+
+function returnFalse() {
+ return false;
+}
+function returnTrue() {
+ return true;
+}
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+ preventDefault: function() {
+ this.isDefaultPrevented = returnTrue;
+
+ var e = this.originalEvent;
+ if ( !e ) {
+ return;
+ }
+
+ // if preventDefault exists run it on the original event
+ if ( e.preventDefault ) {
+ e.preventDefault();
+
+ // otherwise set the returnValue property of the original event to false (IE)
+ } else {
+ e.returnValue = false;
+ }
+ },
+ stopPropagation: function() {
+ this.isPropagationStopped = returnTrue;
+
+ var e = this.originalEvent;
+ if ( !e ) {
+ return;
+ }
+ // if stopPropagation exists run it on the original event
+ if ( e.stopPropagation ) {
+ e.stopPropagation();
+ }
+ // otherwise set the cancelBubble property of the original event to true (IE)
+ e.cancelBubble = true;
+ },
+ stopImmediatePropagation: function() {
+ this.isImmediatePropagationStopped = returnTrue;
+ this.stopPropagation();
+ },
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse
+};
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+jQuery.each({
+ mouseenter: "mouseover",
+ mouseleave: "mouseout"
+}, function( orig, fix ) {
+ jQuery.event.special[ orig ] = {
+ delegateType: fix,
+ bindType: fix,
+
+ handle: function( event ) {
+ var target = this,
+ related = event.relatedTarget,
+ handleObj = event.handleObj,
+ selector = handleObj.selector,
+ ret;
+
+ // For mousenter/leave call the handler if related is outside the target.
+ // NB: No relatedTarget if the mouse left/entered the browser window
+ if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
+ event.type = handleObj.origType;
+ ret = handleObj.handler.apply( this, arguments );
+ event.type = fix;
+ }
+ return ret;
+ }
+ };
+});
+
+// IE submit delegation
+if ( !jQuery.support.submitBubbles ) {
+
+ jQuery.event.special.submit = {
+ setup: function() {
+ // Only need this for delegated form submit events
+ if ( jQuery.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Lazy-add a submit handler when a descendant form may potentially be submitted
+ jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
+ // Node name check avoids a VML-related crash in IE (#9807)
+ var elem = e.target,
+ form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
+ if ( form && !form._submit_attached ) {
+ jQuery.event.add( form, "submit._submit", function( event ) {
+ event._submit_bubble = true;
+ });
+ form._submit_attached = true;
+ }
+ });
+ // return undefined since we don't need an event listener
+ },
+
+ postDispatch: function( event ) {
+ // If form was submitted by the user, bubble the event up the tree
+ if ( event._submit_bubble ) {
+ delete event._submit_bubble;
+ if ( this.parentNode && !event.isTrigger ) {
+ jQuery.event.simulate( "submit", this.parentNode, event, true );
+ }
+ }
+ },
+
+ teardown: function() {
+ // Only need this for delegated form submit events
+ if ( jQuery.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
+ jQuery.event.remove( this, "._submit" );
+ }
+ };
+}
+
+// IE change delegation and checkbox/radio fix
+if ( !jQuery.support.changeBubbles ) {
+
+ jQuery.event.special.change = {
+
+ setup: function() {
+
+ if ( rformElems.test( this.nodeName ) ) {
+ // IE doesn't fire change on a check/radio until blur; trigger it on click
+ // after a propertychange. Eat the blur-change in special.change.handle.
+ // This still fires onchange a second time for check/radio after blur.
+ if ( this.type === "checkbox" || this.type === "radio" ) {
+ jQuery.event.add( this, "propertychange._change", function( event ) {
+ if ( event.originalEvent.propertyName === "checked" ) {
+ this._just_changed = true;
+ }
+ });
+ jQuery.event.add( this, "click._change", function( event ) {
+ if ( this._just_changed && !event.isTrigger ) {
+ this._just_changed = false;
+ jQuery.event.simulate( "change", this, event, true );
+ }
+ });
+ }
+ return false;
+ }
+ // Delegated event; lazy-add a change handler on descendant inputs
+ jQuery.event.add( this, "beforeactivate._change", function( e ) {
+ var elem = e.target;
+
+ if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {
+ jQuery.event.add( elem, "change._change", function( event ) {
+ if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
+ jQuery.event.simulate( "change", this.parentNode, event, true );
+ }
+ });
+ elem._change_attached = true;
+ }
+ });
+ },
+
+ handle: function( event ) {
+ var elem = event.target;
+
+ // Swallow native change events from checkbox/radio, we already triggered them above
+ if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
+ return event.handleObj.handler.apply( this, arguments );
+ }
+ },
+
+ teardown: function() {
+ jQuery.event.remove( this, "._change" );
+
+ return rformElems.test( this.nodeName );
+ }
+ };
+}
+
+// Create "bubbling" focus and blur events
+if ( !jQuery.support.focusinBubbles ) {
+ jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+ // Attach a single capturing handler while someone wants focusin/focusout
+ var attaches = 0,
+ handler = function( event ) {
+ jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
+ };
+
+ jQuery.event.special[ fix ] = {
+ setup: function() {
+ if ( attaches++ === 0 ) {
+ document.addEventListener( orig, handler, true );
+ }
+ },
+ teardown: function() {
+ if ( --attaches === 0 ) {
+ document.removeEventListener( orig, handler, true );
+ }
+ }
+ };
+ });
+}
+
+jQuery.fn.extend({
+
+ on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
+ var origFn, type;
+
+ // Types can be a map of types/handlers
+ if ( typeof types === "object" ) {
+ // ( types-Object, selector, data )
+ if ( typeof selector !== "string" ) { // && selector != null
+ // ( types-Object, data )
+ data = data || selector;
+ selector = undefined;
+ }
+ for ( type in types ) {
+ this.on( type, selector, data, types[ type ], one );
+ }
+ return this;
+ }
+
+ if ( data == null && fn == null ) {
+ // ( types, fn )
+ fn = selector;
+ data = selector = undefined;
+ } else if ( fn == null ) {
+ if ( typeof selector === "string" ) {
+ // ( types, selector, fn )
+ fn = data;
+ data = undefined;
+ } else {
+ // ( types, data, fn )
+ fn = data;
+ data = selector;
+ selector = undefined;
+ }
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ } else if ( !fn ) {
+ return this;
+ }
+
+ if ( one === 1 ) {
+ origFn = fn;
+ fn = function( event ) {
+ // Can use an empty set, since event contains the info
+ jQuery().off( event );
+ return origFn.apply( this, arguments );
+ };
+ // Use same guid so caller can remove using origFn
+ fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+ }
+ return this.each( function() {
+ jQuery.event.add( this, types, fn, data, selector );
+ });
+ },
+ one: function( types, selector, data, fn ) {
+ return this.on( types, selector, data, fn, 1 );
+ },
+ off: function( types, selector, fn ) {
+ if ( types && types.preventDefault && types.handleObj ) {
+ // ( event ) dispatched jQuery.Event
+ var handleObj = types.handleObj;
+ jQuery( types.delegateTarget ).off(
+ handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
+ handleObj.selector,
+ handleObj.handler
+ );
+ return this;
+ }
+ if ( typeof types === "object" ) {
+ // ( types-object [, selector] )
+ for ( var type in types ) {
+ this.off( type, selector, types[ type ] );
+ }
+ return this;
+ }
+ if ( selector === false || typeof selector === "function" ) {
+ // ( types [, fn] )
+ fn = selector;
+ selector = undefined;
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ }
+ return this.each(function() {
+ jQuery.event.remove( this, types, fn, selector );
+ });
+ },
+
+ bind: function( types, data, fn ) {
+ return this.on( types, null, data, fn );
+ },
+ unbind: function( types, fn ) {
+ return this.off( types, null, fn );
+ },
+
+ live: function( types, data, fn ) {
+ jQuery( this.context ).on( types, this.selector, data, fn );
+ return this;
+ },
+ die: function( types, fn ) {
+ jQuery( this.context ).off( types, this.selector || "**", fn );
+ return this;
+ },
+
+ delegate: function( selector, types, data, fn ) {
+ return this.on( types, selector, data, fn );
+ },
+ undelegate: function( selector, types, fn ) {
+ // ( namespace ) or ( selector, types [, fn] )
+ return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn );
+ },
+
+ trigger: function( type, data ) {
+ return this.each(function() {
+ jQuery.event.trigger( type, data, this );
+ });
+ },
+ triggerHandler: function( type, data ) {
+ if ( this[0] ) {
+ return jQuery.event.trigger( type, data, this[0], true );
+ }
+ },
+
+ toggle: function( fn ) {
+ // Save reference to arguments for access in closure
+ var args = arguments,
+ guid = fn.guid || jQuery.guid++,
+ i = 0,
+ toggler = function( event ) {
+ // Figure out which function to execute
+ var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
+ jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
+
+ // Make sure that clicks stop
+ event.preventDefault();
+
+ // and execute the function
+ return args[ lastToggle ].apply( this, arguments ) || false;
+ };
+
+ // link all the functions, so any of them can unbind this click handler
+ toggler.guid = guid;
+ while ( i < args.length ) {
+ args[ i++ ].guid = guid;
+ }
+
+ return this.click( toggler );
+ },
+
+ hover: function( fnOver, fnOut ) {
+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+ }
+});
+
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+ "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
+
+ // Handle event binding
+ jQuery.fn[ name ] = function( data, fn ) {
+ if ( fn == null ) {
+ fn = data;
+ data = null;
+ }
+
+ return arguments.length > 0 ?
+ this.on( name, null, data, fn ) :
+ this.trigger( name );
+ };
+
+ if ( jQuery.attrFn ) {
+ jQuery.attrFn[ name ] = true;
+ }
+
+ if ( rkeyEvent.test( name ) ) {
+ jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
+ }
+
+ if ( rmouseEvent.test( name ) ) {
+ jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
+ }
+});
+
+
+
+/*!
+ * Sizzle CSS Selector Engine
+ * Copyright 2011, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ * More information: http://sizzlejs.com/
+ */
+(function(){
+
+var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
+ expando = "sizcache" + (Math.random() + '').replace('.', ''),
+ done = 0,
+ toString = Object.prototype.toString,
+ hasDuplicate = false,
+ baseHasDuplicate = true,
+ rBackslash = /\\/g,
+ rReturn = /\r\n/g,
+ rNonWord = /\W/;
+
+// Here we check if the JavaScript engine is using some sort of
+// optimization where it does not always call our comparision
+// function. If that is the case, discard the hasDuplicate value.
+// Thus far that includes Google Chrome.
+[0, 0].sort(function() {
+ baseHasDuplicate = false;
+ return 0;
+});
+
+var Sizzle = function( selector, context, results, seed ) {
+ results = results || [];
+ context = context || document;
+
+ var origContext = context;
+
+ if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
+ return [];
+ }
+
+ if ( !selector || typeof selector !== "string" ) {
+ return results;
+ }
+
+ var m, set, checkSet, extra, ret, cur, pop, i,
+ prune = true,
+ contextXML = Sizzle.isXML( context ),
+ parts = [],
+ soFar = selector;
+
+ // Reset the position of the chunker regexp (start from head)
+ do {
+ chunker.exec( "" );
+ m = chunker.exec( soFar );
+
+ if ( m ) {
+ soFar = m[3];
+
+ parts.push( m[1] );
+
+ if ( m[2] ) {
+ extra = m[3];
+ break;
+ }
+ }
+ } while ( m );
+
+ if ( parts.length > 1 && origPOS.exec( selector ) ) {
+
+ if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
+ set = posProcess( parts[0] + parts[1], context, seed );
+
+ } else {
+ set = Expr.relative[ parts[0] ] ?
+ [ context ] :
+ Sizzle( parts.shift(), context );
+
+ while ( parts.length ) {
+ selector = parts.shift();
+
+ if ( Expr.relative[ selector ] ) {
+ selector += parts.shift();
+ }
+
+ set = posProcess( selector, set, seed );
+ }
+ }
+
+ } else {
+ // Take a shortcut and set the context if the root selector is an ID
+ // (but not if it'll be faster if the inner selector is an ID)
+ if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
+ Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
+
+ ret = Sizzle.find( parts.shift(), context, contextXML );
+ context = ret.expr ?
+ Sizzle.filter( ret.expr, ret.set )[0] :
+ ret.set[0];
+ }
+
+ if ( context ) {
+ ret = seed ?
+ { expr: parts.pop(), set: makeArray(seed) } :
+ Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
+
+ set = ret.expr ?
+ Sizzle.filter( ret.expr, ret.set ) :
+ ret.set;
+
+ if ( parts.length > 0 ) {
+ checkSet = makeArray( set );
+
+ } else {
+ prune = false;
+ }
+
+ while ( parts.length ) {
+ cur = parts.pop();
+ pop = cur;
+
+ if ( !Expr.relative[ cur ] ) {
+ cur = "";
+ } else {
+ pop = parts.pop();
+ }
+
+ if ( pop == null ) {
+ pop = context;
+ }
+
+ Expr.relative[ cur ]( checkSet, pop, contextXML );
+ }
+
+ } else {
+ checkSet = parts = [];
+ }
+ }
+
+ if ( !checkSet ) {
+ checkSet = set;
+ }
+
+ if ( !checkSet ) {
+ Sizzle.error( cur || selector );
+ }
+
+ if ( toString.call(checkSet) === "[object Array]" ) {
+ if ( !prune ) {
+ results.push.apply( results, checkSet );
+
+ } else if ( context && context.nodeType === 1 ) {
+ for ( i = 0; checkSet[i] != null; i++ ) {
+ if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
+ results.push( set[i] );
+ }
+ }
+
+ } else {
+ for ( i = 0; checkSet[i] != null; i++ ) {
+ if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
+ results.push( set[i] );
+ }
+ }
+ }
+
+ } else {
+ makeArray( checkSet, results );
+ }
+
+ if ( extra ) {
+ Sizzle( extra, origContext, results, seed );
+ Sizzle.uniqueSort( results );
+ }
+
+ return results;
+};
+
+Sizzle.uniqueSort = function( results ) {
+ if ( sortOrder ) {
+ hasDuplicate = baseHasDuplicate;
+ results.sort( sortOrder );
+
+ if ( hasDuplicate ) {
+ for ( var i = 1; i < results.length; i++ ) {
+ if ( results[i] === results[ i - 1 ] ) {
+ results.splice( i--, 1 );
+ }
+ }
+ }
+ }
+
+ return results;
+};
+
+Sizzle.matches = function( expr, set ) {
+ return Sizzle( expr, null, null, set );
+};
+
+Sizzle.matchesSelector = function( node, expr ) {
+ return Sizzle( expr, null, null, [node] ).length > 0;
+};
+
+Sizzle.find = function( expr, context, isXML ) {
+ var set, i, len, match, type, left;
+
+ if ( !expr ) {
+ return [];
+ }
+
+ for ( i = 0, len = Expr.order.length; i < len; i++ ) {
+ type = Expr.order[i];
+
+ if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
+ left = match[1];
+ match.splice( 1, 1 );
+
+ if ( left.substr( left.length - 1 ) !== "\\" ) {
+ match[1] = (match[1] || "").replace( rBackslash, "" );
+ set = Expr.find[ type ]( match, context, isXML );
+
+ if ( set != null ) {
+ expr = expr.replace( Expr.match[ type ], "" );
+ break;
+ }
+ }
+ }
+ }
+
+ if ( !set ) {
+ set = typeof context.getElementsByTagName !== "undefined" ?
+ context.getElementsByTagName( "*" ) :
+ [];
+ }
+
+ return { set: set, expr: expr };
+};
+
+Sizzle.filter = function( expr, set, inplace, not ) {
+ var match, anyFound,
+ type, found, item, filter, left,
+ i, pass,
+ old = expr,
+ result = [],
+ curLoop = set,
+ isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
+
+ while ( expr && set.length ) {
+ for ( type in Expr.filter ) {
+ if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
+ filter = Expr.filter[ type ];
+ left = match[1];
+
+ anyFound = false;
+
+ match.splice(1,1);
+
+ if ( left.substr( left.length - 1 ) === "\\" ) {
+ continue;
+ }
+
+ if ( curLoop === result ) {
+ result = [];
+ }
+
+ if ( Expr.preFilter[ type ] ) {
+ match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
+
+ if ( !match ) {
+ anyFound = found = true;
+
+ } else if ( match === true ) {
+ continue;
+ }
+ }
+
+ if ( match ) {
+ for ( i = 0; (item = curLoop[i]) != null; i++ ) {
+ if ( item ) {
+ found = filter( item, match, i, curLoop );
+ pass = not ^ found;
+
+ if ( inplace && found != null ) {
+ if ( pass ) {
+ anyFound = true;
+
+ } else {
+ curLoop[i] = false;
+ }
+
+ } else if ( pass ) {
+ result.push( item );
+ anyFound = true;
+ }
+ }
+ }
+ }
+
+ if ( found !== undefined ) {
+ if ( !inplace ) {
+ curLoop = result;
+ }
+
+ expr = expr.replace( Expr.match[ type ], "" );
+
+ if ( !anyFound ) {
+ return [];
+ }
+
+ break;
+ }
+ }
+ }
+
+ // Improper expression
+ if ( expr === old ) {
+ if ( anyFound == null ) {
+ Sizzle.error( expr );
+
+ } else {
+ break;
+ }
+ }
+
+ old = expr;
+ }
+
+ return curLoop;
+};
+
+Sizzle.error = function( msg ) {
+ throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
+
+/**
+ * Utility function for retreiving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+var getText = Sizzle.getText = function( elem ) {
+ var i, node,
+ nodeType = elem.nodeType,
+ ret = "";
+
+ if ( nodeType ) {
+ if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+ // Use textContent || innerText for elements
+ if ( typeof elem.textContent === 'string' ) {
+ return elem.textContent;
+ } else if ( typeof elem.innerText === 'string' ) {
+ // Replace IE's carriage returns
+ return elem.innerText.replace( rReturn, '' );
+ } else {
+ // Traverse it's children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling) {
+ ret += getText( elem );
+ }
+ }
+ } else if ( nodeType === 3 || nodeType === 4 ) {
+ return elem.nodeValue;
+ }
+ } else {
+
+ // If no nodeType, this is expected to be an array
+ for ( i = 0; (node = elem[i]); i++ ) {
+ // Do not traverse comment nodes
+ if ( node.nodeType !== 8 ) {
+ ret += getText( node );
+ }
+ }
+ }
+ return ret;
+};
+
+var Expr = Sizzle.selectors = {
+ order: [ "ID", "NAME", "TAG" ],
+
+ match: {
+ ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
+ CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
+ NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
+ ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
+ TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
+ CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
+ POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
+ PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
+ },
+
+ leftMatch: {},
+
+ attrMap: {
+ "class": "className",
+ "for": "htmlFor"
+ },
+
+ attrHandle: {
+ href: function( elem ) {
+ return elem.getAttribute( "href" );
+ },
+ type: function( elem ) {
+ return elem.getAttribute( "type" );
+ }
+ },
+
+ relative: {
+ "+": function(checkSet, part){
+ var isPartStr = typeof part === "string",
+ isTag = isPartStr && !rNonWord.test( part ),
+ isPartStrNotTag = isPartStr && !isTag;
+
+ if ( isTag ) {
+ part = part.toLowerCase();
+ }
+
+ for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
+ if ( (elem = checkSet[i]) ) {
+ while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
+
+ checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
+ elem || false :
+ elem === part;
+ }
+ }
+
+ if ( isPartStrNotTag ) {
+ Sizzle.filter( part, checkSet, true );
+ }
+ },
+
+ ">": function( checkSet, part ) {
+ var elem,
+ isPartStr = typeof part === "string",
+ i = 0,
+ l = checkSet.length;
+
+ if ( isPartStr && !rNonWord.test( part ) ) {
+ part = part.toLowerCase();
+
+ for ( ; i < l; i++ ) {
+ elem = checkSet[i];
+
+ if ( elem ) {
+ var parent = elem.parentNode;
+ checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
+ }
+ }
+
+ } else {
+ for ( ; i < l; i++ ) {
+ elem = checkSet[i];
+
+ if ( elem ) {
+ checkSet[i] = isPartStr ?
+ elem.parentNode :
+ elem.parentNode === part;
+ }
+ }
+
+ if ( isPartStr ) {
+ Sizzle.filter( part, checkSet, true );
+ }
+ }
+ },
+
+ "": function(checkSet, part, isXML){
+ var nodeCheck,
+ doneName = done++,
+ checkFn = dirCheck;
+
+ if ( typeof part === "string" && !rNonWord.test( part ) ) {
+ part = part.toLowerCase();
+ nodeCheck = part;
+ checkFn = dirNodeCheck;
+ }
+
+ checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
+ },
+
+ "~": function( checkSet, part, isXML ) {
+ var nodeCheck,
+ doneName = done++,
+ checkFn = dirCheck;
+
+ if ( typeof part === "string" && !rNonWord.test( part ) ) {
+ part = part.toLowerCase();
+ nodeCheck = part;
+ checkFn = dirNodeCheck;
+ }
+
+ checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
+ }
+ },
+
+ find: {
+ ID: function( match, context, isXML ) {
+ if ( typeof context.getElementById !== "undefined" && !isXML ) {
+ var m = context.getElementById(match[1]);
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ return m && m.parentNode ? [m] : [];
+ }
+ },
+
+ NAME: function( match, context ) {
+ if ( typeof context.getElementsByName !== "undefined" ) {
+ var ret = [],
+ results = context.getElementsByName( match[1] );
+
+ for ( var i = 0, l = results.length; i < l; i++ ) {
+ if ( results[i].getAttribute("name") === match[1] ) {
+ ret.push( results[i] );
+ }
+ }
+
+ return ret.length === 0 ? null : ret;
+ }
+ },
+
+ TAG: function( match, context ) {
+ if ( typeof context.getElementsByTagName !== "undefined" ) {
+ return context.getElementsByTagName( match[1] );
+ }
+ }
+ },
+ preFilter: {
+ CLASS: function( match, curLoop, inplace, result, not, isXML ) {
+ match = " " + match[1].replace( rBackslash, "" ) + " ";
+
+ if ( isXML ) {
+ return match;
+ }
+
+ for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
+ if ( elem ) {
+ if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) {
+ if ( !inplace ) {
+ result.push( elem );
+ }
+
+ } else if ( inplace ) {
+ curLoop[i] = false;
+ }
+ }
+ }
+
+ return false;
+ },
+
+ ID: function( match ) {
+ return match[1].replace( rBackslash, "" );
+ },
+
+ TAG: function( match, curLoop ) {
+ return match[1].replace( rBackslash, "" ).toLowerCase();
+ },
+
+ CHILD: function( match ) {
+ if ( match[1] === "nth" ) {
+ if ( !match[2] ) {
+ Sizzle.error( match[0] );
+ }
+
+ match[2] = match[2].replace(/^\+|\s*/g, '');
+
+ // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+ var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
+ match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
+ !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
+
+ // calculate the numbers (first)n+(last) including if they are negative
+ match[2] = (test[1] + (test[2] || 1)) - 0;
+ match[3] = test[3] - 0;
+ }
+ else if ( match[2] ) {
+ Sizzle.error( match[0] );
+ }
+
+ // TODO: Move to normal caching system
+ match[0] = done++;
+
+ return match;
+ },
+
+ ATTR: function( match, curLoop, inplace, result, not, isXML ) {
+ var name = match[1] = match[1].replace( rBackslash, "" );
+
+ if ( !isXML && Expr.attrMap[name] ) {
+ match[1] = Expr.attrMap[name];
+ }
+
+ // Handle if an un-quoted value was used
+ match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" );
+
+ if ( match[2] === "~=" ) {
+ match[4] = " " + match[4] + " ";
+ }
+
+ return match;
+ },
+
+ PSEUDO: function( match, curLoop, inplace, result, not ) {
+ if ( match[1] === "not" ) {
+ // If we're dealing with a complex expression, or a simple one
+ if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
+ match[3] = Sizzle(match[3], null, null, curLoop);
+
+ } else {
+ var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
+
+ if ( !inplace ) {
+ result.push.apply( result, ret );
+ }
+
+ return false;
+ }
+
+ } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
+ return true;
+ }
+
+ return match;
+ },
+
+ POS: function( match ) {
+ match.unshift( true );
+
+ return match;
+ }
+ },
+
+ filters: {
+ enabled: function( elem ) {
+ return elem.disabled === false && elem.type !== "hidden";
+ },
+
+ disabled: function( elem ) {
+ return elem.disabled === true;
+ },
+
+ checked: function( elem ) {
+ return elem.checked === true;
+ },
+
+ selected: function( elem ) {
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ if ( elem.parentNode ) {
+ elem.parentNode.selectedIndex;
+ }
+
+ return elem.selected === true;
+ },
+
+ parent: function( elem ) {
+ return !!elem.firstChild;
+ },
+
+ empty: function( elem ) {
+ return !elem.firstChild;
+ },
+
+ has: function( elem, i, match ) {
+ return !!Sizzle( match[3], elem ).length;
+ },
+
+ header: function( elem ) {
+ return (/h\d/i).test( elem.nodeName );
+ },
+
+ text: function( elem ) {
+ var attr = elem.getAttribute( "type" ), type = elem.type;
+ // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
+ // use getAttribute instead to test this case
+ return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null );
+ },
+
+ radio: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type;
+ },
+
+ checkbox: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type;
+ },
+
+ file: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "file" === elem.type;
+ },
+
+ password: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "password" === elem.type;
+ },
+
+ submit: function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && "submit" === elem.type;
+ },
+
+ image: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "image" === elem.type;
+ },
+
+ reset: function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && "reset" === elem.type;
+ },
+
+ button: function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && "button" === elem.type || name === "button";
+ },
+
+ input: function( elem ) {
+ return (/input|select|textarea|button/i).test( elem.nodeName );
+ },
+
+ focus: function( elem ) {
+ return elem === elem.ownerDocument.activeElement;
+ }
+ },
+ setFilters: {
+ first: function( elem, i ) {
+ return i === 0;
+ },
+
+ last: function( elem, i, match, array ) {
+ return i === array.length - 1;
+ },
+
+ even: function( elem, i ) {
+ return i % 2 === 0;
+ },
+
+ odd: function( elem, i ) {
+ return i % 2 === 1;
+ },
+
+ lt: function( elem, i, match ) {
+ return i < match[3] - 0;
+ },
+
+ gt: function( elem, i, match ) {
+ return i > match[3] - 0;
+ },
+
+ nth: function( elem, i, match ) {
+ return match[3] - 0 === i;
+ },
+
+ eq: function( elem, i, match ) {
+ return match[3] - 0 === i;
+ }
+ },
+ filter: {
+ PSEUDO: function( elem, match, i, array ) {
+ var name = match[1],
+ filter = Expr.filters[ name ];
+
+ if ( filter ) {
+ return filter( elem, i, match, array );
+
+ } else if ( name === "contains" ) {
+ return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;
+
+ } else if ( name === "not" ) {
+ var not = match[3];
+
+ for ( var j = 0, l = not.length; j < l; j++ ) {
+ if ( not[j] === elem ) {
+ return false;
+ }
+ }
+
+ return true;
+
+ } else {
+ Sizzle.error( name );
+ }
+ },
+
+ CHILD: function( elem, match ) {
+ var first, last,
+ doneName, parent, cache,
+ count, diff,
+ type = match[1],
+ node = elem;
+
+ switch ( type ) {
+ case "only":
+ case "first":
+ while ( (node = node.previousSibling) ) {
+ if ( node.nodeType === 1 ) {
+ return false;
+ }
+ }
+
+ if ( type === "first" ) {
+ return true;
+ }
+
+ node = elem;
+
+ /* falls through */
+ case "last":
+ while ( (node = node.nextSibling) ) {
+ if ( node.nodeType === 1 ) {
+ return false;
+ }
+ }
+
+ return true;
+
+ case "nth":
+ first = match[2];
+ last = match[3];
+
+ if ( first === 1 && last === 0 ) {
+ return true;
+ }
+
+ doneName = match[0];
+ parent = elem.parentNode;
+
+ if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {
+ count = 0;
+
+ for ( node = parent.firstChild; node; node = node.nextSibling ) {
+ if ( node.nodeType === 1 ) {
+ node.nodeIndex = ++count;
+ }
+ }
+
+ parent[ expando ] = doneName;
+ }
+
+ diff = elem.nodeIndex - last;
+
+ if ( first === 0 ) {
+ return diff === 0;
+
+ } else {
+ return ( diff % first === 0 && diff / first >= 0 );
+ }
+ }
+ },
+
+ ID: function( elem, match ) {
+ return elem.nodeType === 1 && elem.getAttribute("id") === match;
+ },
+
+ TAG: function( elem, match ) {
+ return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;
+ },
+
+ CLASS: function( elem, match ) {
+ return (" " + (elem.className || elem.getAttribute("class")) + " ")
+ .indexOf( match ) > -1;
+ },
+
+ ATTR: function( elem, match ) {
+ var name = match[1],
+ result = Sizzle.attr ?
+ Sizzle.attr( elem, name ) :
+ Expr.attrHandle[ name ] ?
+ Expr.attrHandle[ name ]( elem ) :
+ elem[ name ] != null ?
+ elem[ name ] :
+ elem.getAttribute( name ),
+ value = result + "",
+ type = match[2],
+ check = match[4];
+
+ return result == null ?
+ type === "!=" :
+ !type && Sizzle.attr ?
+ result != null :
+ type === "=" ?
+ value === check :
+ type === "*=" ?
+ value.indexOf(check) >= 0 :
+ type === "~=" ?
+ (" " + value + " ").indexOf(check) >= 0 :
+ !check ?
+ value && result !== false :
+ type === "!=" ?
+ value !== check :
+ type === "^=" ?
+ value.indexOf(check) === 0 :
+ type === "$=" ?
+ value.substr(value.length - check.length) === check :
+ type === "|=" ?
+ value === check || value.substr(0, check.length + 1) === check + "-" :
+ false;
+ },
+
+ POS: function( elem, match, i, array ) {
+ var name = match[2],
+ filter = Expr.setFilters[ name ];
+
+ if ( filter ) {
+ return filter( elem, i, match, array );
+ }
+ }
+ }
+};
+
+var origPOS = Expr.match.POS,
+ fescape = function(all, num){
+ return "\\" + (num - 0 + 1);
+ };
+
+for ( var type in Expr.match ) {
+ Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
+ Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
+}
+// Expose origPOS
+// "global" as in regardless of relation to brackets/parens
+Expr.match.globalPOS = origPOS;
+
+var makeArray = function( array, results ) {
+ array = Array.prototype.slice.call( array, 0 );
+
+ if ( results ) {
+ results.push.apply( results, array );
+ return results;
+ }
+
+ return array;
+};
+
+// Perform a simple check to determine if the browser is capable of
+// converting a NodeList to an array using builtin methods.
+// Also verifies that the returned array holds DOM nodes
+// (which is not the case in the Blackberry browser)
+try {
+ Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
+
+// Provide a fallback method if it does not work
+} catch( e ) {
+ makeArray = function( array, results ) {
+ var i = 0,
+ ret = results || [];
+
+ if ( toString.call(array) === "[object Array]" ) {
+ Array.prototype.push.apply( ret, array );
+
+ } else {
+ if ( typeof array.length === "number" ) {
+ for ( var l = array.length; i < l; i++ ) {
+ ret.push( array[i] );
+ }
+
+ } else {
+ for ( ; array[i]; i++ ) {
+ ret.push( array[i] );
+ }
+ }
+ }
+
+ return ret;
+ };
+}
+
+var sortOrder, siblingCheck;
+
+if ( document.documentElement.compareDocumentPosition ) {
+ sortOrder = function( a, b ) {
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
+ return a.compareDocumentPosition ? -1 : 1;
+ }
+
+ return a.compareDocumentPosition(b) & 4 ? -1 : 1;
+ };
+
+} else {
+ sortOrder = function( a, b ) {
+ // The nodes are identical, we can exit early
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+
+ // Fallback to using sourceIndex (in IE) if it's available on both nodes
+ } else if ( a.sourceIndex && b.sourceIndex ) {
+ return a.sourceIndex - b.sourceIndex;
+ }
+
+ var al, bl,
+ ap = [],
+ bp = [],
+ aup = a.parentNode,
+ bup = b.parentNode,
+ cur = aup;
+
+ // If the nodes are siblings (or identical) we can do a quick check
+ if ( aup === bup ) {
+ return siblingCheck( a, b );
+
+ // If no parents were found then the nodes are disconnected
+ } else if ( !aup ) {
+ return -1;
+
+ } else if ( !bup ) {
+ return 1;
+ }
+
+ // Otherwise they're somewhere else in the tree so we need
+ // to build up a full list of the parentNodes for comparison
+ while ( cur ) {
+ ap.unshift( cur );
+ cur = cur.parentNode;
+ }
+
+ cur = bup;
+
+ while ( cur ) {
+ bp.unshift( cur );
+ cur = cur.parentNode;
+ }
+
+ al = ap.length;
+ bl = bp.length;
+
+ // Start walking down the tree looking for a discrepancy
+ for ( var i = 0; i < al && i < bl; i++ ) {
+ if ( ap[i] !== bp[i] ) {
+ return siblingCheck( ap[i], bp[i] );
+ }
+ }
+
+ // We ended someplace up the tree so do a sibling check
+ return i === al ?
+ siblingCheck( a, bp[i], -1 ) :
+ siblingCheck( ap[i], b, 1 );
+ };
+
+ siblingCheck = function( a, b, ret ) {
+ if ( a === b ) {
+ return ret;
+ }
+
+ var cur = a.nextSibling;
+
+ while ( cur ) {
+ if ( cur === b ) {
+ return -1;
+ }
+
+ cur = cur.nextSibling;
+ }
+
+ return 1;
+ };
+}
+
+// Check to see if the browser returns elements by name when
+// querying by getElementById (and provide a workaround)
+(function(){
+ // We're going to inject a fake input element with a specified name
+ var form = document.createElement("div"),
+ id = "script" + (new Date()).getTime(),
+ root = document.documentElement;
+
+ form.innerHTML = "<a name='" + id + "'/>";
+
+ // Inject it into the root element, check its status, and remove it quickly
+ root.insertBefore( form, root.firstChild );
+
+ // The workaround has to do additional checks after a getElementById
+ // Which slows things down for other browsers (hence the branching)
+ if ( document.getElementById( id ) ) {
+ Expr.find.ID = function( match, context, isXML ) {
+ if ( typeof context.getElementById !== "undefined" && !isXML ) {
+ var m = context.getElementById(match[1]);
+
+ return m ?
+ m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
+ [m] :
+ undefined :
+ [];
+ }
+ };
+
+ Expr.filter.ID = function( elem, match ) {
+ var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
+
+ return elem.nodeType === 1 && node && node.nodeValue === match;
+ };
+ }
+
+ root.removeChild( form );
+
+ // release memory in IE
+ root = form = null;
+})();
+
+(function(){
+ // Check to see if the browser returns only elements
+ // when doing getElementsByTagName("*")
+
+ // Create a fake element
+ var div = document.createElement("div");
+ div.appendChild( document.createComment("") );
+
+ // Make sure no comments are found
+ if ( div.getElementsByTagName("*").length > 0 ) {
+ Expr.find.TAG = function( match, context ) {
+ var results = context.getElementsByTagName( match[1] );
+
+ // Filter out possible comments
+ if ( match[1] === "*" ) {
+ var tmp = [];
+
+ for ( var i = 0; results[i]; i++ ) {
+ if ( results[i].nodeType === 1 ) {
+ tmp.push( results[i] );
+ }
+ }
+
+ results = tmp;
+ }
+
+ return results;
+ };
+ }
+
+ // Check to see if an attribute returns normalized href attributes
+ div.innerHTML = "<a href='#'></a>";
+
+ if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
+ div.firstChild.getAttribute("href") !== "#" ) {
+
+ Expr.attrHandle.href = function( elem ) {
+ return elem.getAttribute( "href", 2 );
+ };
+ }
+
+ // release memory in IE
+ div = null;
+})();
+
+if ( document.querySelectorAll ) {
+ (function(){
+ var oldSizzle = Sizzle,
+ div = document.createElement("div"),
+ id = "__sizzle__";
+
+ div.innerHTML = "<p class='TEST'></p>";
+
+ // Safari can't handle uppercase or unicode characters when
+ // in quirks mode.
+ if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
+ return;
+ }
+
+ Sizzle = function( query, context, extra, seed ) {
+ context = context || document;
+
+ // Only use querySelectorAll on non-XML documents
+ // (ID selectors don't work in non-HTML documents)
+ if ( !seed && !Sizzle.isXML(context) ) {
+ // See if we find a selector to speed up
+ var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
+
+ if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
+ // Speed-up: Sizzle("TAG")
+ if ( match[1] ) {
+ return makeArray( context.getElementsByTagName( query ), extra );
+
+ // Speed-up: Sizzle(".CLASS")
+ } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
+ return makeArray( context.getElementsByClassName( match[2] ), extra );
+ }
+ }
+
+ if ( context.nodeType === 9 ) {
+ // Speed-up: Sizzle("body")
+ // The body element only exists once, optimize finding it
+ if ( query === "body" && context.body ) {
+ return makeArray( [ context.body ], extra );
+
+ // Speed-up: Sizzle("#ID")
+ } else if ( match && match[3] ) {
+ var elem = context.getElementById( match[3] );
+
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( elem.id === match[3] ) {
+ return makeArray( [ elem ], extra );
+ }
+
+ } else {
+ return makeArray( [], extra );
+ }
+ }
+
+ try {
+ return makeArray( context.querySelectorAll(query), extra );
+ } catch(qsaError) {}
+
+ // qSA works strangely on Element-rooted queries
+ // We can work around this by specifying an extra ID on the root
+ // and working up from there (Thanks to Andrew Dupont for the technique)
+ // IE 8 doesn't work on object elements
+ } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+ var oldContext = context,
+ old = context.getAttribute( "id" ),
+ nid = old || id,
+ hasParent = context.parentNode,
+ relativeHierarchySelector = /^\s*[+~]/.test( query );
+
+ if ( !old ) {
+ context.setAttribute( "id", nid );
+ } else {
+ nid = nid.replace( /'/g, "\\$&" );
+ }
+ if ( relativeHierarchySelector && hasParent ) {
+ context = context.parentNode;
+ }
+
+ try {
+ if ( !relativeHierarchySelector || hasParent ) {
+ return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );
+ }
+
+ } catch(pseudoError) {
+ } finally {
+ if ( !old ) {
+ oldContext.removeAttribute( "id" );
+ }
+ }
+ }
+ }
+
+ return oldSizzle(query, context, extra, seed);
+ };
+
+ for ( var prop in oldSizzle ) {
+ Sizzle[ prop ] = oldSizzle[ prop ];
+ }
+
+ // release memory in IE
+ div = null;
+ })();
+}
+
+(function(){
+ var html = document.documentElement,
+ matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;
+
+ if ( matches ) {
+ // Check to see if it's possible to do matchesSelector
+ // on a disconnected node (IE 9 fails this)
+ var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ),
+ pseudoWorks = false;
+
+ try {
+ // This should fail with an exception
+ // Gecko does not error, returns false instead
+ matches.call( document.documentElement, "[test!='']:sizzle" );
+
+ } catch( pseudoError ) {
+ pseudoWorks = true;
+ }
+
+ Sizzle.matchesSelector = function( node, expr ) {
+ // Make sure that attribute selectors are quoted
+ expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
+
+ if ( !Sizzle.isXML( node ) ) {
+ try {
+ if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
+ var ret = matches.call( node, expr );
+
+ // IE 9's matchesSelector returns false on disconnected nodes
+ if ( ret || !disconnectedMatch ||
+ // As well, disconnected nodes are said to be in a document
+ // fragment in IE 9, so check for that
+ node.document && node.document.nodeType !== 11 ) {
+ return ret;
+ }
+ }
+ } catch(e) {}
+ }
+
+ return Sizzle(expr, null, null, [node]).length > 0;
+ };
+ }
+})();
+
+(function(){
+ var div = document.createElement("div");
+
+ div.innerHTML = "<div class='test e'></div><div class='test'></div>";
+
+ // Opera can't find a second classname (in 9.6)
+ // Also, make sure that getElementsByClassName actually exists
+ if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
+ return;
+ }
+
+ // Safari caches class attributes, doesn't catch changes (in 3.2)
+ div.lastChild.className = "e";
+
+ if ( div.getElementsByClassName("e").length === 1 ) {
+ return;
+ }
+
+ Expr.order.splice(1, 0, "CLASS");
+ Expr.find.CLASS = function( match, context, isXML ) {
+ if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
+ return context.getElementsByClassName(match[1]);
+ }
+ };
+
+ // release memory in IE
+ div = null;
+})();
+
+function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+
+ if ( elem ) {
+ var match = false;
+
+ elem = elem[dir];
+
+ while ( elem ) {
+ if ( elem[ expando ] === doneName ) {
+ match = checkSet[elem.sizset];
+ break;
+ }
+
+ if ( elem.nodeType === 1 && !isXML ){
+ elem[ expando ] = doneName;
+ elem.sizset = i;
+ }
+
+ if ( elem.nodeName.toLowerCase() === cur ) {
+ match = elem;
+ break;
+ }
+
+ elem = elem[dir];
+ }
+
+ checkSet[i] = match;
+ }
+ }
+}
+
+function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+
+ if ( elem ) {
+ var match = false;
+
+ elem = elem[dir];
+
+ while ( elem ) {
+ if ( elem[ expando ] === doneName ) {
+ match = checkSet[elem.sizset];
+ break;
+ }
+
+ if ( elem.nodeType === 1 ) {
+ if ( !isXML ) {
+ elem[ expando ] = doneName;
+ elem.sizset = i;
+ }
+
+ if ( typeof cur !== "string" ) {
+ if ( elem === cur ) {
+ match = true;
+ break;
+ }
+
+ } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
+ match = elem;
+ break;
+ }
+ }
+
+ elem = elem[dir];
+ }
+
+ checkSet[i] = match;
+ }
+ }
+}
+
+if ( document.documentElement.contains ) {
+ Sizzle.contains = function( a, b ) {
+ return a !== b && (a.contains ? a.contains(b) : true);
+ };
+
+} else if ( document.documentElement.compareDocumentPosition ) {
+ Sizzle.contains = function( a, b ) {
+ return !!(a.compareDocumentPosition(b) & 16);
+ };
+
+} else {
+ Sizzle.contains = function() {
+ return false;
+ };
+}
+
+Sizzle.isXML = function( elem ) {
+ // documentElement is verified for cases where it doesn't yet exist
+ // (such as loading iframes in IE - #4833)
+ var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
+
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+var posProcess = function( selector, context, seed ) {
+ var match,
+ tmpSet = [],
+ later = "",
+ root = context.nodeType ? [context] : context;
+
+ // Position selectors must be done after the filter
+ // And so must :not(positional) so we move all PSEUDOs to the end
+ while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
+ later += match[0];
+ selector = selector.replace( Expr.match.PSEUDO, "" );
+ }
+
+ selector = Expr.relative[selector] ? selector + "*" : selector;
+
+ for ( var i = 0, l = root.length; i < l; i++ ) {
+ Sizzle( selector, root[i], tmpSet, seed );
+ }
+
+ return Sizzle.filter( later, tmpSet );
+};
+
+// EXPOSE
+// Override sizzle attribute retrieval
+Sizzle.attr = jQuery.attr;
+Sizzle.selectors.attrMap = {};
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.filters;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+})();
+
+
+var runtil = /Until$/,
+ rparentsprev = /^(?:parents|prevUntil|prevAll)/,
+ // Note: This RegExp should be improved, or likely pulled from Sizzle
+ rmultiselector = /,/,
+ isSimple = /^.[^:#\[\.,]*$/,
+ slice = Array.prototype.slice,
+ POS = jQuery.expr.match.globalPOS,
+ // methods guaranteed to produce a unique set when starting from a unique set
+ guaranteedUnique = {
+ children: true,
+ contents: true,
+ next: true,
+ prev: true
+ };
+
+jQuery.fn.extend({
+ find: function( selector ) {
+ var self = this,
+ i, l;
+
+ if ( typeof selector !== "string" ) {
+ return jQuery( selector ).filter(function() {
+ for ( i = 0, l = self.length; i < l; i++ ) {
+ if ( jQuery.contains( self[ i ], this ) ) {
+ return true;
+ }
+ }
+ });
+ }
+
+ var ret = this.pushStack( "", "find", selector ),
+ length, n, r;
+
+ for ( i = 0, l = this.length; i < l; i++ ) {
+ length = ret.length;
+ jQuery.find( selector, this[i], ret );
+
+ if ( i > 0 ) {
+ // Make sure that the results are unique
+ for ( n = length; n < ret.length; n++ ) {
+ for ( r = 0; r < length; r++ ) {
+ if ( ret[r] === ret[n] ) {
+ ret.splice(n--, 1);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return ret;
+ },
+
+ has: function( target ) {
+ var targets = jQuery( target );
+ return this.filter(function() {
+ for ( var i = 0, l = targets.length; i < l; i++ ) {
+ if ( jQuery.contains( this, targets[i] ) ) {
+ return true;
+ }
+ }
+ });
+ },
+
+ not: function( selector ) {
+ return this.pushStack( winnow(this, selector, false), "not", selector);
+ },
+
+ filter: function( selector ) {
+ return this.pushStack( winnow(this, selector, true), "filter", selector );
+ },
+
+ is: function( selector ) {
+ return !!selector && (
+ typeof selector === "string" ?
+ // If this is a positional selector, check membership in the returned set
+ // so $("p:first").is("p:last") won't return true for a doc with two "p".
+ POS.test( selector ) ?
+ jQuery( selector, this.context ).index( this[0] ) >= 0 :
+ jQuery.filter( selector, this ).length > 0 :
+ this.filter( selector ).length > 0 );
+ },
+
+ closest: function( selectors, context ) {
+ var ret = [], i, l, cur = this[0];
+
+ // Array (deprecated as of jQuery 1.7)
+ if ( jQuery.isArray( selectors ) ) {
+ var level = 1;
+
+ while ( cur && cur.ownerDocument && cur !== context ) {
+ for ( i = 0; i < selectors.length; i++ ) {
+
+ if ( jQuery( cur ).is( selectors[ i ] ) ) {
+ ret.push({ selector: selectors[ i ], elem: cur, level: level });
+ }
+ }
+
+ cur = cur.parentNode;
+ level++;
+ }
+
+ return ret;
+ }
+
+ // String
+ var pos = POS.test( selectors ) || typeof selectors !== "string" ?
+ jQuery( selectors, context || this.context ) :
+ 0;
+
+ for ( i = 0, l = this.length; i < l; i++ ) {
+ cur = this[i];
+
+ while ( cur ) {
+ if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
+ ret.push( cur );
+ break;
+
+ } else {
+ cur = cur.parentNode;
+ if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {
+ break;
+ }
+ }
+ }
+ }
+
+ ret = ret.length > 1 ? jQuery.unique( ret ) : ret;
+
+ return this.pushStack( ret, "closest", selectors );
+ },
+
+ // Determine the position of an element within
+ // the matched set of elements
+ index: function( elem ) {
+
+ // No argument, return index in parent
+ if ( !elem ) {
+ return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
+ }
+
+ // index in selector
+ if ( typeof elem === "string" ) {
+ return jQuery.inArray( this[0], jQuery( elem ) );
+ }
+
+ // Locate the position of the desired element
+ return jQuery.inArray(
+ // If it receives a jQuery object, the first element is used
+ elem.jquery ? elem[0] : elem, this );
+ },
+
+ add: function( selector, context ) {
+ var set = typeof selector === "string" ?
+ jQuery( selector, context ) :
+ jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
+ all = jQuery.merge( this.get(), set );
+
+ return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
+ all :
+ jQuery.unique( all ) );
+ },
+
+ andSelf: function() {
+ return this.add( this.prevObject );
+ }
+});
+
+// A painfully simple check to see if an element is disconnected
+// from a document (should be improved, where feasible).
+function isDisconnected( node ) {
+ return !node || !node.parentNode || node.parentNode.nodeType === 11;
+}
+
+jQuery.each({
+ parent: function( elem ) {
+ var parent = elem.parentNode;
+ return parent && parent.nodeType !== 11 ? parent : null;
+ },
+ parents: function( elem ) {
+ return jQuery.dir( elem, "parentNode" );
+ },
+ parentsUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "parentNode", until );
+ },
+ next: function( elem ) {
+ return jQuery.nth( elem, 2, "nextSibling" );
+ },
+ prev: function( elem ) {
+ return jQuery.nth( elem, 2, "previousSibling" );
+ },
+ nextAll: function( elem ) {
+ return jQuery.dir( elem, "nextSibling" );
+ },
+ prevAll: function( elem ) {
+ return jQuery.dir( elem, "previousSibling" );
+ },
+ nextUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "nextSibling", until );
+ },
+ prevUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "previousSibling", until );
+ },
+ siblings: function( elem ) {
+ return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
+ },
+ children: function( elem ) {
+ return jQuery.sibling( elem.firstChild );
+ },
+ contents: function( elem ) {
+ return jQuery.nodeName( elem, "iframe" ) ?
+ elem.contentDocument || elem.contentWindow.document :
+ jQuery.makeArray( elem.childNodes );
+ }
+}, function( name, fn ) {
+ jQuery.fn[ name ] = function( until, selector ) {
+ var ret = jQuery.map( this, fn, until );
+
+ if ( !runtil.test( name ) ) {
+ selector = until;
+ }
+
+ if ( selector && typeof selector === "string" ) {
+ ret = jQuery.filter( selector, ret );
+ }
+
+ ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
+
+ if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
+ ret = ret.reverse();
+ }
+
+ return this.pushStack( ret, name, slice.call( arguments ).join(",") );
+ };
+});
+
+jQuery.extend({
+ filter: function( expr, elems, not ) {
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
+
+ return elems.length === 1 ?
+ jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
+ jQuery.find.matches(expr, elems);
+ },
+
+ dir: function( elem, dir, until ) {
+ var matched = [],
+ cur = elem[ dir ];
+
+ while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+ if ( cur.nodeType === 1 ) {
+ matched.push( cur );
+ }
+ cur = cur[dir];
+ }
+ return matched;
+ },
+
+ nth: function( cur, result, dir, elem ) {
+ result = result || 1;
+ var num = 0;
+
+ for ( ; cur; cur = cur[dir] ) {
+ if ( cur.nodeType === 1 && ++num === result ) {
+ break;
+ }
+ }
+
+ return cur;
+ },
+
+ sibling: function( n, elem ) {
+ var r = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType === 1 && n !== elem ) {
+ r.push( n );
+ }
+ }
+
+ return r;
+ }
+});
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, keep ) {
+
+ // Can't pass null or undefined to indexOf in Firefox 4
+ // Set to 0 to skip string check
+ qualifier = qualifier || 0;
+
+ if ( jQuery.isFunction( qualifier ) ) {
+ return jQuery.grep(elements, function( elem, i ) {
+ var retVal = !!qualifier.call( elem, i, elem );
+ return retVal === keep;
+ });
+
+ } else if ( qualifier.nodeType ) {
+ return jQuery.grep(elements, function( elem, i ) {
+ return ( elem === qualifier ) === keep;
+ });
+
+ } else if ( typeof qualifier === "string" ) {
+ var filtered = jQuery.grep(elements, function( elem ) {
+ return elem.nodeType === 1;
+ });
+
+ if ( isSimple.test( qualifier ) ) {
+ return jQuery.filter(qualifier, filtered, !keep);
+ } else {
+ qualifier = jQuery.filter( qualifier, filtered );
+ }
+ }
+
+ return jQuery.grep(elements, function( elem, i ) {
+ return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
+ });
+}
+
+
+
+
+function createSafeFragment( document ) {
+ var list = nodeNames.split( "|" ),
+ safeFrag = document.createDocumentFragment();
+
+ if ( safeFrag.createElement ) {
+ while ( list.length ) {
+ safeFrag.createElement(
+ list.pop()
+ );
+ }
+ }
+ return safeFrag;
+}
+
+var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
+ "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
+ rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
+ rleadingWhitespace = /^\s+/,
+ rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
+ rtagName = /<([\w:]+)/,
+ rtbody = /<tbody/i,
+ rhtml = /<|&#?\w+;/,
+ rnoInnerhtml = /<(?:script|style)/i,
+ rnocache = /<(?:script|object|embed|option|style)/i,
+ rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
+ // checked="checked" or checked
+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+ rscriptType = /\/(java|ecma)script/i,
+ rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)/,
+ wrapMap = {
+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
+ legend: [ 1, "<fieldset>", "</fieldset>" ],
+ thead: [ 1, "<table>", "</table>" ],
+ tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+ td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+ col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
+ area: [ 1, "<map>", "</map>" ],
+ _default: [ 0, "", "" ]
+ },
+ safeFragment = createSafeFragment( document );
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+// IE can't serialize <link> and <script> tags normally
+if ( !jQuery.support.htmlSerialize ) {
+ wrapMap._default = [ 1, "div<div>", "</div>" ];
+}
+
+jQuery.fn.extend({
+ text: function( value ) {
+ return jQuery.access( this, function( value ) {
+ return value === undefined ?
+ jQuery.text( this ) :
+ this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
+ }, null, value, arguments.length );
+ },
+
+ wrapAll: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapAll( html.call(this, i) );
+ });
+ }
+
+ if ( this[0] ) {
+ // The elements to wrap the target around
+ var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+
+ if ( this[0].parentNode ) {
+ wrap.insertBefore( this[0] );
+ }
+
+ wrap.map(function() {
+ var elem = this;
+
+ while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+ elem = elem.firstChild;
+ }
+
+ return elem;
+ }).append( this );
+ }
+
+ return this;
+ },
+
+ wrapInner: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapInner( html.call(this, i) );
+ });
+ }
+
+ return this.each(function() {
+ var self = jQuery( this ),
+ contents = self.contents();
+
+ if ( contents.length ) {
+ contents.wrapAll( html );
+
+ } else {
+ self.append( html );
+ }
+ });
+ },
+
+ wrap: function( html ) {
+ var isFunction = jQuery.isFunction( html );
+
+ return this.each(function(i) {
+ jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
+ });
+ },
+
+ unwrap: function() {
+ return this.parent().each(function() {
+ if ( !jQuery.nodeName( this, "body" ) ) {
+ jQuery( this ).replaceWith( this.childNodes );
+ }
+ }).end();
+ },
+
+ append: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 ) {
+ this.appendChild( elem );
+ }
+ });
+ },
+
+ prepend: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 ) {
+ this.insertBefore( elem, this.firstChild );
+ }
+ });
+ },
+
+ before: function() {
+ if ( this[0] && this[0].parentNode ) {
+ return this.domManip(arguments, false, function( elem ) {
+ this.parentNode.insertBefore( elem, this );
+ });
+ } else if ( arguments.length ) {
+ var set = jQuery.clean( arguments );
+ set.push.apply( set, this.toArray() );
+ return this.pushStack( set, "before", arguments );
+ }
+ },
+
+ after: function() {
+ if ( this[0] && this[0].parentNode ) {
+ return this.domManip(arguments, false, function( elem ) {
+ this.parentNode.insertBefore( elem, this.nextSibling );
+ });
+ } else if ( arguments.length ) {
+ var set = this.pushStack( this, "after", arguments );
+ set.push.apply( set, jQuery.clean(arguments) );
+ return set;
+ }
+ },
+
+ // keepData is for internal use only--do not document
+ remove: function( selector, keepData ) {
+ for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+ if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
+ if ( !keepData && elem.nodeType === 1 ) {
+ jQuery.cleanData( elem.getElementsByTagName("*") );
+ jQuery.cleanData( [ elem ] );
+ }
+
+ if ( elem.parentNode ) {
+ elem.parentNode.removeChild( elem );
+ }
+ }
+ }
+
+ return this;
+ },
+
+ empty: function() {
+ for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( elem.getElementsByTagName("*") );
+ }
+
+ // Remove any remaining nodes
+ while ( elem.firstChild ) {
+ elem.removeChild( elem.firstChild );
+ }
+ }
+
+ return this;
+ },
+
+ clone: function( dataAndEvents, deepDataAndEvents ) {
+ dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+ deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+ return this.map( function () {
+ return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+ });
+ },
+
+ html: function( value ) {
+ return jQuery.access( this, function( value ) {
+ var elem = this[0] || {},
+ i = 0,
+ l = this.length;
+
+ if ( value === undefined ) {
+ return elem.nodeType === 1 ?
+ elem.innerHTML.replace( rinlinejQuery, "" ) :
+ null;
+ }
+
+
+ if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+ ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
+ !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {
+
+ value = value.replace( rxhtmlTag, "<$1></$2>" );
+
+ try {
+ for (; i < l; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ elem = this[i] || {};
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( elem.getElementsByTagName( "*" ) );
+ elem.innerHTML = value;
+ }
+ }
+
+ elem = 0;
+
+ // If using innerHTML throws an exception, use the fallback method
+ } catch(e) {}
+ }
+
+ if ( elem ) {
+ this.empty().append( value );
+ }
+ }, null, value, arguments.length );
+ },
+
+ replaceWith: function( value ) {
+ if ( this[0] && this[0].parentNode ) {
+ // Make sure that the elements are removed from the DOM before they are inserted
+ // this can help fix replacing a parent with child elements
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function(i) {
+ var self = jQuery(this), old = self.html();
+ self.replaceWith( value.call( this, i, old ) );
+ });
+ }
+
+ if ( typeof value !== "string" ) {
+ value = jQuery( value ).detach();
+ }
+
+ return this.each(function() {
+ var next = this.nextSibling,
+ parent = this.parentNode;
+
+ jQuery( this ).remove();
+
+ if ( next ) {
+ jQuery(next).before( value );
+ } else {
+ jQuery(parent).append( value );
+ }
+ });
+ } else {
+ return this.length ?
+ this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
+ this;
+ }
+ },
+
+ detach: function( selector ) {
+ return this.remove( selector, true );
+ },
+
+ domManip: function( args, table, callback ) {
+ var results, first, fragment, parent,
+ value = args[0],
+ scripts = [];
+
+ // We can't cloneNode fragments that contain checked, in WebKit
+ if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
+ return this.each(function() {
+ jQuery(this).domManip( args, table, callback, true );
+ });
+ }
+
+ if ( jQuery.isFunction(value) ) {
+ return this.each(function(i) {
+ var self = jQuery(this);
+ args[0] = value.call(this, i, table ? self.html() : undefined);
+ self.domManip( args, table, callback );
+ });
+ }
+
+ if ( this[0] ) {
+ parent = value && value.parentNode;
+
+ // If we're in a fragment, just use that instead of building a new one
+ if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
+ results = { fragment: parent };
+
+ } else {
+ results = jQuery.buildFragment( args, this, scripts );
+ }
+
+ fragment = results.fragment;
+
+ if ( fragment.childNodes.length === 1 ) {
+ first = fragment = fragment.firstChild;
+ } else {
+ first = fragment.firstChild;
+ }
+
+ if ( first ) {
+ table = table && jQuery.nodeName( first, "tr" );
+
+ for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {
+ callback.call(
+ table ?
+ root(this[i], first) :
+ this[i],
+ // Make sure that we do not leak memory by inadvertently discarding
+ // the original fragment (which might have attached data) instead of
+ // using it; in addition, use the original fragment object for the last
+ // item instead of first because it can end up being emptied incorrectly
+ // in certain situations (Bug #8070).
+ // Fragments from the fragment cache must always be cloned and never used
+ // in place.
+ results.cacheable || ( l > 1 && i < lastIndex ) ?
+ jQuery.clone( fragment, true, true ) :
+ fragment
+ );
+ }
+ }
+
+ if ( scripts.length ) {
+ jQuery.each( scripts, function( i, elem ) {
+ if ( elem.src ) {
+ jQuery.ajax({
+ type: "GET",
+ global: false,
+ url: elem.src,
+ async: false,
+ dataType: "script"
+ });
+ } else {
+ jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "/*$0*/" ) );
+ }
+
+ if ( elem.parentNode ) {
+ elem.parentNode.removeChild( elem );
+ }
+ });
+ }
+ }
+
+ return this;
+ }
+});
+
+function root( elem, cur ) {
+ return jQuery.nodeName(elem, "table") ?
+ (elem.getElementsByTagName("tbody")[0] ||
+ elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
+ elem;
+}
+
+function cloneCopyEvent( src, dest ) {
+
+ if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
+ return;
+ }
+
+ var type, i, l,
+ oldData = jQuery._data( src ),
+ curData = jQuery._data( dest, oldData ),
+ events = oldData.events;
+
+ if ( events ) {
+ delete curData.handle;
+ curData.events = {};
+
+ for ( type in events ) {
+ for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+ jQuery.event.add( dest, type, events[ type ][ i ] );
+ }
+ }
+ }
+
+ // make the cloned public data object a copy from the original
+ if ( curData.data ) {
+ curData.data = jQuery.extend( {}, curData.data );
+ }
+}
+
+function cloneFixAttributes( src, dest ) {
+ var nodeName;
+
+ // We do not need to do anything for non-Elements
+ if ( dest.nodeType !== 1 ) {
+ return;
+ }
+
+ // clearAttributes removes the attributes, which we don't want,
+ // but also removes the attachEvent events, which we *do* want
+ if ( dest.clearAttributes ) {
+ dest.clearAttributes();
+ }
+
+ // mergeAttributes, in contrast, only merges back on the
+ // original attributes, not the events
+ if ( dest.mergeAttributes ) {
+ dest.mergeAttributes( src );
+ }
+
+ nodeName = dest.nodeName.toLowerCase();
+
+ // IE6-8 fail to clone children inside object elements that use
+ // the proprietary classid attribute value (rather than the type
+ // attribute) to identify the type of content to display
+ if ( nodeName === "object" ) {
+ dest.outerHTML = src.outerHTML;
+
+ } else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
+ // IE6-8 fails to persist the checked state of a cloned checkbox
+ // or radio button. Worse, IE6-7 fail to give the cloned element
+ // a checked appearance if the defaultChecked value isn't also set
+ if ( src.checked ) {
+ dest.defaultChecked = dest.checked = src.checked;
+ }
+
+ // IE6-7 get confused and end up setting the value of a cloned
+ // checkbox/radio button to an empty string instead of "on"
+ if ( dest.value !== src.value ) {
+ dest.value = src.value;
+ }
+
+ // IE6-8 fails to return the selected option to the default selected
+ // state when cloning options
+ } else if ( nodeName === "option" ) {
+ dest.selected = src.defaultSelected;
+
+ // IE6-8 fails to set the defaultValue to the correct value when
+ // cloning other types of input fields
+ } else if ( nodeName === "input" || nodeName === "textarea" ) {
+ dest.defaultValue = src.defaultValue;
+
+ // IE blanks contents when cloning scripts
+ } else if ( nodeName === "script" && dest.text !== src.text ) {
+ dest.text = src.text;
+ }
+
+ // Event data gets referenced instead of copied if the expando
+ // gets copied too
+ dest.removeAttribute( jQuery.expando );
+
+ // Clear flags for bubbling special change/submit events, they must
+ // be reattached when the newly cloned events are first activated
+ dest.removeAttribute( "_submit_attached" );
+ dest.removeAttribute( "_change_attached" );
+}
+
+jQuery.buildFragment = function( args, nodes, scripts ) {
+ var fragment, cacheable, cacheresults, doc,
+ first = args[ 0 ];
+
+ // nodes may contain either an explicit document object,
+ // a jQuery collection or context object.
+ // If nodes[0] contains a valid object to assign to doc
+ if ( nodes && nodes[0] ) {
+ doc = nodes[0].ownerDocument || nodes[0];
+ }
+
+ // Ensure that an attr object doesn't incorrectly stand in as a document object
+ // Chrome and Firefox seem to allow this to occur and will throw exception
+ // Fixes #8950
+ if ( !doc.createDocumentFragment ) {
+ doc = document;
+ }
+
+ // Only cache "small" (1/2 KB) HTML strings that are associated with the main document
+ // Cloning options loses the selected state, so don't cache them
+ // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
+ // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
+ // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501
+ if ( args.length === 1 && typeof first === "string" && first.length < 512 && doc === document &&
+ first.charAt(0) === "<" && !rnocache.test( first ) &&
+ (jQuery.support.checkClone || !rchecked.test( first )) &&
+ (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {
+
+ cacheable = true;
+
+ cacheresults = jQuery.fragments[ first ];
+ if ( cacheresults && cacheresults !== 1 ) {
+ fragment = cacheresults;
+ }
+ }
+
+ if ( !fragment ) {
+ fragment = doc.createDocumentFragment();
+ jQuery.clean( args, doc, fragment, scripts );
+ }
+
+ if ( cacheable ) {
+ jQuery.fragments[ first ] = cacheresults ? fragment : 1;
+ }
+
+ return { fragment: fragment, cacheable: cacheable };
+};
+
+jQuery.fragments = {};
+
+jQuery.each({
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+}, function( name, original ) {
+ jQuery.fn[ name ] = function( selector ) {
+ var ret = [],
+ insert = jQuery( selector ),
+ parent = this.length === 1 && this[0].parentNode;
+
+ if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
+ insert[ original ]( this[0] );
+ return this;
+
+ } else {
+ for ( var i = 0, l = insert.length; i < l; i++ ) {
+ var elems = ( i > 0 ? this.clone(true) : this ).get();
+ jQuery( insert[i] )[ original ]( elems );
+ ret = ret.concat( elems );
+ }
+
+ return this.pushStack( ret, name, insert.selector );
+ }
+ };
+});
+
+function getAll( elem ) {
+ if ( typeof elem.getElementsByTagName !== "undefined" ) {
+ return elem.getElementsByTagName( "*" );
+
+ } else if ( typeof elem.querySelectorAll !== "undefined" ) {
+ return elem.querySelectorAll( "*" );
+
+ } else {
+ return [];
+ }
+}
+
+// Used in clean, fixes the defaultChecked property
+function fixDefaultChecked( elem ) {
+ if ( elem.type === "checkbox" || elem.type === "radio" ) {
+ elem.defaultChecked = elem.checked;
+ }
+}
+// Finds all inputs and passes them to fixDefaultChecked
+function findInputs( elem ) {
+ var nodeName = ( elem.nodeName || "" ).toLowerCase();
+ if ( nodeName === "input" ) {
+ fixDefaultChecked( elem );
+ // Skip scripts, get other children
+ } else if ( nodeName !== "script" && typeof elem.getElementsByTagName !== "undefined" ) {
+ jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
+ }
+}
+
+// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js
+function shimCloneNode( elem ) {
+ var div = document.createElement( "div" );
+ safeFragment.appendChild( div );
+
+ div.innerHTML = elem.outerHTML;
+ return div.firstChild;
+}
+
+jQuery.extend({
+ clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+ var srcElements,
+ destElements,
+ i,
+ // IE<=8 does not properly clone detached, unknown element nodes
+ clone = jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ?
+ elem.cloneNode( true ) :
+ shimCloneNode( elem );
+
+ if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
+ (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
+ // IE copies events bound via attachEvent when using cloneNode.
+ // Calling detachEvent on the clone will also remove the events
+ // from the original. In order to get around this, we use some
+ // proprietary methods to clear the events. Thanks to MooTools
+ // guys for this hotness.
+
+ cloneFixAttributes( elem, clone );
+
+ // Using Sizzle here is crazy slow, so we use getElementsByTagName instead
+ srcElements = getAll( elem );
+ destElements = getAll( clone );
+
+ // Weird iteration because IE will replace the length property
+ // with an element if you are cloning the body and one of the
+ // elements on the page has a name or id of "length"
+ for ( i = 0; srcElements[i]; ++i ) {
+ // Ensure that the destination node is not null; Fixes #9587
+ if ( destElements[i] ) {
+ cloneFixAttributes( srcElements[i], destElements[i] );
+ }
+ }
+ }
+
+ // Copy the events from the original to the clone
+ if ( dataAndEvents ) {
+ cloneCopyEvent( elem, clone );
+
+ if ( deepDataAndEvents ) {
+ srcElements = getAll( elem );
+ destElements = getAll( clone );
+
+ for ( i = 0; srcElements[i]; ++i ) {
+ cloneCopyEvent( srcElements[i], destElements[i] );
+ }
+ }
+ }
+
+ srcElements = destElements = null;
+
+ // Return the cloned set
+ return clone;
+ },
+
+ clean: function( elems, context, fragment, scripts ) {
+ var checkScriptType, script, j,
+ ret = [];
+
+ context = context || document;
+
+ // !context.createElement fails in IE with an error but returns typeof 'object'
+ if ( typeof context.createElement === "undefined" ) {
+ context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+ }
+
+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+ if ( typeof elem === "number" ) {
+ elem += "";
+ }
+
+ if ( !elem ) {
+ continue;
+ }
+
+ // Convert html string into DOM nodes
+ if ( typeof elem === "string" ) {
+ if ( !rhtml.test( elem ) ) {
+ elem = context.createTextNode( elem );
+ } else {
+ // Fix "XHTML"-style tags in all browsers
+ elem = elem.replace(rxhtmlTag, "<$1></$2>");
+
+ // Trim whitespace, otherwise indexOf won't work as expected
+ var tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(),
+ wrap = wrapMap[ tag ] || wrapMap._default,
+ depth = wrap[0],
+ div = context.createElement("div"),
+ safeChildNodes = safeFragment.childNodes,
+ remove;
+
+ // Append wrapper element to unknown element safe doc fragment
+ if ( context === document ) {
+ // Use the fragment we've already created for this document
+ safeFragment.appendChild( div );
+ } else {
+ // Use a fragment created with the owner document
+ createSafeFragment( context ).appendChild( div );
+ }
+
+ // Go to html and back, then peel off extra wrappers
+ div.innerHTML = wrap[1] + elem + wrap[2];
+
+ // Move to the right depth
+ while ( depth-- ) {
+ div = div.lastChild;
+ }
+
+ // Remove IE's autoinserted <tbody> from table fragments
+ if ( !jQuery.support.tbody ) {
+
+ // String was a <table>, *may* have spurious <tbody>
+ var hasBody = rtbody.test(elem),
+ tbody = tag === "table" && !hasBody ?
+ div.firstChild && div.firstChild.childNodes :
+
+ // String was a bare <thead> or <tfoot>
+ wrap[1] === "<table>" && !hasBody ?
+ div.childNodes :
+ [];
+
+ for ( j = tbody.length - 1; j >= 0 ; --j ) {
+ if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
+ tbody[ j ].parentNode.removeChild( tbody[ j ] );
+ }
+ }
+ }
+
+ // IE completely kills leading whitespace when innerHTML is used
+ if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+ div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
+ }
+
+ elem = div.childNodes;
+
+ // Clear elements from DocumentFragment (safeFragment or otherwise)
+ // to avoid hoarding elements. Fixes #11356
+ if ( div ) {
+ div.parentNode.removeChild( div );
+
+ // Guard against -1 index exceptions in FF3.6
+ if ( safeChildNodes.length > 0 ) {
+ remove = safeChildNodes[ safeChildNodes.length - 1 ];
+
+ if ( remove && remove.parentNode ) {
+ remove.parentNode.removeChild( remove );
+ }
+ }
+ }
+ }
+ }
+
+ // Resets defaultChecked for any radios and checkboxes
+ // about to be appended to the DOM in IE 6/7 (#8060)
+ var len;
+ if ( !jQuery.support.appendChecked ) {
+ if ( elem[0] && typeof (len = elem.length) === "number" ) {
+ for ( j = 0; j < len; j++ ) {
+ findInputs( elem[j] );
+ }
+ } else {
+ findInputs( elem );
+ }
+ }
+
+ if ( elem.nodeType ) {
+ ret.push( elem );
+ } else {
+ ret = jQuery.merge( ret, elem );
+ }
+ }
+
+ if ( fragment ) {
+ checkScriptType = function( elem ) {
+ return !elem.type || rscriptType.test( elem.type );
+ };
+ for ( i = 0; ret[i]; i++ ) {
+ script = ret[i];
+ if ( scripts && jQuery.nodeName( script, "script" ) && (!script.type || rscriptType.test( script.type )) ) {
+ scripts.push( script.parentNode ? script.parentNode.removeChild( script ) : script );
+
+ } else {
+ if ( script.nodeType === 1 ) {
+ var jsTags = jQuery.grep( script.getElementsByTagName( "script" ), checkScriptType );
+
+ ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
+ }
+ fragment.appendChild( script );
+ }
+ }
+ }
+
+ return ret;
+ },
+
+ cleanData: function( elems ) {
+ var data, id,
+ cache = jQuery.cache,
+ special = jQuery.event.special,
+ deleteExpando = jQuery.support.deleteExpando;
+
+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+ if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
+ continue;
+ }
+
+ id = elem[ jQuery.expando ];
+
+ if ( id ) {
+ data = cache[ id ];
+
+ if ( data && data.events ) {
+ for ( var type in data.events ) {
+ if ( special[ type ] ) {
+ jQuery.event.remove( elem, type );
+
+ // This is a shortcut to avoid jQuery.event.remove's overhead
+ } else {
+ jQuery.removeEvent( elem, type, data.handle );
+ }
+ }
+
+ // Null the DOM reference to avoid IE6/7/8 leak (#7054)
+ if ( data.handle ) {
+ data.handle.elem = null;
+ }
+ }
+
+ if ( deleteExpando ) {
+ delete elem[ jQuery.expando ];
+
+ } else if ( elem.removeAttribute ) {
+ elem.removeAttribute( jQuery.expando );
+ }
+
+ delete cache[ id ];
+ }
+ }
+ }
+});
+
+
+
+
+var ralpha = /alpha\([^)]*\)/i,
+ ropacity = /opacity=([^)]*)/,
+ // fixed for IE9, see #8346
+ rupper = /([A-Z]|^ms)/g,
+ rnum = /^[\-+]?(?:\d*\.)?\d+$/i,
+ rnumnonpx = /^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i,
+ rrelNum = /^([\-+])=([\-+.\de]+)/,
+ rmargin = /^margin/,
+
+ cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+
+ // order is important!
+ cssExpand = [ "Top", "Right", "Bottom", "Left" ],
+
+ curCSS,
+
+ getComputedStyle,
+ currentStyle;
+
+jQuery.fn.css = function( name, value ) {
+ return jQuery.access( this, function( elem, name, value ) {
+ return value !== undefined ?
+ jQuery.style( elem, name, value ) :
+ jQuery.css( elem, name );
+ }, name, value, arguments.length > 1 );
+};
+
+jQuery.extend({
+ // Add in style property hooks for overriding the default
+ // behavior of getting and setting a style property
+ cssHooks: {
+ opacity: {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ // We should always get a number back from opacity
+ var ret = curCSS( elem, "opacity" );
+ return ret === "" ? "1" : ret;
+
+ } else {
+ return elem.style.opacity;
+ }
+ }
+ }
+ },
+
+ // Exclude the following css properties to add px
+ cssNumber: {
+ "fillOpacity": true,
+ "fontWeight": true,
+ "lineHeight": true,
+ "opacity": true,
+ "orphans": true,
+ "widows": true,
+ "zIndex": true,
+ "zoom": true
+ },
+
+ // Add in properties whose names you wish to fix before
+ // setting or getting the value
+ cssProps: {
+ // normalize float css property
+ "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
+ },
+
+ // Get and set the style property on a DOM Node
+ style: function( elem, name, value, extra ) {
+ // Don't set styles on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+ return;
+ }
+
+ // Make sure that we're working with the right name
+ var ret, type, origName = jQuery.camelCase( name ),
+ style = elem.style, hooks = jQuery.cssHooks[ origName ];
+
+ name = jQuery.cssProps[ origName ] || origName;
+
+ // Check if we're setting a value
+ if ( value !== undefined ) {
+ type = typeof value;
+
+ // convert relative number strings (+= or -=) to relative numbers. #7345
+ if ( type === "string" && (ret = rrelNum.exec( value )) ) {
+ value = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );
+ // Fixes bug #9237
+ type = "number";
+ }
+
+ // Make sure that NaN and null values aren't set. See: #7116
+ if ( value == null || type === "number" && isNaN( value ) ) {
+ return;
+ }
+
+ // If a number was passed in, add 'px' to the (except for certain CSS properties)
+ if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
+ value += "px";
+ }
+
+ // If a hook was provided, use that value, otherwise just set the specified value
+ if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
+ // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
+ // Fixes bug #5509
+ try {
+ style[ name ] = value;
+ } catch(e) {}
+ }
+
+ } else {
+ // If a hook was provided get the non-computed value from there
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+ return ret;
+ }
+
+ // Otherwise just get the value from the style object
+ return style[ name ];
+ }
+ },
+
+ css: function( elem, name, extra ) {
+ var ret, hooks;
+
+ // Make sure that we're working with the right name
+ name = jQuery.camelCase( name );
+ hooks = jQuery.cssHooks[ name ];
+ name = jQuery.cssProps[ name ] || name;
+
+ // cssFloat needs a special treatment
+ if ( name === "cssFloat" ) {
+ name = "float";
+ }
+
+ // If a hook was provided get the computed value from there
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
+ return ret;
+
+ // Otherwise, if a way to get the computed value exists, use that
+ } else if ( curCSS ) {
+ return curCSS( elem, name );
+ }
+ },
+
+ // A method for quickly swapping in/out CSS properties to get correct calculations
+ swap: function( elem, options, callback ) {
+ var old = {},
+ ret, name;
+
+ // Remember the old values, and insert the new ones
+ for ( name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ ret = callback.call( elem );
+
+ // Revert the old values
+ for ( name in options ) {
+ elem.style[ name ] = old[ name ];
+ }
+
+ return ret;
+ }
+});
+
+// DEPRECATED in 1.3, Use jQuery.css() instead
+jQuery.curCSS = jQuery.css;
+
+if ( document.defaultView && document.defaultView.getComputedStyle ) {
+ getComputedStyle = function( elem, name ) {
+ var ret, defaultView, computedStyle, width,
+ style = elem.style;
+
+ name = name.replace( rupper, "-$1" ).toLowerCase();
+
+ if ( (defaultView = elem.ownerDocument.defaultView) &&
+ (computedStyle = defaultView.getComputedStyle( elem, null )) ) {
+
+ ret = computedStyle.getPropertyValue( name );
+ if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
+ ret = jQuery.style( elem, name );
+ }
+ }
+
+ // A tribute to the "awesome hack by Dean Edwards"
+ // WebKit uses "computed value (percentage if specified)" instead of "used value" for margins
+ // which is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
+ if ( !jQuery.support.pixelMargin && computedStyle && rmargin.test( name ) && rnumnonpx.test( ret ) ) {
+ width = style.width;
+ style.width = ret;
+ ret = computedStyle.width;
+ style.width = width;
+ }
+
+ return ret;
+ };
+}
+
+if ( document.documentElement.currentStyle ) {
+ currentStyle = function( elem, name ) {
+ var left, rsLeft, uncomputed,
+ ret = elem.currentStyle && elem.currentStyle[ name ],
+ style = elem.style;
+
+ // Avoid setting ret to empty string here
+ // so we don't default to auto
+ if ( ret == null && style && (uncomputed = style[ name ]) ) {
+ ret = uncomputed;
+ }
+
+ // From the awesome hack by Dean Edwards
+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+ // If we're not dealing with a regular pixel number
+ // but a number that has a weird ending, we need to convert it to pixels
+ if ( rnumnonpx.test( ret ) ) {
+
+ // Remember the original values
+ left = style.left;
+ rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;
+
+ // Put in the new values to get a computed value out
+ if ( rsLeft ) {
+ elem.runtimeStyle.left = elem.currentStyle.left;
+ }
+ style.left = name === "fontSize" ? "1em" : ret;
+ ret = style.pixelLeft + "px";
+
+ // Revert the changed values
+ style.left = left;
+ if ( rsLeft ) {
+ elem.runtimeStyle.left = rsLeft;
+ }
+ }
+
+ return ret === "" ? "auto" : ret;
+ };
+}
+
+curCSS = getComputedStyle || currentStyle;
+
+function getWidthOrHeight( elem, name, extra ) {
+
+ // Start with offset property
+ var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+ i = name === "width" ? 1 : 0,
+ len = 4;
+
+ if ( val > 0 ) {
+ if ( extra !== "border" ) {
+ for ( ; i < len; i += 2 ) {
+ if ( !extra ) {
+ val -= parseFloat( jQuery.css( elem, "padding" + cssExpand[ i ] ) ) || 0;
+ }
+ if ( extra === "margin" ) {
+ val += parseFloat( jQuery.css( elem, extra + cssExpand[ i ] ) ) || 0;
+ } else {
+ val -= parseFloat( jQuery.css( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
+ }
+ }
+ }
+
+ return val + "px";
+ }
+
+ // Fall back to computed then uncomputed css if necessary
+ val = curCSS( elem, name );
+ if ( val < 0 || val == null ) {
+ val = elem.style[ name ];
+ }
+
+ // Computed unit is not pixels. Stop here and return.
+ if ( rnumnonpx.test(val) ) {
+ return val;
+ }
+
+ // Normalize "", auto, and prepare for extra
+ val = parseFloat( val ) || 0;
+
+ // Add padding, border, margin
+ if ( extra ) {
+ for ( ; i < len; i += 2 ) {
+ val += parseFloat( jQuery.css( elem, "padding" + cssExpand[ i ] ) ) || 0;
+ if ( extra !== "padding" ) {
+ val += parseFloat( jQuery.css( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
+ }
+ if ( extra === "margin" ) {
+ val += parseFloat( jQuery.css( elem, extra + cssExpand[ i ]) ) || 0;
+ }
+ }
+ }
+
+ return val + "px";
+}
+
+jQuery.each([ "height", "width" ], function( i, name ) {
+ jQuery.cssHooks[ name ] = {
+ get: function( elem, computed, extra ) {
+ if ( computed ) {
+ if ( elem.offsetWidth !== 0 ) {
+ return getWidthOrHeight( elem, name, extra );
+ } else {
+ return jQuery.swap( elem, cssShow, function() {
+ return getWidthOrHeight( elem, name, extra );
+ });
+ }
+ }
+ },
+
+ set: function( elem, value ) {
+ return rnum.test( value ) ?
+ value + "px" :
+ value;
+ }
+ };
+});
+
+if ( !jQuery.support.opacity ) {
+ jQuery.cssHooks.opacity = {
+ get: function( elem, computed ) {
+ // IE uses filters for opacity
+ return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
+ ( parseFloat( RegExp.$1 ) / 100 ) + "" :
+ computed ? "1" : "";
+ },
+
+ set: function( elem, value ) {
+ var style = elem.style,
+ currentStyle = elem.currentStyle,
+ opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
+ filter = currentStyle && currentStyle.filter || style.filter || "";
+
+ // IE has trouble with opacity if it does not have layout
+ // Force it by setting the zoom level
+ style.zoom = 1;
+
+ // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
+ if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" ) {
+
+ // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
+ // if "filter:" is present at all, clearType is disabled, we want to avoid this
+ // style.removeAttribute is IE Only, but so apparently is this code path...
+ style.removeAttribute( "filter" );
+
+ // if there there is no filter style applied in a css rule, we are done
+ if ( currentStyle && !currentStyle.filter ) {
+ return;
+ }
+ }
+
+ // otherwise, set new filter values
+ style.filter = ralpha.test( filter ) ?
+ filter.replace( ralpha, opacity ) :
+ filter + " " + opacity;
+ }
+ };
+}
+
+jQuery(function() {
+ // This hook cannot be added until DOM ready because the support test
+ // for it is not run until after DOM ready
+ if ( !jQuery.support.reliableMarginRight ) {
+ jQuery.cssHooks.marginRight = {
+ get: function( elem, computed ) {
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ // Work around by temporarily setting element display to inline-block
+ return jQuery.swap( elem, { "display": "inline-block" }, function() {
+ if ( computed ) {
+ return curCSS( elem, "margin-right" );
+ } else {
+ return elem.style.marginRight;
+ }
+ });
+ }
+ };
+ }
+});
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.hidden = function( elem ) {
+ var width = elem.offsetWidth,
+ height = elem.offsetHeight;
+
+ return ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
+ };
+
+ jQuery.expr.filters.visible = function( elem ) {
+ return !jQuery.expr.filters.hidden( elem );
+ };
+}
+
+// These hooks are used by animate to expand properties
+jQuery.each({
+ margin: "",
+ padding: "",
+ border: "Width"
+}, function( prefix, suffix ) {
+
+ jQuery.cssHooks[ prefix + suffix ] = {
+ expand: function( value ) {
+ var i,
+
+ // assumes a single number if not a string
+ parts = typeof value === "string" ? value.split(" ") : [ value ],
+ expanded = {};
+
+ for ( i = 0; i < 4; i++ ) {
+ expanded[ prefix + cssExpand[ i ] + suffix ] =
+ parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
+ }
+
+ return expanded;
+ }
+ };
+});
+
+
+
+
+var r20 = /%20/g,
+ rbracket = /\[\]$/,
+ rCRLF = /\r?\n/g,
+ rhash = /#.*$/,
+ rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
+ rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
+ // #7653, #8125, #8152: local protocol detection
+ rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,
+ rnoContent = /^(?:GET|HEAD)$/,
+ rprotocol = /^\/\//,
+ rquery = /\?/,
+ rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
+ rselectTextarea = /^(?:select|textarea)/i,
+ rspacesAjax = /\s+/,
+ rts = /([?&])_=[^&]*/,
+ rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,
+
+ // Keep a copy of the old load method
+ _load = jQuery.fn.load,
+
+ /* Prefilters
+ * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+ * 2) These are called:
+ * - BEFORE asking for a transport
+ * - AFTER param serialization (s.data is a string if s.processData is true)
+ * 3) key is the dataType
+ * 4) the catchall symbol "*" can be used
+ * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+ */
+ prefilters = {},
+
+ /* Transports bindings
+ * 1) key is the dataType
+ * 2) the catchall symbol "*" can be used
+ * 3) selection will start with transport dataType and THEN go to "*" if needed
+ */
+ transports = {},
+
+ // Document location
+ ajaxLocation,
+
+ // Document location segments
+ ajaxLocParts,
+
+ // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+ allTypes = ["*/"] + ["*"];
+
+// #8138, IE may throw an exception when accessing
+// a field from window.location if document.domain has been set
+try {
+ ajaxLocation = location.href;
+} catch( e ) {
+ // Use the href attribute of an A element
+ // since IE will modify it given document.location
+ ajaxLocation = document.createElement( "a" );
+ ajaxLocation.href = "";
+ ajaxLocation = ajaxLocation.href;
+}
+
+// Segment location into parts
+ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+function addToPrefiltersOrTransports( structure ) {
+
+ // dataTypeExpression is optional and defaults to "*"
+ return function( dataTypeExpression, func ) {
+
+ if ( typeof dataTypeExpression !== "string" ) {
+ func = dataTypeExpression;
+ dataTypeExpression = "*";
+ }
+
+ if ( jQuery.isFunction( func ) ) {
+ var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),
+ i = 0,
+ length = dataTypes.length,
+ dataType,
+ list,
+ placeBefore;
+
+ // For each dataType in the dataTypeExpression
+ for ( ; i < length; i++ ) {
+ dataType = dataTypes[ i ];
+ // We control if we're asked to add before
+ // any existing element
+ placeBefore = /^\+/.test( dataType );
+ if ( placeBefore ) {
+ dataType = dataType.substr( 1 ) || "*";
+ }
+ list = structure[ dataType ] = structure[ dataType ] || [];
+ // then we add to the structure accordingly
+ list[ placeBefore ? "unshift" : "push" ]( func );
+ }
+ }
+ };
+}
+
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
+ dataType /* internal */, inspected /* internal */ ) {
+
+ dataType = dataType || options.dataTypes[ 0 ];
+ inspected = inspected || {};
+
+ inspected[ dataType ] = true;
+
+ var list = structure[ dataType ],
+ i = 0,
+ length = list ? list.length : 0,
+ executeOnly = ( structure === prefilters ),
+ selection;
+
+ for ( ; i < length && ( executeOnly || !selection ); i++ ) {
+ selection = list[ i ]( options, originalOptions, jqXHR );
+ // If we got redirected to another dataType
+ // we try there if executing only and not done already
+ if ( typeof selection === "string" ) {
+ if ( !executeOnly || inspected[ selection ] ) {
+ selection = undefined;
+ } else {
+ options.dataTypes.unshift( selection );
+ selection = inspectPrefiltersOrTransports(
+ structure, options, originalOptions, jqXHR, selection, inspected );
+ }
+ }
+ }
+ // If we're only executing or nothing was selected
+ // we try the catchall dataType if not done already
+ if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
+ selection = inspectPrefiltersOrTransports(
+ structure, options, originalOptions, jqXHR, "*", inspected );
+ }
+ // unnecessary when only executing (prefilters)
+ // but it'll be ignored by the caller in that case
+ return selection;
+}
+
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+function ajaxExtend( target, src ) {
+ var key, deep,
+ flatOptions = jQuery.ajaxSettings.flatOptions || {};
+ for ( key in src ) {
+ if ( src[ key ] !== undefined ) {
+ ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
+ }
+ }
+ if ( deep ) {
+ jQuery.extend( true, target, deep );
+ }
+}
+
+jQuery.fn.extend({
+ load: function( url, params, callback ) {
+ if ( typeof url !== "string" && _load ) {
+ return _load.apply( this, arguments );
+
+ // Don't do a request if no elements are being requested
+ } else if ( !this.length ) {
+ return this;
+ }
+
+ var off = url.indexOf( " " );
+ if ( off >= 0 ) {
+ var selector = url.slice( off, url.length );
+ url = url.slice( 0, off );
+ }
+
+ // Default to a GET request
+ var type = "GET";
+
+ // If the second parameter was provided
+ if ( params ) {
+ // If it's a function
+ if ( jQuery.isFunction( params ) ) {
+ // We assume that it's the callback
+ callback = params;
+ params = undefined;
+
+ // Otherwise, build a param string
+ } else if ( typeof params === "object" ) {
+ params = jQuery.param( params, jQuery.ajaxSettings.traditional );
+ type = "POST";
+ }
+ }
+
+ var self = this;
+
+ // Request the remote document
+ jQuery.ajax({
+ url: url,
+ type: type,
+ dataType: "html",
+ data: params,
+ // Complete callback (responseText is used internally)
+ complete: function( jqXHR, status, responseText ) {
+ // Store the response as specified by the jqXHR object
+ responseText = jqXHR.responseText;
+ // If successful, inject the HTML into all the matched elements
+ if ( jqXHR.isResolved() ) {
+ // #4825: Get the actual response in case
+ // a dataFilter is present in ajaxSettings
+ jqXHR.done(function( r ) {
+ responseText = r;
+ });
+ // See if a selector was specified
+ self.html( selector ?
+ // Create a dummy div to hold the results
+ jQuery("<div>")
+ // inject the contents of the document in, removing the scripts
+ // to avoid any 'Permission Denied' errors in IE
+ .append(responseText.replace(rscript, ""))
+
+ // Locate the specified elements
+ .find(selector) :
+
+ // If not, just inject the full result
+ responseText );
+ }
+
+ if ( callback ) {
+ self.each( callback, [ responseText, status, jqXHR ] );
+ }
+ }
+ });
+
+ return this;
+ },
+
+ serialize: function() {
+ return jQuery.param( this.serializeArray() );
+ },
+
+ serializeArray: function() {
+ return this.map(function(){
+ return this.elements ? jQuery.makeArray( this.elements ) : this;
+ })
+ .filter(function(){
+ return this.name && !this.disabled &&
+ ( this.checked || rselectTextarea.test( this.nodeName ) ||
+ rinput.test( this.type ) );
+ })
+ .map(function( i, elem ){
+ var val = jQuery( this ).val();
+
+ return val == null ?
+ null :
+ jQuery.isArray( val ) ?
+ jQuery.map( val, function( val, i ){
+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }) :
+ { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }).get();
+ }
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
+ jQuery.fn[ o ] = function( f ){
+ return this.on( o, f );
+ };
+});
+
+jQuery.each( [ "get", "post" ], function( i, method ) {
+ jQuery[ method ] = function( url, data, callback, type ) {
+ // shift arguments if data argument was omitted
+ if ( jQuery.isFunction( data ) ) {
+ type = type || callback;
+ callback = data;
+ data = undefined;
+ }
+
+ return jQuery.ajax({
+ type: method,
+ url: url,
+ data: data,
+ success: callback,
+ dataType: type
+ });
+ };
+});
+
+jQuery.extend({
+
+ getScript: function( url, callback ) {
+ return jQuery.get( url, undefined, callback, "script" );
+ },
+
+ getJSON: function( url, data, callback ) {
+ return jQuery.get( url, data, callback, "json" );
+ },
+
+ // Creates a full fledged settings object into target
+ // with both ajaxSettings and settings fields.
+ // If target is omitted, writes into ajaxSettings.
+ ajaxSetup: function( target, settings ) {
+ if ( settings ) {
+ // Building a settings object
+ ajaxExtend( target, jQuery.ajaxSettings );
+ } else {
+ // Extending ajaxSettings
+ settings = target;
+ target = jQuery.ajaxSettings;
+ }
+ ajaxExtend( target, settings );
+ return target;
+ },
+
+ ajaxSettings: {
+ url: ajaxLocation,
+ isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
+ global: true,
+ type: "GET",
+ contentType: "application/x-www-form-urlencoded; charset=UTF-8",
+ processData: true,
+ async: true,
+ /*
+ timeout: 0,
+ data: null,
+ dataType: null,
+ username: null,
+ password: null,
+ cache: null,
+ traditional: false,
+ headers: {},
+ */
+
+ accepts: {
+ xml: "application/xml, text/xml",
+ html: "text/html",
+ text: "text/plain",
+ json: "application/json, text/javascript",
+ "*": allTypes
+ },
+
+ contents: {
+ xml: /xml/,
+ html: /html/,
+ json: /json/
+ },
+
+ responseFields: {
+ xml: "responseXML",
+ text: "responseText"
+ },
+
+ // List of data converters
+ // 1) key format is "source_type destination_type" (a single space in-between)
+ // 2) the catchall symbol "*" can be used for source_type
+ converters: {
+
+ // Convert anything to text
+ "* text": window.String,
+
+ // Text to html (true = no transformation)
+ "text html": true,
+
+ // Evaluate text as a json expression
+ "text json": jQuery.parseJSON,
+
+ // Parse text as xml
+ "text xml": jQuery.parseXML
+ },
+
+ // For options that shouldn't be deep extended:
+ // you can add your own custom options here if
+ // and when you create one that shouldn't be
+ // deep extended (see ajaxExtend)
+ flatOptions: {
+ context: true,
+ url: true
+ }
+ },
+
+ ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+ ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+ // Main method
+ ajax: function( url, options ) {
+
+ // If url is an object, simulate pre-1.5 signature
+ if ( typeof url === "object" ) {
+ options = url;
+ url = undefined;
+ }
+
+ // Force options to be an object
+ options = options || {};
+
+ var // Create the final options object
+ s = jQuery.ajaxSetup( {}, options ),
+ // Callbacks context
+ callbackContext = s.context || s,
+ // Context for global events
+ // It's the callbackContext if one was provided in the options
+ // and if it's a DOM node or a jQuery collection
+ globalEventContext = callbackContext !== s &&
+ ( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
+ jQuery( callbackContext ) : jQuery.event,
+ // Deferreds
+ deferred = jQuery.Deferred(),
+ completeDeferred = jQuery.Callbacks( "once memory" ),
+ // Status-dependent callbacks
+ statusCode = s.statusCode || {},
+ // ifModified key
+ ifModifiedKey,
+ // Headers (they are sent all at once)
+ requestHeaders = {},
+ requestHeadersNames = {},
+ // Response headers
+ responseHeadersString,
+ responseHeaders,
+ // transport
+ transport,
+ // timeout handle
+ timeoutTimer,
+ // Cross-domain detection vars
+ parts,
+ // The jqXHR state
+ state = 0,
+ // To know if global events are to be dispatched
+ fireGlobals,
+ // Loop variable
+ i,
+ // Fake xhr
+ jqXHR = {
+
+ readyState: 0,
+
+ // Caches the header
+ setRequestHeader: function( name, value ) {
+ if ( !state ) {
+ var lname = name.toLowerCase();
+ name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+ requestHeaders[ name ] = value;
+ }
+ return this;
+ },
+
+ // Raw string
+ getAllResponseHeaders: function() {
+ return state === 2 ? responseHeadersString : null;
+ },
+
+ // Builds headers hashtable if needed
+ getResponseHeader: function( key ) {
+ var match;
+ if ( state === 2 ) {
+ if ( !responseHeaders ) {
+ responseHeaders = {};
+ while( ( match = rheaders.exec( responseHeadersString ) ) ) {
+ responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
+ }
+ }
+ match = responseHeaders[ key.toLowerCase() ];
+ }
+ return match === undefined ? null : match;
+ },
+
+ // Overrides response content-type header
+ overrideMimeType: function( type ) {
+ if ( !state ) {
+ s.mimeType = type;
+ }
+ return this;
+ },
+
+ // Cancel the request
+ abort: function( statusText ) {
+ statusText = statusText || "abort";
+ if ( transport ) {
+ transport.abort( statusText );
+ }
+ done( 0, statusText );
+ return this;
+ }
+ };
+
+ // Callback for when everything is done
+ // It is defined here because jslint complains if it is declared
+ // at the end of the function (which would be more logical and readable)
+ function done( status, nativeStatusText, responses, headers ) {
+
+ // Called once
+ if ( state === 2 ) {
+ return;
+ }
+
+ // State is "done" now
+ state = 2;
+
+ // Clear timeout if it exists
+ if ( timeoutTimer ) {
+ clearTimeout( timeoutTimer );
+ }
+
+ // Dereference transport for early garbage collection
+ // (no matter how long the jqXHR object will be used)
+ transport = undefined;
+
+ // Cache response headers
+ responseHeadersString = headers || "";
+
+ // Set readyState
+ jqXHR.readyState = status > 0 ? 4 : 0;
+
+ var isSuccess,
+ success,
+ error,
+ statusText = nativeStatusText,
+ response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,
+ lastModified,
+ etag;
+
+ // If successful, handle type chaining
+ if ( status >= 200 && status < 300 || status === 304 ) {
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+
+ if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) {
+ jQuery.lastModified[ ifModifiedKey ] = lastModified;
+ }
+ if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) {
+ jQuery.etag[ ifModifiedKey ] = etag;
+ }
+ }
+
+ // If not modified
+ if ( status === 304 ) {
+
+ statusText = "notmodified";
+ isSuccess = true;
+
+ // If we have data
+ } else {
+
+ try {
+ success = ajaxConvert( s, response );
+ statusText = "success";
+ isSuccess = true;
+ } catch(e) {
+ // We have a parsererror
+ statusText = "parsererror";
+ error = e;
+ }
+ }
+ } else {
+ // We extract error from statusText
+ // then normalize statusText and status for non-aborts
+ error = statusText;
+ if ( !statusText || status ) {
+ statusText = "error";
+ if ( status < 0 ) {
+ status = 0;
+ }
+ }
+ }
+
+ // Set data for the fake xhr object
+ jqXHR.status = status;
+ jqXHR.statusText = "" + ( nativeStatusText || statusText );
+
+ // Success/Error
+ if ( isSuccess ) {
+ deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+ } else {
+ deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+ }
+
+ // Status-dependent callbacks
+ jqXHR.statusCode( statusCode );
+ statusCode = undefined;
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
+ [ jqXHR, s, isSuccess ? success : error ] );
+ }
+
+ // Complete
+ completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+ // Handle the global AJAX counter
+ if ( !( --jQuery.active ) ) {
+ jQuery.event.trigger( "ajaxStop" );
+ }
+ }
+ }
+
+ // Attach deferreds
+ deferred.promise( jqXHR );
+ jqXHR.success = jqXHR.done;
+ jqXHR.error = jqXHR.fail;
+ jqXHR.complete = completeDeferred.add;
+
+ // Status-dependent callbacks
+ jqXHR.statusCode = function( map ) {
+ if ( map ) {
+ var tmp;
+ if ( state < 2 ) {
+ for ( tmp in map ) {
+ statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
+ }
+ } else {
+ tmp = map[ jqXHR.status ];
+ jqXHR.then( tmp, tmp );
+ }
+ }
+ return this;
+ };
+
+ // Remove hash character (#7531: and string promotion)
+ // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
+ // We also use the url parameter if available
+ s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+
+ // Extract dataTypes list
+ s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax );
+
+ // Determine if a cross-domain request is in order
+ if ( s.crossDomain == null ) {
+ parts = rurl.exec( s.url.toLowerCase() );
+ s.crossDomain = !!( parts &&
+ ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||
+ ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
+ ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
+ );
+ }
+
+ // Convert data if not already a string
+ if ( s.data && s.processData && typeof s.data !== "string" ) {
+ s.data = jQuery.param( s.data, s.traditional );
+ }
+
+ // Apply prefilters
+ inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+ // If request was aborted inside a prefilter, stop there
+ if ( state === 2 ) {
+ return false;
+ }
+
+ // We can fire global events as of now if asked to
+ fireGlobals = s.global;
+
+ // Uppercase the type
+ s.type = s.type.toUpperCase();
+
+ // Determine if request has content
+ s.hasContent = !rnoContent.test( s.type );
+
+ // Watch for a new set of requests
+ if ( fireGlobals && jQuery.active++ === 0 ) {
+ jQuery.event.trigger( "ajaxStart" );
+ }
+
+ // More options handling for requests with no content
+ if ( !s.hasContent ) {
+
+ // If data is available, append data to url
+ if ( s.data ) {
+ s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
+ // #9682: remove data so that it's not used in an eventual retry
+ delete s.data;
+ }
+
+ // Get ifModifiedKey before adding the anti-cache parameter
+ ifModifiedKey = s.url;
+
+ // Add anti-cache in url if needed
+ if ( s.cache === false ) {
+
+ var ts = jQuery.now(),
+ // try replacing _= if it is there
+ ret = s.url.replace( rts, "$1_=" + ts );
+
+ // if nothing was replaced, add timestamp to the end
+ s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
+ }
+ }
+
+ // Set the correct header, if data is being sent
+ if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+ jqXHR.setRequestHeader( "Content-Type", s.contentType );
+ }
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ ifModifiedKey = ifModifiedKey || s.url;
+ if ( jQuery.lastModified[ ifModifiedKey ] ) {
+ jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
+ }
+ if ( jQuery.etag[ ifModifiedKey ] ) {
+ jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
+ }
+ }
+
+ // Set the Accepts header for the server, depending on the dataType
+ jqXHR.setRequestHeader(
+ "Accept",
+ s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
+ s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+ s.accepts[ "*" ]
+ );
+
+ // Check for headers option
+ for ( i in s.headers ) {
+ jqXHR.setRequestHeader( i, s.headers[ i ] );
+ }
+
+ // Allow custom headers/mimetypes and early abort
+ if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+ // Abort if not done already
+ jqXHR.abort();
+ return false;
+
+ }
+
+ // Install callbacks on deferreds
+ for ( i in { success: 1, error: 1, complete: 1 } ) {
+ jqXHR[ i ]( s[ i ] );
+ }
+
+ // Get transport
+ transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+ // If no transport, we auto-abort
+ if ( !transport ) {
+ done( -1, "No Transport" );
+ } else {
+ jqXHR.readyState = 1;
+ // Send global event
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+ }
+ // Timeout
+ if ( s.async && s.timeout > 0 ) {
+ timeoutTimer = setTimeout( function(){
+ jqXHR.abort( "timeout" );
+ }, s.timeout );
+ }
+
+ try {
+ state = 1;
+ transport.send( requestHeaders, done );
+ } catch (e) {
+ // Propagate exception as error if not done
+ if ( state < 2 ) {
+ done( -1, e );
+ // Simply rethrow otherwise
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ return jqXHR;
+ },
+
+ // Serialize an array of form elements or a set of
+ // key/values into a query string
+ param: function( a, traditional ) {
+ var s = [],
+ add = function( key, value ) {
+ // If value is a function, invoke it and return its value
+ value = jQuery.isFunction( value ) ? value() : value;
+ s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+ };
+
+ // Set traditional to true for jQuery <= 1.3.2 behavior.
+ if ( traditional === undefined ) {
+ traditional = jQuery.ajaxSettings.traditional;
+ }
+
+ // If an array was passed in, assume that it is an array of form elements.
+ if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+ // Serialize the form elements
+ jQuery.each( a, function() {
+ add( this.name, this.value );
+ });
+
+ } else {
+ // If traditional, encode the "old" way (the way 1.3.2 or older
+ // did it), otherwise encode params recursively.
+ for ( var prefix in a ) {
+ buildParams( prefix, a[ prefix ], traditional, add );
+ }
+ }
+
+ // Return the resulting serialization
+ return s.join( "&" ).replace( r20, "+" );
+ }
+});
+
+function buildParams( prefix, obj, traditional, add ) {
+ if ( jQuery.isArray( obj ) ) {
+ // Serialize array item.
+ jQuery.each( obj, function( i, v ) {
+ if ( traditional || rbracket.test( prefix ) ) {
+ // Treat each array item as a scalar.
+ add( prefix, v );
+
+ } else {
+ // If array item is non-scalar (array or object), encode its
+ // numeric index to resolve deserialization ambiguity issues.
+ // Note that rack (as of 1.0.0) can't currently deserialize
+ // nested arrays properly, and attempting to do so may cause
+ // a server error. Possible fixes are to modify rack's
+ // deserialization algorithm or to provide an option or flag
+ // to force array serialization to be shallow.
+ buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
+ }
+ });
+
+ } else if ( !traditional && jQuery.type( obj ) === "object" ) {
+ // Serialize object item.
+ for ( var name in obj ) {
+ buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+ }
+
+ } else {
+ // Serialize scalar item.
+ add( prefix, obj );
+ }
+}
+
+// This is still on the jQuery object... for now
+// Want to move this to jQuery.ajax some day
+jQuery.extend({
+
+ // Counter for holding the number of active queries
+ active: 0,
+
+ // Last-Modified header cache for next request
+ lastModified: {},
+ etag: {}
+
+});
+
+/* Handles responses to an ajax request:
+ * - sets all responseXXX fields accordingly
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+
+ var contents = s.contents,
+ dataTypes = s.dataTypes,
+ responseFields = s.responseFields,
+ ct,
+ type,
+ finalDataType,
+ firstDataType;
+
+ // Fill responseXXX fields
+ for ( type in responseFields ) {
+ if ( type in responses ) {
+ jqXHR[ responseFields[type] ] = responses[ type ];
+ }
+ }
+
+ // Remove auto dataType and get content-type in the process
+ while( dataTypes[ 0 ] === "*" ) {
+ dataTypes.shift();
+ if ( ct === undefined ) {
+ ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
+ }
+ }
+
+ // Check if we're dealing with a known content-type
+ if ( ct ) {
+ for ( type in contents ) {
+ if ( contents[ type ] && contents[ type ].test( ct ) ) {
+ dataTypes.unshift( type );
+ break;
+ }
+ }
+ }
+
+ // Check to see if we have a response for the expected dataType
+ if ( dataTypes[ 0 ] in responses ) {
+ finalDataType = dataTypes[ 0 ];
+ } else {
+ // Try convertible dataTypes
+ for ( type in responses ) {
+ if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+ finalDataType = type;
+ break;
+ }
+ if ( !firstDataType ) {
+ firstDataType = type;
+ }
+ }
+ // Or just use first one
+ finalDataType = finalDataType || firstDataType;
+ }
+
+ // If we found a dataType
+ // We add the dataType to the list if needed
+ // and return the corresponding response
+ if ( finalDataType ) {
+ if ( finalDataType !== dataTypes[ 0 ] ) {
+ dataTypes.unshift( finalDataType );
+ }
+ return responses[ finalDataType ];
+ }
+}
+
+// Chain conversions given the request and the original response
+function ajaxConvert( s, response ) {
+
+ // Apply the dataFilter if provided
+ if ( s.dataFilter ) {
+ response = s.dataFilter( response, s.dataType );
+ }
+
+ var dataTypes = s.dataTypes,
+ converters = {},
+ i,
+ key,
+ length = dataTypes.length,
+ tmp,
+ // Current and previous dataTypes
+ current = dataTypes[ 0 ],
+ prev,
+ // Conversion expression
+ conversion,
+ // Conversion function
+ conv,
+ // Conversion functions (transitive conversion)
+ conv1,
+ conv2;
+
+ // For each dataType in the chain
+ for ( i = 1; i < length; i++ ) {
+
+ // Create converters map
+ // with lowercased keys
+ if ( i === 1 ) {
+ for ( key in s.converters ) {
+ if ( typeof key === "string" ) {
+ converters[ key.toLowerCase() ] = s.converters[ key ];
+ }
+ }
+ }
+
+ // Get the dataTypes
+ prev = current;
+ current = dataTypes[ i ];
+
+ // If current is auto dataType, update it to prev
+ if ( current === "*" ) {
+ current = prev;
+ // If no auto and dataTypes are actually different
+ } else if ( prev !== "*" && prev !== current ) {
+
+ // Get the converter
+ conversion = prev + " " + current;
+ conv = converters[ conversion ] || converters[ "* " + current ];
+
+ // If there is no direct converter, search transitively
+ if ( !conv ) {
+ conv2 = undefined;
+ for ( conv1 in converters ) {
+ tmp = conv1.split( " " );
+ if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) {
+ conv2 = converters[ tmp[1] + " " + current ];
+ if ( conv2 ) {
+ conv1 = converters[ conv1 ];
+ if ( conv1 === true ) {
+ conv = conv2;
+ } else if ( conv2 === true ) {
+ conv = conv1;
+ }
+ break;
+ }
+ }
+ }
+ }
+ // If we found no converter, dispatch an error
+ if ( !( conv || conv2 ) ) {
+ jQuery.error( "No conversion from " + conversion.replace(" "," to ") );
+ }
+ // If found converter is not an equivalence
+ if ( conv !== true ) {
+ // Convert with 1 or 2 converters accordingly
+ response = conv ? conv( response ) : conv2( conv1(response) );
+ }
+ }
+ }
+ return response;
+}
+
+
+
+
+var jsc = jQuery.now(),
+ jsre = /(\=)\?(&|$)|\?\?/i;
+
+// Default jsonp settings
+jQuery.ajaxSetup({
+ jsonp: "callback",
+ jsonpCallback: function() {
+ return jQuery.expando + "_" + ( jsc++ );
+ }
+});
+
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+ var inspectData = ( typeof s.data === "string" ) && /^application\/x\-www\-form\-urlencoded/.test( s.contentType );
+
+ if ( s.dataTypes[ 0 ] === "jsonp" ||
+ s.jsonp !== false && ( jsre.test( s.url ) ||
+ inspectData && jsre.test( s.data ) ) ) {
+
+ var responseContainer,
+ jsonpCallback = s.jsonpCallback =
+ jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
+ previous = window[ jsonpCallback ],
+ url = s.url,
+ data = s.data,
+ replace = "$1" + jsonpCallback + "$2";
+
+ if ( s.jsonp !== false ) {
+ url = url.replace( jsre, replace );
+ if ( s.url === url ) {
+ if ( inspectData ) {
+ data = data.replace( jsre, replace );
+ }
+ if ( s.data === data ) {
+ // Add callback manually
+ url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
+ }
+ }
+ }
+
+ s.url = url;
+ s.data = data;
+
+ // Install callback
+ window[ jsonpCallback ] = function( response ) {
+ responseContainer = [ response ];
+ };
+
+ // Clean-up function
+ jqXHR.always(function() {
+ // Set callback back to previous value
+ window[ jsonpCallback ] = previous;
+ // Call if it was a function and we have a response
+ if ( responseContainer && jQuery.isFunction( previous ) ) {
+ window[ jsonpCallback ]( responseContainer[ 0 ] );
+ }
+ });
+
+ // Use data converter to retrieve json after script execution
+ s.converters["script json"] = function() {
+ if ( !responseContainer ) {
+ jQuery.error( jsonpCallback + " was not called" );
+ }
+ return responseContainer[ 0 ];
+ };
+
+ // force json dataType
+ s.dataTypes[ 0 ] = "json";
+
+ // Delegate to script
+ return "script";
+ }
+});
+
+
+
+
+// Install script dataType
+jQuery.ajaxSetup({
+ accepts: {
+ script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
+ },
+ contents: {
+ script: /javascript|ecmascript/
+ },
+ converters: {
+ "text script": function( text ) {
+ jQuery.globalEval( text );
+ return text;
+ }
+ }
+});
+
+// Handle cache's special case and global
+jQuery.ajaxPrefilter( "script", function( s ) {
+ if ( s.cache === undefined ) {
+ s.cache = false;
+ }
+ if ( s.crossDomain ) {
+ s.type = "GET";
+ s.global = false;
+ }
+});
+
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function(s) {
+
+ // This transport only deals with cross domain requests
+ if ( s.crossDomain ) {
+
+ var script,
+ head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
+
+ return {
+
+ send: function( _, callback ) {
+
+ script = document.createElement( "script" );
+
+ script.async = "async";
+
+ if ( s.scriptCharset ) {
+ script.charset = s.scriptCharset;
+ }
+
+ script.src = s.url;
+
+ // Attach handlers for all browsers
+ script.onload = script.onreadystatechange = function( _, isAbort ) {
+
+ if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
+
+ // Handle memory leak in IE
+ script.onload = script.onreadystatechange = null;
+
+ // Remove the script
+ if ( head && script.parentNode ) {
+ head.removeChild( script );
+ }
+
+ // Dereference the script
+ script = undefined;
+
+ // Callback if not abort
+ if ( !isAbort ) {
+ callback( 200, "success" );
+ }
+ }
+ };
+ // Use insertBefore instead of appendChild to circumvent an IE6 bug.
+ // This arises when a base node is used (#2709 and #4378).
+ head.insertBefore( script, head.firstChild );
+ },
+
+ abort: function() {
+ if ( script ) {
+ script.onload( 0, 1 );
+ }
+ }
+ };
+ }
+});
+
+
+
+
+var // #5280: Internet Explorer will keep connections alive if we don't abort on unload
+ xhrOnUnloadAbort = window.ActiveXObject ? function() {
+ // Abort all pending requests
+ for ( var key in xhrCallbacks ) {
+ xhrCallbacks[ key ]( 0, 1 );
+ }
+ } : false,
+ xhrId = 0,
+ xhrCallbacks;
+
+// Functions to create xhrs
+function createStandardXHR() {
+ try {
+ return new window.XMLHttpRequest();
+ } catch( e ) {}
+}
+
+function createActiveXHR() {
+ try {
+ return new window.ActiveXObject( "Microsoft.XMLHTTP" );
+ } catch( e ) {}
+}
+
+// Create the request object
+// (This is still attached to ajaxSettings for backward compatibility)
+jQuery.ajaxSettings.xhr = window.ActiveXObject ?
+ /* Microsoft failed to properly
+ * implement the XMLHttpRequest in IE7 (can't request local files),
+ * so we use the ActiveXObject when it is available
+ * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
+ * we need a fallback.
+ */
+ function() {
+ return !this.isLocal && createStandardXHR() || createActiveXHR();
+ } :
+ // For all other browsers, use the standard XMLHttpRequest object
+ createStandardXHR;
+
+// Determine support properties
+(function( xhr ) {
+ jQuery.extend( jQuery.support, {
+ ajax: !!xhr,
+ cors: !!xhr && ( "withCredentials" in xhr )
+ });
+})( jQuery.ajaxSettings.xhr() );
+
+// Create transport if the browser can provide an xhr
+if ( jQuery.support.ajax ) {
+
+ jQuery.ajaxTransport(function( s ) {
+ // Cross domain only allowed if supported through XMLHttpRequest
+ if ( !s.crossDomain || jQuery.support.cors ) {
+
+ var callback;
+
+ return {
+ send: function( headers, complete ) {
+
+ // Get a new xhr
+ var xhr = s.xhr(),
+ handle,
+ i;
+
+ // Open the socket
+ // Passing null username, generates a login popup on Opera (#2865)
+ if ( s.username ) {
+ xhr.open( s.type, s.url, s.async, s.username, s.password );
+ } else {
+ xhr.open( s.type, s.url, s.async );
+ }
+
+ // Apply custom fields if provided
+ if ( s.xhrFields ) {
+ for ( i in s.xhrFields ) {
+ xhr[ i ] = s.xhrFields[ i ];
+ }
+ }
+
+ // Override mime type if needed
+ if ( s.mimeType && xhr.overrideMimeType ) {
+ xhr.overrideMimeType( s.mimeType );
+ }
+
+ // X-Requested-With header
+ // For cross-domain requests, seeing as conditions for a preflight are
+ // akin to a jigsaw puzzle, we simply never set it to be sure.
+ // (it can always be set on a per-request basis or even using ajaxSetup)
+ // For same-domain requests, won't change header if already provided.
+ if ( !s.crossDomain && !headers["X-Requested-With"] ) {
+ headers[ "X-Requested-With" ] = "XMLHttpRequest";
+ }
+
+ // Need an extra try/catch for cross domain requests in Firefox 3
+ try {
+ for ( i in headers ) {
+ xhr.setRequestHeader( i, headers[ i ] );
+ }
+ } catch( _ ) {}
+
+ // Do send the request
+ // This may raise an exception which is actually
+ // handled in jQuery.ajax (so no try/catch here)
+ xhr.send( ( s.hasContent && s.data ) || null );
+
+ // Listener
+ callback = function( _, isAbort ) {
+
+ var status,
+ statusText,
+ responseHeaders,
+ responses,
+ xml;
+
+ // Firefox throws exceptions when accessing properties
+ // of an xhr when a network error occured
+ // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
+ try {
+
+ // Was never called and is aborted or complete
+ if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
+
+ // Only called once
+ callback = undefined;
+
+ // Do not keep as active anymore
+ if ( handle ) {
+ xhr.onreadystatechange = jQuery.noop;
+ if ( xhrOnUnloadAbort ) {
+ delete xhrCallbacks[ handle ];
+ }
+ }
+
+ // If it's an abort
+ if ( isAbort ) {
+ // Abort it manually if needed
+ if ( xhr.readyState !== 4 ) {
+ xhr.abort();
+ }
+ } else {
+ status = xhr.status;
+ responseHeaders = xhr.getAllResponseHeaders();
+ responses = {};
+ xml = xhr.responseXML;
+
+ // Construct response list
+ if ( xml && xml.documentElement /* #4958 */ ) {
+ responses.xml = xml;
+ }
+
+ // When requesting binary data, IE6-9 will throw an exception
+ // on any attempt to access responseText (#11426)
+ try {
+ responses.text = xhr.responseText;
+ } catch( _ ) {
+ }
+
+ // Firefox throws an exception when accessing
+ // statusText for faulty cross-domain requests
+ try {
+ statusText = xhr.statusText;
+ } catch( e ) {
+ // We normalize with Webkit giving an empty statusText
+ statusText = "";
+ }
+
+ // Filter status for non standard behaviors
+
+ // If the request is local and we have data: assume a success
+ // (success with no data won't get notified, that's the best we
+ // can do given current implementations)
+ if ( !status && s.isLocal && !s.crossDomain ) {
+ status = responses.text ? 200 : 404;
+ // IE - #1450: sometimes returns 1223 when it should be 204
+ } else if ( status === 1223 ) {
+ status = 204;
+ }
+ }
+ }
+ } catch( firefoxAccessException ) {
+ if ( !isAbort ) {
+ complete( -1, firefoxAccessException );
+ }
+ }
+
+ // Call complete if needed
+ if ( responses ) {
+ complete( status, statusText, responses, responseHeaders );
+ }
+ };
+
+ // if we're in sync mode or it's in cache
+ // and has been retrieved directly (IE6 & IE7)
+ // we need to manually fire the callback
+ if ( !s.async || xhr.readyState === 4 ) {
+ callback();
+ } else {
+ handle = ++xhrId;
+ if ( xhrOnUnloadAbort ) {
+ // Create the active xhrs callbacks list if needed
+ // and attach the unload handler
+ if ( !xhrCallbacks ) {
+ xhrCallbacks = {};
+ jQuery( window ).unload( xhrOnUnloadAbort );
+ }
+ // Add to list of active xhrs callbacks
+ xhrCallbacks[ handle ] = callback;
+ }
+ xhr.onreadystatechange = callback;
+ }
+ },
+
+ abort: function() {
+ if ( callback ) {
+ callback(0,1);
+ }
+ }
+ };
+ }
+ });
+}
+
+
+
+
+var elemdisplay = {},
+ iframe, iframeDoc,
+ rfxtypes = /^(?:toggle|show|hide)$/,
+ rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,
+ timerId,
+ fxAttrs = [
+ // height animations
+ [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
+ // width animations
+ [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
+ // opacity animations
+ [ "opacity" ]
+ ],
+ fxNow;
+
+jQuery.fn.extend({
+ show: function( speed, easing, callback ) {
+ var elem, display;
+
+ if ( speed || speed === 0 ) {
+ return this.animate( genFx("show", 3), speed, easing, callback );
+
+ } else {
+ for ( var i = 0, j = this.length; i < j; i++ ) {
+ elem = this[ i ];
+
+ if ( elem.style ) {
+ display = elem.style.display;
+
+ // Reset the inline display of this element to learn if it is
+ // being hidden by cascaded rules or not
+ if ( !jQuery._data(elem, "olddisplay") && display === "none" ) {
+ display = elem.style.display = "";
+ }
+
+ // Set elements which have been overridden with display: none
+ // in a stylesheet to whatever the default browser style is
+ // for such an element
+ if ( (display === "" && jQuery.css(elem, "display") === "none") ||
+ !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
+ jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
+ }
+ }
+ }
+
+ // Set the display of most of the elements in a second loop
+ // to avoid the constant reflow
+ for ( i = 0; i < j; i++ ) {
+ elem = this[ i ];
+
+ if ( elem.style ) {
+ display = elem.style.display;
+
+ if ( display === "" || display === "none" ) {
+ elem.style.display = jQuery._data( elem, "olddisplay" ) || "";
+ }
+ }
+ }
+
+ return this;
+ }
+ },
+
+ hide: function( speed, easing, callback ) {
+ if ( speed || speed === 0 ) {
+ return this.animate( genFx("hide", 3), speed, easing, callback);
+
+ } else {
+ var elem, display,
+ i = 0,
+ j = this.length;
+
+ for ( ; i < j; i++ ) {
+ elem = this[i];
+ if ( elem.style ) {
+ display = jQuery.css( elem, "display" );
+
+ if ( display !== "none" && !jQuery._data( elem, "olddisplay" ) ) {
+ jQuery._data( elem, "olddisplay", display );
+ }
+ }
+ }
+
+ // Set the display of the elements in a second loop
+ // to avoid the constant reflow
+ for ( i = 0; i < j; i++ ) {
+ if ( this[i].style ) {
+ this[i].style.display = "none";
+ }
+ }
+
+ return this;
+ }
+ },
+
+ // Save the old toggle function
+ _toggle: jQuery.fn.toggle,
+
+ toggle: function( fn, fn2, callback ) {
+ var bool = typeof fn === "boolean";
+
+ if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
+ this._toggle.apply( this, arguments );
+
+ } else if ( fn == null || bool ) {
+ this.each(function() {
+ var state = bool ? fn : jQuery(this).is(":hidden");
+ jQuery(this)[ state ? "show" : "hide" ]();
+ });
+
+ } else {
+ this.animate(genFx("toggle", 3), fn, fn2, callback);
+ }
+
+ return this;
+ },
+
+ fadeTo: function( speed, to, easing, callback ) {
+ return this.filter(":hidden").css("opacity", 0).show().end()
+ .animate({opacity: to}, speed, easing, callback);
+ },
+
+ animate: function( prop, speed, easing, callback ) {
+ var optall = jQuery.speed( speed, easing, callback );
+
+ if ( jQuery.isEmptyObject( prop ) ) {
+ return this.each( optall.complete, [ false ] );
+ }
+
+ // Do not change referenced properties as per-property easing will be lost
+ prop = jQuery.extend( {}, prop );
+
+ function doAnimation() {
+ // XXX 'this' does not always have a nodeName when running the
+ // test suite
+
+ if ( optall.queue === false ) {
+ jQuery._mark( this );
+ }
+
+ var opt = jQuery.extend( {}, optall ),
+ isElement = this.nodeType === 1,
+ hidden = isElement && jQuery(this).is(":hidden"),
+ name, val, p, e, hooks, replace,
+ parts, start, end, unit,
+ method;
+
+ // will store per property easing and be used to determine when an animation is complete
+ opt.animatedProperties = {};
+
+ // first pass over propertys to expand / normalize
+ for ( p in prop ) {
+ name = jQuery.camelCase( p );
+ if ( p !== name ) {
+ prop[ name ] = prop[ p ];
+ delete prop[ p ];
+ }
+
+ if ( ( hooks = jQuery.cssHooks[ name ] ) && "expand" in hooks ) {
+ replace = hooks.expand( prop[ name ] );
+ delete prop[ name ];
+
+ // not quite $.extend, this wont overwrite keys already present.
+ // also - reusing 'p' from above because we have the correct "name"
+ for ( p in replace ) {
+ if ( ! ( p in prop ) ) {
+ prop[ p ] = replace[ p ];
+ }
+ }
+ }
+ }
+
+ for ( name in prop ) {
+ val = prop[ name ];
+ // easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)
+ if ( jQuery.isArray( val ) ) {
+ opt.animatedProperties[ name ] = val[ 1 ];
+ val = prop[ name ] = val[ 0 ];
+ } else {
+ opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';
+ }
+
+ if ( val === "hide" && hidden || val === "show" && !hidden ) {
+ return opt.complete.call( this );
+ }
+
+ if ( isElement && ( name === "height" || name === "width" ) ) {
+ // Make sure that nothing sneaks out
+ // Record all 3 overflow attributes because IE does not
+ // change the overflow attribute when overflowX and
+ // overflowY are set to the same value
+ opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];
+
+ // Set display property to inline-block for height/width
+ // animations on inline elements that are having width/height animated
+ if ( jQuery.css( this, "display" ) === "inline" &&
+ jQuery.css( this, "float" ) === "none" ) {
+
+ // inline-level elements accept inline-block;
+ // block-level elements need to be inline with layout
+ if ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === "inline" ) {
+ this.style.display = "inline-block";
+
+ } else {
+ this.style.zoom = 1;
+ }
+ }
+ }
+ }
+
+ if ( opt.overflow != null ) {
+ this.style.overflow = "hidden";
+ }
+
+ for ( p in prop ) {
+ e = new jQuery.fx( this, opt, p );
+ val = prop[ p ];
+
+ if ( rfxtypes.test( val ) ) {
+
+ // Tracks whether to show or hide based on private
+ // data attached to the element
+ method = jQuery._data( this, "toggle" + p ) || ( val === "toggle" ? hidden ? "show" : "hide" : 0 );
+ if ( method ) {
+ jQuery._data( this, "toggle" + p, method === "show" ? "hide" : "show" );
+ e[ method ]();
+ } else {
+ e[ val ]();
+ }
+
+ } else {
+ parts = rfxnum.exec( val );
+ start = e.cur();
+
+ if ( parts ) {
+ end = parseFloat( parts[2] );
+ unit = parts[3] || ( jQuery.cssNumber[ p ] ? "" : "px" );
+
+ // We need to compute starting value
+ if ( unit !== "px" ) {
+ jQuery.style( this, p, (end || 1) + unit);
+ start = ( (end || 1) / e.cur() ) * start;
+ jQuery.style( this, p, start + unit);
+ }
+
+ // If a +=/-= token was provided, we're doing a relative animation
+ if ( parts[1] ) {
+ end = ( (parts[ 1 ] === "-=" ? -1 : 1) * end ) + start;
+ }
+
+ e.custom( start, end, unit );
+
+ } else {
+ e.custom( start, val, "" );
+ }
+ }
+ }
+
+ // For JS strict compliance
+ return true;
+ }
+
+ return optall.queue === false ?
+ this.each( doAnimation ) :
+ this.queue( optall.queue, doAnimation );
+ },
+
+ stop: function( type, clearQueue, gotoEnd ) {
+ if ( typeof type !== "string" ) {
+ gotoEnd = clearQueue;
+ clearQueue = type;
+ type = undefined;
+ }
+ if ( clearQueue && type !== false ) {
+ this.queue( type || "fx", [] );
+ }
+
+ return this.each(function() {
+ var index,
+ hadTimers = false,
+ timers = jQuery.timers,
+ data = jQuery._data( this );
+
+ // clear marker counters if we know they won't be
+ if ( !gotoEnd ) {
+ jQuery._unmark( true, this );
+ }
+
+ function stopQueue( elem, data, index ) {
+ var hooks = data[ index ];
+ jQuery.removeData( elem, index, true );
+ hooks.stop( gotoEnd );
+ }
+
+ if ( type == null ) {
+ for ( index in data ) {
+ if ( data[ index ] && data[ index ].stop && index.indexOf(".run") === index.length - 4 ) {
+ stopQueue( this, data, index );
+ }
+ }
+ } else if ( data[ index = type + ".run" ] && data[ index ].stop ){
+ stopQueue( this, data, index );
+ }
+
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
+ if ( gotoEnd ) {
+
+ // force the next step to be the last
+ timers[ index ]( true );
+ } else {
+ timers[ index ].saveState();
+ }
+ hadTimers = true;
+ timers.splice( index, 1 );
+ }
+ }
+
+ // start the next in the queue if the last step wasn't forced
+ // timers currently will call their complete callbacks, which will dequeue
+ // but only if they were gotoEnd
+ if ( !( gotoEnd && hadTimers ) ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ }
+
+});
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+ setTimeout( clearFxNow, 0 );
+ return ( fxNow = jQuery.now() );
+}
+
+function clearFxNow() {
+ fxNow = undefined;
+}
+
+// Generate parameters to create a standard animation
+function genFx( type, num ) {
+ var obj = {};
+
+ jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {
+ obj[ this ] = type;
+ });
+
+ return obj;
+}
+
+// Generate shortcuts for custom animations
+jQuery.each({
+ slideDown: genFx( "show", 1 ),
+ slideUp: genFx( "hide", 1 ),
+ slideToggle: genFx( "toggle", 1 ),
+ fadeIn: { opacity: "show" },
+ fadeOut: { opacity: "hide" },
+ fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return this.animate( props, speed, easing, callback );
+ };
+});
+
+jQuery.extend({
+ speed: function( speed, easing, fn ) {
+ var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+ complete: fn || !fn && easing ||
+ jQuery.isFunction( speed ) && speed,
+ duration: speed,
+ easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+ };
+
+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+ opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+
+ // normalize opt.queue - true/undefined/null -> "fx"
+ if ( opt.queue == null || opt.queue === true ) {
+ opt.queue = "fx";
+ }
+
+ // Queueing
+ opt.old = opt.complete;
+
+ opt.complete = function( noUnmark ) {
+ if ( jQuery.isFunction( opt.old ) ) {
+ opt.old.call( this );
+ }
+
+ if ( opt.queue ) {
+ jQuery.dequeue( this, opt.queue );
+ } else if ( noUnmark !== false ) {
+ jQuery._unmark( this );
+ }
+ };
+
+ return opt;
+ },
+
+ easing: {
+ linear: function( p ) {
+ return p;
+ },
+ swing: function( p ) {
+ return ( -Math.cos( p*Math.PI ) / 2 ) + 0.5;
+ }
+ },
+
+ timers: [],
+
+ fx: function( elem, options, prop ) {
+ this.options = options;
+ this.elem = elem;
+ this.prop = prop;
+
+ options.orig = options.orig || {};
+ }
+
+});
+
+jQuery.fx.prototype = {
+ // Simple function for setting a style value
+ update: function() {
+ if ( this.options.step ) {
+ this.options.step.call( this.elem, this.now, this );
+ }
+
+ ( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );
+ },
+
+ // Get the current size
+ cur: function() {
+ if ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {
+ return this.elem[ this.prop ];
+ }
+
+ var parsed,
+ r = jQuery.css( this.elem, this.prop );
+ // Empty strings, null, undefined and "auto" are converted to 0,
+ // complex values such as "rotate(1rad)" are returned as is,
+ // simple values such as "10px" are parsed to Float.
+ return isNaN( parsed = parseFloat( r ) ) ? !r || r === "auto" ? 0 : r : parsed;
+ },
+
+ // Start an animation from one number to another
+ custom: function( from, to, unit ) {
+ var self = this,
+ fx = jQuery.fx;
+
+ this.startTime = fxNow || createFxNow();
+ this.end = to;
+ this.now = this.start = from;
+ this.pos = this.state = 0;
+ this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );
+
+ function t( gotoEnd ) {
+ return self.step( gotoEnd );
+ }
+
+ t.queue = this.options.queue;
+ t.elem = this.elem;
+ t.saveState = function() {
+ if ( jQuery._data( self.elem, "fxshow" + self.prop ) === undefined ) {
+ if ( self.options.hide ) {
+ jQuery._data( self.elem, "fxshow" + self.prop, self.start );
+ } else if ( self.options.show ) {
+ jQuery._data( self.elem, "fxshow" + self.prop, self.end );
+ }
+ }
+ };
+
+ if ( t() && jQuery.timers.push(t) && !timerId ) {
+ timerId = setInterval( fx.tick, fx.interval );
+ }
+ },
+
+ // Simple 'show' function
+ show: function() {
+ var dataShow = jQuery._data( this.elem, "fxshow" + this.prop );
+
+ // Remember where we started, so that we can go back to it later
+ this.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );
+ this.options.show = true;
+
+ // Begin the animation
+ // Make sure that we start at a small width/height to avoid any flash of content
+ if ( dataShow !== undefined ) {
+ // This show is picking up where a previous hide or show left off
+ this.custom( this.cur(), dataShow );
+ } else {
+ this.custom( this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur() );
+ }
+
+ // Start by showing the element
+ jQuery( this.elem ).show();
+ },
+
+ // Simple 'hide' function
+ hide: function() {
+ // Remember where we started, so that we can go back to it later
+ this.options.orig[ this.prop ] = jQuery._data( this.elem, "fxshow" + this.prop ) || jQuery.style( this.elem, this.prop );
+ this.options.hide = true;
+
+ // Begin the animation
+ this.custom( this.cur(), 0 );
+ },
+
+ // Each step of an animation
+ step: function( gotoEnd ) {
+ var p, n, complete,
+ t = fxNow || createFxNow(),
+ done = true,
+ elem = this.elem,
+ options = this.options;
+
+ if ( gotoEnd || t >= options.duration + this.startTime ) {
+ this.now = this.end;
+ this.pos = this.state = 1;
+ this.update();
+
+ options.animatedProperties[ this.prop ] = true;
+
+ for ( p in options.animatedProperties ) {
+ if ( options.animatedProperties[ p ] !== true ) {
+ done = false;
+ }
+ }
+
+ if ( done ) {
+ // Reset the overflow
+ if ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {
+
+ jQuery.each( [ "", "X", "Y" ], function( index, value ) {
+ elem.style[ "overflow" + value ] = options.overflow[ index ];
+ });
+ }
+
+ // Hide the element if the "hide" operation was done
+ if ( options.hide ) {
+ jQuery( elem ).hide();
+ }
+
+ // Reset the properties, if the item has been hidden or shown
+ if ( options.hide || options.show ) {
+ for ( p in options.animatedProperties ) {
+ jQuery.style( elem, p, options.orig[ p ] );
+ jQuery.removeData( elem, "fxshow" + p, true );
+ // Toggle data is no longer needed
+ jQuery.removeData( elem, "toggle" + p, true );
+ }
+ }
+
+ // Execute the complete function
+ // in the event that the complete function throws an exception
+ // we must ensure it won't be called twice. #5684
+
+ complete = options.complete;
+ if ( complete ) {
+
+ options.complete = false;
+ complete.call( elem );
+ }
+ }
+
+ return false;
+
+ } else {
+ // classical easing cannot be used with an Infinity duration
+ if ( options.duration == Infinity ) {
+ this.now = t;
+ } else {
+ n = t - this.startTime;
+ this.state = n / options.duration;
+
+ // Perform the easing function, defaults to swing
+ this.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );
+ this.now = this.start + ( (this.end - this.start) * this.pos );
+ }
+ // Perform the next step of the animation
+ this.update();
+ }
+
+ return true;
+ }
+};
+
+jQuery.extend( jQuery.fx, {
+ tick: function() {
+ var timer,
+ timers = jQuery.timers,
+ i = 0;
+
+ for ( ; i < timers.length; i++ ) {
+ timer = timers[ i ];
+ // Checks the timer has not already been removed
+ if ( !timer() && timers[ i ] === timer ) {
+ timers.splice( i--, 1 );
+ }
+ }
+
+ if ( !timers.length ) {
+ jQuery.fx.stop();
+ }
+ },
+
+ interval: 13,
+
+ stop: function() {
+ clearInterval( timerId );
+ timerId = null;
+ },
+
+ speeds: {
+ slow: 600,
+ fast: 200,
+ // Default speed
+ _default: 400
+ },
+
+ step: {
+ opacity: function( fx ) {
+ jQuery.style( fx.elem, "opacity", fx.now );
+ },
+
+ _default: function( fx ) {
+ if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
+ fx.elem.style[ fx.prop ] = fx.now + fx.unit;
+ } else {
+ fx.elem[ fx.prop ] = fx.now;
+ }
+ }
+ }
+});
+
+// Ensure props that can't be negative don't go there on undershoot easing
+jQuery.each( fxAttrs.concat.apply( [], fxAttrs ), function( i, prop ) {
+ // exclude marginTop, marginLeft, marginBottom and marginRight from this list
+ if ( prop.indexOf( "margin" ) ) {
+ jQuery.fx.step[ prop ] = function( fx ) {
+ jQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );
+ };
+ }
+});
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.animated = function( elem ) {
+ return jQuery.grep(jQuery.timers, function( fn ) {
+ return elem === fn.elem;
+ }).length;
+ };
+}
+
+// Try to restore the default display value of an element
+function defaultDisplay( nodeName ) {
+
+ if ( !elemdisplay[ nodeName ] ) {
+
+ var body = document.body,
+ elem = jQuery( "<" + nodeName + ">" ).appendTo( body ),
+ display = elem.css( "display" );
+ elem.remove();
+
+ // If the simple way fails,
+ // get element's real default display by attaching it to a temp iframe
+ if ( display === "none" || display === "" ) {
+ // No iframe to use yet, so create it
+ if ( !iframe ) {
+ iframe = document.createElement( "iframe" );
+ iframe.frameBorder = iframe.width = iframe.height = 0;
+ }
+
+ body.appendChild( iframe );
+
+ // Create a cacheable copy of the iframe document on first call.
+ // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML
+ // document to it; WebKit & Firefox won't allow reusing the iframe document.
+ if ( !iframeDoc || !iframe.createElement ) {
+ iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
+ iframeDoc.write( ( jQuery.support.boxModel ? "<!doctype html>" : "" ) + "<html><body>" );
+ iframeDoc.close();
+ }
+
+ elem = iframeDoc.createElement( nodeName );
+
+ iframeDoc.body.appendChild( elem );
+
+ display = jQuery.css( elem, "display" );
+ body.removeChild( iframe );
+ }
+
+ // Store the correct default display
+ elemdisplay[ nodeName ] = display;
+ }
+
+ return elemdisplay[ nodeName ];
+}
+
+
+
+
+var getOffset,
+ rtable = /^t(?:able|d|h)$/i,
+ rroot = /^(?:body|html)$/i;
+
+if ( "getBoundingClientRect" in document.documentElement ) {
+ getOffset = function( elem, doc, docElem, box ) {
+ try {
+ box = elem.getBoundingClientRect();
+ } catch(e) {}
+
+ // Make sure we're not dealing with a disconnected DOM node
+ if ( !box || !jQuery.contains( docElem, elem ) ) {
+ return box ? { top: box.top, left: box.left } : { top: 0, left: 0 };
+ }
+
+ var body = doc.body,
+ win = getWindow( doc ),
+ clientTop = docElem.clientTop || body.clientTop || 0,
+ clientLeft = docElem.clientLeft || body.clientLeft || 0,
+ scrollTop = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop,
+ scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,
+ top = box.top + scrollTop - clientTop,
+ left = box.left + scrollLeft - clientLeft;
+
+ return { top: top, left: left };
+ };
+
+} else {
+ getOffset = function( elem, doc, docElem ) {
+ var computedStyle,
+ offsetParent = elem.offsetParent,
+ prevOffsetParent = elem,
+ body = doc.body,
+ defaultView = doc.defaultView,
+ prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
+ top = elem.offsetTop,
+ left = elem.offsetLeft;
+
+ while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
+ if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
+ break;
+ }
+
+ computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
+ top -= elem.scrollTop;
+ left -= elem.scrollLeft;
+
+ if ( elem === offsetParent ) {
+ top += elem.offsetTop;
+ left += elem.offsetLeft;
+
+ if ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
+ top += parseFloat( computedStyle.borderTopWidth ) || 0;
+ left += parseFloat( computedStyle.borderLeftWidth ) || 0;
+ }
+
+ prevOffsetParent = offsetParent;
+ offsetParent = elem.offsetParent;
+ }
+
+ if ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
+ top += parseFloat( computedStyle.borderTopWidth ) || 0;
+ left += parseFloat( computedStyle.borderLeftWidth ) || 0;
+ }
+
+ prevComputedStyle = computedStyle;
+ }
+
+ if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
+ top += body.offsetTop;
+ left += body.offsetLeft;
+ }
+
+ if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
+ top += Math.max( docElem.scrollTop, body.scrollTop );
+ left += Math.max( docElem.scrollLeft, body.scrollLeft );
+ }
+
+ return { top: top, left: left };
+ };
+}
+
+jQuery.fn.offset = function( options ) {
+ if ( arguments.length ) {
+ return options === undefined ?
+ this :
+ this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ var elem = this[0],
+ doc = elem && elem.ownerDocument;
+
+ if ( !doc ) {
+ return null;
+ }
+
+ if ( elem === doc.body ) {
+ return jQuery.offset.bodyOffset( elem );
+ }
+
+ return getOffset( elem, doc, doc.documentElement );
+};
+
+jQuery.offset = {
+
+ bodyOffset: function( body ) {
+ var top = body.offsetTop,
+ left = body.offsetLeft;
+
+ if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {
+ top += parseFloat( jQuery.css(body, "marginTop") ) || 0;
+ left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
+ }
+
+ return { top: top, left: left };
+ },
+
+ setOffset: function( elem, options, i ) {
+ var position = jQuery.css( elem, "position" );
+
+ // set position first, in-case top/left are set even on static elem
+ if ( position === "static" ) {
+ elem.style.position = "relative";
+ }
+
+ var curElem = jQuery( elem ),
+ curOffset = curElem.offset(),
+ curCSSTop = jQuery.css( elem, "top" ),
+ curCSSLeft = jQuery.css( elem, "left" ),
+ calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
+ props = {}, curPosition = {}, curTop, curLeft;
+
+ // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
+ if ( calculatePosition ) {
+ curPosition = curElem.position();
+ curTop = curPosition.top;
+ curLeft = curPosition.left;
+ } else {
+ curTop = parseFloat( curCSSTop ) || 0;
+ curLeft = parseFloat( curCSSLeft ) || 0;
+ }
+
+ if ( jQuery.isFunction( options ) ) {
+ options = options.call( elem, i, curOffset );
+ }
+
+ if ( options.top != null ) {
+ props.top = ( options.top - curOffset.top ) + curTop;
+ }
+ if ( options.left != null ) {
+ props.left = ( options.left - curOffset.left ) + curLeft;
+ }
+
+ if ( "using" in options ) {
+ options.using.call( elem, props );
+ } else {
+ curElem.css( props );
+ }
+ }
+};
+
+
+jQuery.fn.extend({
+
+ position: function() {
+ if ( !this[0] ) {
+ return null;
+ }
+
+ var elem = this[0],
+
+ // Get *real* offsetParent
+ offsetParent = this.offsetParent(),
+
+ // Get correct offsets
+ offset = this.offset(),
+ parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
+
+ // Subtract element margins
+ // note: when an element has margin: auto the offsetLeft and marginLeft
+ // are the same in Safari causing offset.left to incorrectly be 0
+ offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
+ offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
+
+ // Add offsetParent borders
+ parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
+ parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
+
+ // Subtract the two offsets
+ return {
+ top: offset.top - parentOffset.top,
+ left: offset.left - parentOffset.left
+ };
+ },
+
+ offsetParent: function() {
+ return this.map(function() {
+ var offsetParent = this.offsetParent || document.body;
+ while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
+ offsetParent = offsetParent.offsetParent;
+ }
+ return offsetParent;
+ });
+ }
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
+ var top = /Y/.test( prop );
+
+ jQuery.fn[ method ] = function( val ) {
+ return jQuery.access( this, function( elem, method, val ) {
+ var win = getWindow( elem );
+
+ if ( val === undefined ) {
+ return win ? (prop in win) ? win[ prop ] :
+ jQuery.support.boxModel && win.document.documentElement[ method ] ||
+ win.document.body[ method ] :
+ elem[ method ];
+ }
+
+ if ( win ) {
+ win.scrollTo(
+ !top ? val : jQuery( win ).scrollLeft(),
+ top ? val : jQuery( win ).scrollTop()
+ );
+
+ } else {
+ elem[ method ] = val;
+ }
+ }, method, val, arguments.length, null );
+ };
+});
+
+function getWindow( elem ) {
+ return jQuery.isWindow( elem ) ?
+ elem :
+ elem.nodeType === 9 ?
+ elem.defaultView || elem.parentWindow :
+ false;
+}
+
+
+
+
+// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods
+jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+ var clientProp = "client" + name,
+ scrollProp = "scroll" + name,
+ offsetProp = "offset" + name;
+
+ // innerHeight and innerWidth
+ jQuery.fn[ "inner" + name ] = function() {
+ var elem = this[0];
+ return elem ?
+ elem.style ?
+ parseFloat( jQuery.css( elem, type, "padding" ) ) :
+ this[ type ]() :
+ null;
+ };
+
+ // outerHeight and outerWidth
+ jQuery.fn[ "outer" + name ] = function( margin ) {
+ var elem = this[0];
+ return elem ?
+ elem.style ?
+ parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) :
+ this[ type ]() :
+ null;
+ };
+
+ jQuery.fn[ type ] = function( value ) {
+ return jQuery.access( this, function( elem, type, value ) {
+ var doc, docElemProp, orig, ret;
+
+ if ( jQuery.isWindow( elem ) ) {
+ // 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat
+ doc = elem.document;
+ docElemProp = doc.documentElement[ clientProp ];
+ return jQuery.support.boxModel && docElemProp ||
+ doc.body && doc.body[ clientProp ] || docElemProp;
+ }
+
+ // Get document width or height
+ if ( elem.nodeType === 9 ) {
+ // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
+ doc = elem.documentElement;
+
+ // when a window > document, IE6 reports a offset[Width/Height] > client[Width/Height]
+ // so we can't use max, as it'll choose the incorrect offset[Width/Height]
+ // instead we use the correct client[Width/Height]
+ // support:IE6
+ if ( doc[ clientProp ] >= doc[ scrollProp ] ) {
+ return doc[ clientProp ];
+ }
+
+ return Math.max(
+ elem.body[ scrollProp ], doc[ scrollProp ],
+ elem.body[ offsetProp ], doc[ offsetProp ]
+ );
+ }
+
+ // Get width or height on the element
+ if ( value === undefined ) {
+ orig = jQuery.css( elem, type );
+ ret = parseFloat( orig );
+ return jQuery.isNumeric( ret ) ? ret : orig;
+ }
+
+ // Set the width or height on the element
+ jQuery( elem ).css( type, value );
+ }, type, value, arguments.length, null );
+ };
+});
+
+
+
+
+// Expose jQuery to the global object
+window.jQuery = window.$ = jQuery;
+
+// Expose jQuery as an AMD module, but only for AMD loaders that
+// understand the issues with loading multiple versions of jQuery
+// in a page that all might call define(). The loader will indicate
+// they have special allowances for multiple jQuery versions by
+// specifying define.amd.jQuery = true. Register as a named module,
+// since jQuery can be concatenated with other files that may use define,
+// but not use a proper concatenation script that understands anonymous
+// AMD modules. A named AMD is safest and most robust way to register.
+// Lowercase jquery is used because AMD module names are derived from
+// file names, and jQuery is normally delivered in a lowercase file name.
+// Do this after creating the global so that if an AMD module wants to call
+// noConflict to hide this version of jQuery, it will work.
+if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
+ define( "jquery", [], function () { return jQuery; } );
+}
+
+
+
+})( window );
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-ui-1.8.18.custom.js b/storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-ui-1.8.18.custom.js
new file mode 100644
index 00000000000..d4444b2bd11
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-ui-1.8.18.custom.js
@@ -0,0 +1,11802 @@
+/*!
+ * jQuery UI 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI
+ */
+(function( $, undefined ) {
+
+// prevent duplicate loading
+// this is only a problem because we proxy existing functions
+// and we don't want to double proxy them
+$.ui = $.ui || {};
+if ( $.ui.version ) {
+ return;
+}
+
+$.extend( $.ui, {
+ version: "1.8.18",
+
+ keyCode: {
+ ALT: 18,
+ BACKSPACE: 8,
+ CAPS_LOCK: 20,
+ COMMA: 188,
+ COMMAND: 91,
+ COMMAND_LEFT: 91, // COMMAND
+ COMMAND_RIGHT: 93,
+ CONTROL: 17,
+ DELETE: 46,
+ DOWN: 40,
+ END: 35,
+ ENTER: 13,
+ ESCAPE: 27,
+ HOME: 36,
+ INSERT: 45,
+ LEFT: 37,
+ MENU: 93, // COMMAND_RIGHT
+ NUMPAD_ADD: 107,
+ NUMPAD_DECIMAL: 110,
+ NUMPAD_DIVIDE: 111,
+ NUMPAD_ENTER: 108,
+ NUMPAD_MULTIPLY: 106,
+ NUMPAD_SUBTRACT: 109,
+ PAGE_DOWN: 34,
+ PAGE_UP: 33,
+ PERIOD: 190,
+ RIGHT: 39,
+ SHIFT: 16,
+ SPACE: 32,
+ TAB: 9,
+ UP: 38,
+ WINDOWS: 91 // COMMAND
+ }
+});
+
+// plugins
+$.fn.extend({
+ propAttr: $.fn.prop || $.fn.attr,
+
+ _focus: $.fn.focus,
+ focus: function( delay, fn ) {
+ return typeof delay === "number" ?
+ this.each(function() {
+ var elem = this;
+ setTimeout(function() {
+ $( elem ).focus();
+ if ( fn ) {
+ fn.call( elem );
+ }
+ }, delay );
+ }) :
+ this._focus.apply( this, arguments );
+ },
+
+ scrollParent: function() {
+ var scrollParent;
+ if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
+ scrollParent = this.parents().filter(function() {
+ return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
+ }).eq(0);
+ } else {
+ scrollParent = this.parents().filter(function() {
+ return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
+ }).eq(0);
+ }
+
+ return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
+ },
+
+ zIndex: function( zIndex ) {
+ if ( zIndex !== undefined ) {
+ return this.css( "zIndex", zIndex );
+ }
+
+ if ( this.length ) {
+ var elem = $( this[ 0 ] ), position, value;
+ while ( elem.length && elem[ 0 ] !== document ) {
+ // Ignore z-index if position is set to a value where z-index is ignored by the browser
+ // This makes behavior of this function consistent across browsers
+ // WebKit always returns auto if the element is positioned
+ position = elem.css( "position" );
+ if ( position === "absolute" || position === "relative" || position === "fixed" ) {
+ // IE returns 0 when zIndex is not specified
+ // other browsers return a string
+ // we ignore the case of nested elements with an explicit value of 0
+ // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
+ value = parseInt( elem.css( "zIndex" ), 10 );
+ if ( !isNaN( value ) && value !== 0 ) {
+ return value;
+ }
+ }
+ elem = elem.parent();
+ }
+ }
+
+ return 0;
+ },
+
+ disableSelection: function() {
+ return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
+ ".ui-disableSelection", function( event ) {
+ event.preventDefault();
+ });
+ },
+
+ enableSelection: function() {
+ return this.unbind( ".ui-disableSelection" );
+ }
+});
+
+$.each( [ "Width", "Height" ], function( i, name ) {
+ var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
+ type = name.toLowerCase(),
+ orig = {
+ innerWidth: $.fn.innerWidth,
+ innerHeight: $.fn.innerHeight,
+ outerWidth: $.fn.outerWidth,
+ outerHeight: $.fn.outerHeight
+ };
+
+ function reduce( elem, size, border, margin ) {
+ $.each( side, function() {
+ size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
+ if ( border ) {
+ size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
+ }
+ if ( margin ) {
+ size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
+ }
+ });
+ return size;
+ }
+
+ $.fn[ "inner" + name ] = function( size ) {
+ if ( size === undefined ) {
+ return orig[ "inner" + name ].call( this );
+ }
+
+ return this.each(function() {
+ $( this ).css( type, reduce( this, size ) + "px" );
+ });
+ };
+
+ $.fn[ "outer" + name] = function( size, margin ) {
+ if ( typeof size !== "number" ) {
+ return orig[ "outer" + name ].call( this, size );
+ }
+
+ return this.each(function() {
+ $( this).css( type, reduce( this, size, true, margin ) + "px" );
+ });
+ };
+});
+
+// selectors
+function focusable( element, isTabIndexNotNaN ) {
+ var nodeName = element.nodeName.toLowerCase();
+ if ( "area" === nodeName ) {
+ var map = element.parentNode,
+ mapName = map.name,
+ img;
+ if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
+ return false;
+ }
+ img = $( "img[usemap=#" + mapName + "]" )[0];
+ return !!img && visible( img );
+ }
+ return ( /input|select|textarea|button|object/.test( nodeName )
+ ? !element.disabled
+ : "a" == nodeName
+ ? element.href || isTabIndexNotNaN
+ : isTabIndexNotNaN)
+ // the element and all of its ancestors must be visible
+ && visible( element );
+}
+
+function visible( element ) {
+ return !$( element ).parents().andSelf().filter(function() {
+ return $.curCSS( this, "visibility" ) === "hidden" ||
+ $.expr.filters.hidden( this );
+ }).length;
+}
+
+$.extend( $.expr[ ":" ], {
+ data: function( elem, i, match ) {
+ return !!$.data( elem, match[ 3 ] );
+ },
+
+ focusable: function( element ) {
+ return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
+ },
+
+ tabbable: function( element ) {
+ var tabIndex = $.attr( element, "tabindex" ),
+ isTabIndexNaN = isNaN( tabIndex );
+ return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
+ }
+});
+
+// support
+$(function() {
+ var body = document.body,
+ div = body.appendChild( div = document.createElement( "div" ) );
+
+ // access offsetHeight before setting the style to prevent a layout bug
+ // in IE 9 which causes the elemnt to continue to take up space even
+ // after it is removed from the DOM (#8026)
+ div.offsetHeight;
+
+ $.extend( div.style, {
+ minHeight: "100px",
+ height: "auto",
+ padding: 0,
+ borderWidth: 0
+ });
+
+ $.support.minHeight = div.offsetHeight === 100;
+ $.support.selectstart = "onselectstart" in div;
+
+ // set display to none to avoid a layout bug in IE
+ // http://dev.jquery.com/ticket/4014
+ body.removeChild( div ).style.display = "none";
+});
+
+
+
+
+
+// deprecated
+$.extend( $.ui, {
+ // $.ui.plugin is deprecated. Use the proxy pattern instead.
+ plugin: {
+ add: function( module, option, set ) {
+ var proto = $.ui[ module ].prototype;
+ for ( var i in set ) {
+ proto.plugins[ i ] = proto.plugins[ i ] || [];
+ proto.plugins[ i ].push( [ option, set[ i ] ] );
+ }
+ },
+ call: function( instance, name, args ) {
+ var set = instance.plugins[ name ];
+ if ( !set || !instance.element[ 0 ].parentNode ) {
+ return;
+ }
+
+ for ( var i = 0; i < set.length; i++ ) {
+ if ( instance.options[ set[ i ][ 0 ] ] ) {
+ set[ i ][ 1 ].apply( instance.element, args );
+ }
+ }
+ }
+ },
+
+ // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
+ contains: function( a, b ) {
+ return document.compareDocumentPosition ?
+ a.compareDocumentPosition( b ) & 16 :
+ a !== b && a.contains( b );
+ },
+
+ // only used by resizable
+ hasScroll: function( el, a ) {
+
+ //If overflow is hidden, the element might have extra content, but the user wants to hide it
+ if ( $( el ).css( "overflow" ) === "hidden") {
+ return false;
+ }
+
+ var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
+ has = false;
+
+ if ( el[ scroll ] > 0 ) {
+ return true;
+ }
+
+ // TODO: determine which cases actually cause this to happen
+ // if the element doesn't have the scroll set, see if it's possible to
+ // set the scroll
+ el[ scroll ] = 1;
+ has = ( el[ scroll ] > 0 );
+ el[ scroll ] = 0;
+ return has;
+ },
+
+ // these are odd functions, fix the API or move into individual plugins
+ isOverAxis: function( x, reference, size ) {
+ //Determines when x coordinate is over "b" element axis
+ return ( x > reference ) && ( x < ( reference + size ) );
+ },
+ isOver: function( y, x, top, left, height, width ) {
+ //Determines when x, y coordinates is over "b" element
+ return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
+ }
+});
+
+})( jQuery );
+/*!
+ * jQuery UI Widget 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Widget
+ */
+(function( $, undefined ) {
+
+// jQuery 1.4+
+if ( $.cleanData ) {
+ var _cleanData = $.cleanData;
+ $.cleanData = function( elems ) {
+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+ try {
+ $( elem ).triggerHandler( "remove" );
+ // http://bugs.jquery.com/ticket/8235
+ } catch( e ) {}
+ }
+ _cleanData( elems );
+ };
+} else {
+ var _remove = $.fn.remove;
+ $.fn.remove = function( selector, keepData ) {
+ return this.each(function() {
+ if ( !keepData ) {
+ if ( !selector || $.filter( selector, [ this ] ).length ) {
+ $( "*", this ).add( [ this ] ).each(function() {
+ try {
+ $( this ).triggerHandler( "remove" );
+ // http://bugs.jquery.com/ticket/8235
+ } catch( e ) {}
+ });
+ }
+ }
+ return _remove.call( $(this), selector, keepData );
+ });
+ };
+}
+
+$.widget = function( name, base, prototype ) {
+ var namespace = name.split( "." )[ 0 ],
+ fullName;
+ name = name.split( "." )[ 1 ];
+ fullName = namespace + "-" + name;
+
+ if ( !prototype ) {
+ prototype = base;
+ base = $.Widget;
+ }
+
+ // create selector for plugin
+ $.expr[ ":" ][ fullName ] = function( elem ) {
+ return !!$.data( elem, name );
+ };
+
+ $[ namespace ] = $[ namespace ] || {};
+ $[ namespace ][ name ] = function( options, element ) {
+ // allow instantiation without initializing for simple inheritance
+ if ( arguments.length ) {
+ this._createWidget( options, element );
+ }
+ };
+
+ var basePrototype = new base();
+ // we need to make the options hash a property directly on the new instance
+ // otherwise we'll modify the options hash on the prototype that we're
+ // inheriting from
+// $.each( basePrototype, function( key, val ) {
+// if ( $.isPlainObject(val) ) {
+// basePrototype[ key ] = $.extend( {}, val );
+// }
+// });
+ basePrototype.options = $.extend( true, {}, basePrototype.options );
+ $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
+ namespace: namespace,
+ widgetName: name,
+ widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
+ widgetBaseClass: fullName
+ }, prototype );
+
+ $.widget.bridge( name, $[ namespace ][ name ] );
+};
+
+$.widget.bridge = function( name, object ) {
+ $.fn[ name ] = function( options ) {
+ var isMethodCall = typeof options === "string",
+ args = Array.prototype.slice.call( arguments, 1 ),
+ returnValue = this;
+
+ // allow multiple hashes to be passed on init
+ options = !isMethodCall && args.length ?
+ $.extend.apply( null, [ true, options ].concat(args) ) :
+ options;
+
+ // prevent calls to internal methods
+ if ( isMethodCall && options.charAt( 0 ) === "_" ) {
+ return returnValue;
+ }
+
+ if ( isMethodCall ) {
+ this.each(function() {
+ var instance = $.data( this, name ),
+ methodValue = instance && $.isFunction( instance[options] ) ?
+ instance[ options ].apply( instance, args ) :
+ instance;
+ // TODO: add this back in 1.9 and use $.error() (see #5972)
+// if ( !instance ) {
+// throw "cannot call methods on " + name + " prior to initialization; " +
+// "attempted to call method '" + options + "'";
+// }
+// if ( !$.isFunction( instance[options] ) ) {
+// throw "no such method '" + options + "' for " + name + " widget instance";
+// }
+// var methodValue = instance[ options ].apply( instance, args );
+ if ( methodValue !== instance && methodValue !== undefined ) {
+ returnValue = methodValue;
+ return false;
+ }
+ });
+ } else {
+ this.each(function() {
+ var instance = $.data( this, name );
+ if ( instance ) {
+ instance.option( options || {} )._init();
+ } else {
+ $.data( this, name, new object( options, this ) );
+ }
+ });
+ }
+
+ return returnValue;
+ };
+};
+
+$.Widget = function( options, element ) {
+ // allow instantiation without initializing for simple inheritance
+ if ( arguments.length ) {
+ this._createWidget( options, element );
+ }
+};
+
+$.Widget.prototype = {
+ widgetName: "widget",
+ widgetEventPrefix: "",
+ options: {
+ disabled: false
+ },
+ _createWidget: function( options, element ) {
+ // $.widget.bridge stores the plugin instance, but we do it anyway
+ // so that it's stored even before the _create function runs
+ $.data( element, this.widgetName, this );
+ this.element = $( element );
+ this.options = $.extend( true, {},
+ this.options,
+ this._getCreateOptions(),
+ options );
+
+ var self = this;
+ this.element.bind( "remove." + this.widgetName, function() {
+ self.destroy();
+ });
+
+ this._create();
+ this._trigger( "create" );
+ this._init();
+ },
+ _getCreateOptions: function() {
+ return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
+ },
+ _create: function() {},
+ _init: function() {},
+
+ destroy: function() {
+ this.element
+ .unbind( "." + this.widgetName )
+ .removeData( this.widgetName );
+ this.widget()
+ .unbind( "." + this.widgetName )
+ .removeAttr( "aria-disabled" )
+ .removeClass(
+ this.widgetBaseClass + "-disabled " +
+ "ui-state-disabled" );
+ },
+
+ widget: function() {
+ return this.element;
+ },
+
+ option: function( key, value ) {
+ var options = key;
+
+ if ( arguments.length === 0 ) {
+ // don't return a reference to the internal hash
+ return $.extend( {}, this.options );
+ }
+
+ if (typeof key === "string" ) {
+ if ( value === undefined ) {
+ return this.options[ key ];
+ }
+ options = {};
+ options[ key ] = value;
+ }
+
+ this._setOptions( options );
+
+ return this;
+ },
+ _setOptions: function( options ) {
+ var self = this;
+ $.each( options, function( key, value ) {
+ self._setOption( key, value );
+ });
+
+ return this;
+ },
+ _setOption: function( key, value ) {
+ this.options[ key ] = value;
+
+ if ( key === "disabled" ) {
+ this.widget()
+ [ value ? "addClass" : "removeClass"](
+ this.widgetBaseClass + "-disabled" + " " +
+ "ui-state-disabled" )
+ .attr( "aria-disabled", value );
+ }
+
+ return this;
+ },
+
+ enable: function() {
+ return this._setOption( "disabled", false );
+ },
+ disable: function() {
+ return this._setOption( "disabled", true );
+ },
+
+ _trigger: function( type, event, data ) {
+ var prop, orig,
+ callback = this.options[ type ];
+
+ data = data || {};
+ event = $.Event( event );
+ event.type = ( type === this.widgetEventPrefix ?
+ type :
+ this.widgetEventPrefix + type ).toLowerCase();
+ // the original event may come from any element
+ // so we need to reset the target on the new event
+ event.target = this.element[ 0 ];
+
+ // copy original event properties over to the new event
+ orig = event.originalEvent;
+ if ( orig ) {
+ for ( prop in orig ) {
+ if ( !( prop in event ) ) {
+ event[ prop ] = orig[ prop ];
+ }
+ }
+ }
+
+ this.element.trigger( event, data );
+
+ return !( $.isFunction(callback) &&
+ callback.call( this.element[0], event, data ) === false ||
+ event.isDefaultPrevented() );
+ }
+};
+
+})( jQuery );
+/*!
+ * jQuery UI Mouse 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Mouse
+ *
+ * Depends:
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+var mouseHandled = false;
+$( document ).mouseup( function( e ) {
+ mouseHandled = false;
+});
+
+$.widget("ui.mouse", {
+ options: {
+ cancel: ':input,option',
+ distance: 1,
+ delay: 0
+ },
+ _mouseInit: function() {
+ var self = this;
+
+ this.element
+ .bind('mousedown.'+this.widgetName, function(event) {
+ return self._mouseDown(event);
+ })
+ .bind('click.'+this.widgetName, function(event) {
+ if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) {
+ $.removeData(event.target, self.widgetName + '.preventClickEvent');
+ event.stopImmediatePropagation();
+ return false;
+ }
+ });
+
+ this.started = false;
+ },
+
+ // TODO: make sure destroying one instance of mouse doesn't mess with
+ // other instances of mouse
+ _mouseDestroy: function() {
+ this.element.unbind('.'+this.widgetName);
+ },
+
+ _mouseDown: function(event) {
+ // don't let more than one widget handle mouseStart
+ if( mouseHandled ) { return };
+
+ // we may have missed mouseup (out of window)
+ (this._mouseStarted && this._mouseUp(event));
+
+ this._mouseDownEvent = event;
+
+ var self = this,
+ btnIsLeft = (event.which == 1),
+ // event.target.nodeName works around a bug in IE 8 with
+ // disabled inputs (#7620)
+ elIsCancel = (typeof this.options.cancel == "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
+ if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
+ return true;
+ }
+
+ this.mouseDelayMet = !this.options.delay;
+ if (!this.mouseDelayMet) {
+ this._mouseDelayTimer = setTimeout(function() {
+ self.mouseDelayMet = true;
+ }, this.options.delay);
+ }
+
+ if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
+ this._mouseStarted = (this._mouseStart(event) !== false);
+ if (!this._mouseStarted) {
+ event.preventDefault();
+ return true;
+ }
+ }
+
+ // Click event may never have fired (Gecko & Opera)
+ if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) {
+ $.removeData(event.target, this.widgetName + '.preventClickEvent');
+ }
+
+ // these delegates are required to keep context
+ this._mouseMoveDelegate = function(event) {
+ return self._mouseMove(event);
+ };
+ this._mouseUpDelegate = function(event) {
+ return self._mouseUp(event);
+ };
+ $(document)
+ .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
+ .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
+
+ event.preventDefault();
+
+ mouseHandled = true;
+ return true;
+ },
+
+ _mouseMove: function(event) {
+ // IE mouseup check - mouseup happened when mouse was out of window
+ if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
+ return this._mouseUp(event);
+ }
+
+ if (this._mouseStarted) {
+ this._mouseDrag(event);
+ return event.preventDefault();
+ }
+
+ if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
+ this._mouseStarted =
+ (this._mouseStart(this._mouseDownEvent, event) !== false);
+ (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
+ }
+
+ return !this._mouseStarted;
+ },
+
+ _mouseUp: function(event) {
+ $(document)
+ .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
+ .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
+
+ if (this._mouseStarted) {
+ this._mouseStarted = false;
+
+ if (event.target == this._mouseDownEvent.target) {
+ $.data(event.target, this.widgetName + '.preventClickEvent', true);
+ }
+
+ this._mouseStop(event);
+ }
+
+ return false;
+ },
+
+ _mouseDistanceMet: function(event) {
+ return (Math.max(
+ Math.abs(this._mouseDownEvent.pageX - event.pageX),
+ Math.abs(this._mouseDownEvent.pageY - event.pageY)
+ ) >= this.options.distance
+ );
+ },
+
+ _mouseDelayMet: function(event) {
+ return this.mouseDelayMet;
+ },
+
+ // These are placeholder methods, to be overriden by extending plugin
+ _mouseStart: function(event) {},
+ _mouseDrag: function(event) {},
+ _mouseStop: function(event) {},
+ _mouseCapture: function(event) { return true; }
+});
+
+})(jQuery);
+/*
+ * jQuery UI Draggable 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Draggables
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+$.widget("ui.draggable", $.ui.mouse, {
+ widgetEventPrefix: "drag",
+ options: {
+ addClasses: true,
+ appendTo: "parent",
+ axis: false,
+ connectToSortable: false,
+ containment: false,
+ cursor: "auto",
+ cursorAt: false,
+ grid: false,
+ handle: false,
+ helper: "original",
+ iframeFix: false,
+ opacity: false,
+ refreshPositions: false,
+ revert: false,
+ revertDuration: 500,
+ scope: "default",
+ scroll: true,
+ scrollSensitivity: 20,
+ scrollSpeed: 20,
+ snap: false,
+ snapMode: "both",
+ snapTolerance: 20,
+ stack: false,
+ zIndex: false
+ },
+ _create: function() {
+
+ if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
+ this.element[0].style.position = 'relative';
+
+ (this.options.addClasses && this.element.addClass("ui-draggable"));
+ (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
+
+ this._mouseInit();
+
+ },
+
+ destroy: function() {
+ if(!this.element.data('draggable')) return;
+ this.element
+ .removeData("draggable")
+ .unbind(".draggable")
+ .removeClass("ui-draggable"
+ + " ui-draggable-dragging"
+ + " ui-draggable-disabled");
+ this._mouseDestroy();
+
+ return this;
+ },
+
+ _mouseCapture: function(event) {
+
+ var o = this.options;
+
+ // among others, prevent a drag on a resizable-handle
+ if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
+ return false;
+
+ //Quit if we're not on a valid handle
+ this.handle = this._getHandle(event);
+ if (!this.handle)
+ return false;
+
+ if ( o.iframeFix ) {
+ $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
+ $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
+ .css({
+ width: this.offsetWidth+"px", height: this.offsetHeight+"px",
+ position: "absolute", opacity: "0.001", zIndex: 1000
+ })
+ .css($(this).offset())
+ .appendTo("body");
+ });
+ }
+
+ return true;
+
+ },
+
+ _mouseStart: function(event) {
+
+ var o = this.options;
+
+ //Create and append the visible helper
+ this.helper = this._createHelper(event);
+
+ //Cache the helper size
+ this._cacheHelperProportions();
+
+ //If ddmanager is used for droppables, set the global draggable
+ if($.ui.ddmanager)
+ $.ui.ddmanager.current = this;
+
+ /*
+ * - Position generation -
+ * This block generates everything position related - it's the core of draggables.
+ */
+
+ //Cache the margins of the original element
+ this._cacheMargins();
+
+ //Store the helper's css position
+ this.cssPosition = this.helper.css("position");
+ this.scrollParent = this.helper.scrollParent();
+
+ //The element's absolute position on the page minus margins
+ this.offset = this.positionAbs = this.element.offset();
+ this.offset = {
+ top: this.offset.top - this.margins.top,
+ left: this.offset.left - this.margins.left
+ };
+
+ $.extend(this.offset, {
+ click: { //Where the click happened, relative to the element
+ left: event.pageX - this.offset.left,
+ top: event.pageY - this.offset.top
+ },
+ parent: this._getParentOffset(),
+ relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
+ });
+
+ //Generate the original position
+ this.originalPosition = this.position = this._generatePosition(event);
+ this.originalPageX = event.pageX;
+ this.originalPageY = event.pageY;
+
+ //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
+ (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
+
+ //Set a containment if given in the options
+ if(o.containment)
+ this._setContainment();
+
+ //Trigger event + callbacks
+ if(this._trigger("start", event) === false) {
+ this._clear();
+ return false;
+ }
+
+ //Recache the helper size
+ this._cacheHelperProportions();
+
+ //Prepare the droppable offsets
+ if ($.ui.ddmanager && !o.dropBehaviour)
+ $.ui.ddmanager.prepareOffsets(this, event);
+
+ this.helper.addClass("ui-draggable-dragging");
+ this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
+
+ //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
+ if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event);
+
+ return true;
+ },
+
+ _mouseDrag: function(event, noPropagation) {
+
+ //Compute the helpers position
+ this.position = this._generatePosition(event);
+ this.positionAbs = this._convertPositionTo("absolute");
+
+ //Call plugins and callbacks and use the resulting position if something is returned
+ if (!noPropagation) {
+ var ui = this._uiHash();
+ if(this._trigger('drag', event, ui) === false) {
+ this._mouseUp({});
+ return false;
+ }
+ this.position = ui.position;
+ }
+
+ if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
+ if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
+ if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
+
+ return false;
+ },
+
+ _mouseStop: function(event) {
+
+ //If we are using droppables, inform the manager about the drop
+ var dropped = false;
+ if ($.ui.ddmanager && !this.options.dropBehaviour)
+ dropped = $.ui.ddmanager.drop(this, event);
+
+ //if a drop comes from outside (a sortable)
+ if(this.dropped) {
+ dropped = this.dropped;
+ this.dropped = false;
+ }
+
+ //if the original element is removed, don't bother to continue if helper is set to "original"
+ if((!this.element[0] || !this.element[0].parentNode) && this.options.helper == "original")
+ return false;
+
+ if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
+ var self = this;
+ $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
+ if(self._trigger("stop", event) !== false) {
+ self._clear();
+ }
+ });
+ } else {
+ if(this._trigger("stop", event) !== false) {
+ this._clear();
+ }
+ }
+
+ return false;
+ },
+
+ _mouseUp: function(event) {
+ if (this.options.iframeFix === true) {
+ $("div.ui-draggable-iframeFix").each(function() {
+ this.parentNode.removeChild(this);
+ }); //Remove frame helpers
+ }
+
+ //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
+ if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event);
+
+ return $.ui.mouse.prototype._mouseUp.call(this, event);
+ },
+
+ cancel: function() {
+
+ if(this.helper.is(".ui-draggable-dragging")) {
+ this._mouseUp({});
+ } else {
+ this._clear();
+ }
+
+ return this;
+
+ },
+
+ _getHandle: function(event) {
+
+ var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
+ $(this.options.handle, this.element)
+ .find("*")
+ .andSelf()
+ .each(function() {
+ if(this == event.target) handle = true;
+ });
+
+ return handle;
+
+ },
+
+ _createHelper: function(event) {
+
+ var o = this.options;
+ var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element);
+
+ if(!helper.parents('body').length)
+ helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
+
+ if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
+ helper.css("position", "absolute");
+
+ return helper;
+
+ },
+
+ _adjustOffsetFromHelper: function(obj) {
+ if (typeof obj == 'string') {
+ obj = obj.split(' ');
+ }
+ if ($.isArray(obj)) {
+ obj = {left: +obj[0], top: +obj[1] || 0};
+ }
+ if ('left' in obj) {
+ this.offset.click.left = obj.left + this.margins.left;
+ }
+ if ('right' in obj) {
+ this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
+ }
+ if ('top' in obj) {
+ this.offset.click.top = obj.top + this.margins.top;
+ }
+ if ('bottom' in obj) {
+ this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
+ }
+ },
+
+ _getParentOffset: function() {
+
+ //Get the offsetParent and cache its position
+ this.offsetParent = this.helper.offsetParent();
+ var po = this.offsetParent.offset();
+
+ // This is a special case where we need to modify a offset calculated on start, since the following happened:
+ // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
+ // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
+ // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
+ if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
+ po.left += this.scrollParent.scrollLeft();
+ po.top += this.scrollParent.scrollTop();
+ }
+
+ if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
+ || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
+ po = { top: 0, left: 0 };
+
+ return {
+ top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
+ left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
+ };
+
+ },
+
+ _getRelativeOffset: function() {
+
+ if(this.cssPosition == "relative") {
+ var p = this.element.position();
+ return {
+ top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
+ left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
+ };
+ } else {
+ return { top: 0, left: 0 };
+ }
+
+ },
+
+ _cacheMargins: function() {
+ this.margins = {
+ left: (parseInt(this.element.css("marginLeft"),10) || 0),
+ top: (parseInt(this.element.css("marginTop"),10) || 0),
+ right: (parseInt(this.element.css("marginRight"),10) || 0),
+ bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
+ };
+ },
+
+ _cacheHelperProportions: function() {
+ this.helperProportions = {
+ width: this.helper.outerWidth(),
+ height: this.helper.outerHeight()
+ };
+ },
+
+ _setContainment: function() {
+
+ var o = this.options;
+ if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
+ if(o.containment == 'document' || o.containment == 'window') this.containment = [
+ o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
+ o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top,
+ (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
+ (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
+ ];
+
+ if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
+ var c = $(o.containment);
+ var ce = c[0]; if(!ce) return;
+ var co = c.offset();
+ var over = ($(ce).css("overflow") != 'hidden');
+
+ this.containment = [
+ (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0),
+ (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0),
+ (over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right,
+ (over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top - this.margins.bottom
+ ];
+ this.relative_container = c;
+
+ } else if(o.containment.constructor == Array) {
+ this.containment = o.containment;
+ }
+
+ },
+
+ _convertPositionTo: function(d, pos) {
+
+ if(!pos) pos = this.position;
+ var mod = d == "absolute" ? 1 : -1;
+ var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
+
+ return {
+ top: (
+ pos.top // The absolute mouse position
+ + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
+ + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
+ - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
+ ),
+ left: (
+ pos.left // The absolute mouse position
+ + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
+ + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
+ - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
+ )
+ };
+
+ },
+
+ _generatePosition: function(event) {
+
+ var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
+ var pageX = event.pageX;
+ var pageY = event.pageY;
+
+ /*
+ * - Position constraining -
+ * Constrain the position to a mix of grid, containment.
+ */
+
+ if(this.originalPosition) { //If we are not dragging yet, we won't check for options
+ var containment;
+ if(this.containment) {
+ if (this.relative_container){
+ var co = this.relative_container.offset();
+ containment = [ this.containment[0] + co.left,
+ this.containment[1] + co.top,
+ this.containment[2] + co.left,
+ this.containment[3] + co.top ];
+ }
+ else {
+ containment = this.containment;
+ }
+
+ if(event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left;
+ if(event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top;
+ if(event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left;
+ if(event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top;
+ }
+
+ if(o.grid) {
+ //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
+ var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
+ pageY = containment ? (!(top - this.offset.click.top < containment[1] || top - this.offset.click.top > containment[3]) ? top : (!(top - this.offset.click.top < containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
+
+ var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
+ pageX = containment ? (!(left - this.offset.click.left < containment[0] || left - this.offset.click.left > containment[2]) ? left : (!(left - this.offset.click.left < containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
+ }
+
+ }
+
+ return {
+ top: (
+ pageY // The absolute mouse position
+ - this.offset.click.top // Click offset (relative to the element)
+ - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
+ - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
+ + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
+ ),
+ left: (
+ pageX // The absolute mouse position
+ - this.offset.click.left // Click offset (relative to the element)
+ - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
+ - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
+ + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
+ )
+ };
+
+ },
+
+ _clear: function() {
+ this.helper.removeClass("ui-draggable-dragging");
+ if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
+ //if($.ui.ddmanager) $.ui.ddmanager.current = null;
+ this.helper = null;
+ this.cancelHelperRemoval = false;
+ },
+
+ // From now on bulk stuff - mainly helpers
+
+ _trigger: function(type, event, ui) {
+ ui = ui || this._uiHash();
+ $.ui.plugin.call(this, type, [event, ui]);
+ if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
+ return $.Widget.prototype._trigger.call(this, type, event, ui);
+ },
+
+ plugins: {},
+
+ _uiHash: function(event) {
+ return {
+ helper: this.helper,
+ position: this.position,
+ originalPosition: this.originalPosition,
+ offset: this.positionAbs
+ };
+ }
+
+});
+
+$.extend($.ui.draggable, {
+ version: "1.8.18"
+});
+
+$.ui.plugin.add("draggable", "connectToSortable", {
+ start: function(event, ui) {
+
+ var inst = $(this).data("draggable"), o = inst.options,
+ uiSortable = $.extend({}, ui, { item: inst.element });
+ inst.sortables = [];
+ $(o.connectToSortable).each(function() {
+ var sortable = $.data(this, 'sortable');
+ if (sortable && !sortable.options.disabled) {
+ inst.sortables.push({
+ instance: sortable,
+ shouldRevert: sortable.options.revert
+ });
+ sortable.refreshPositions(); // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page).
+ sortable._trigger("activate", event, uiSortable);
+ }
+ });
+
+ },
+ stop: function(event, ui) {
+
+ //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
+ var inst = $(this).data("draggable"),
+ uiSortable = $.extend({}, ui, { item: inst.element });
+
+ $.each(inst.sortables, function() {
+ if(this.instance.isOver) {
+
+ this.instance.isOver = 0;
+
+ inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
+ this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
+
+ //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
+ if(this.shouldRevert) this.instance.options.revert = true;
+
+ //Trigger the stop of the sortable
+ this.instance._mouseStop(event);
+
+ this.instance.options.helper = this.instance.options._helper;
+
+ //If the helper has been the original item, restore properties in the sortable
+ if(inst.options.helper == 'original')
+ this.instance.currentItem.css({ top: 'auto', left: 'auto' });
+
+ } else {
+ this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
+ this.instance._trigger("deactivate", event, uiSortable);
+ }
+
+ });
+
+ },
+ drag: function(event, ui) {
+
+ var inst = $(this).data("draggable"), self = this;
+
+ var checkPos = function(o) {
+ var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
+ var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
+ var itemHeight = o.height, itemWidth = o.width;
+ var itemTop = o.top, itemLeft = o.left;
+
+ return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
+ };
+
+ $.each(inst.sortables, function(i) {
+
+ //Copy over some variables to allow calling the sortable's native _intersectsWith
+ this.instance.positionAbs = inst.positionAbs;
+ this.instance.helperProportions = inst.helperProportions;
+ this.instance.offset.click = inst.offset.click;
+
+ if(this.instance._intersectsWith(this.instance.containerCache)) {
+
+ //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
+ if(!this.instance.isOver) {
+
+ this.instance.isOver = 1;
+ //Now we fake the start of dragging for the sortable instance,
+ //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
+ //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
+ this.instance.currentItem = $(self).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true);
+ this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
+ this.instance.options.helper = function() { return ui.helper[0]; };
+
+ event.target = this.instance.currentItem[0];
+ this.instance._mouseCapture(event, true);
+ this.instance._mouseStart(event, true, true);
+
+ //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
+ this.instance.offset.click.top = inst.offset.click.top;
+ this.instance.offset.click.left = inst.offset.click.left;
+ this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
+ this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
+
+ inst._trigger("toSortable", event);
+ inst.dropped = this.instance.element; //draggable revert needs that
+ //hack so receive/update callbacks work (mostly)
+ inst.currentItem = inst.element;
+ this.instance.fromOutside = inst;
+
+ }
+
+ //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
+ if(this.instance.currentItem) this.instance._mouseDrag(event);
+
+ } else {
+
+ //If it doesn't intersect with the sortable, and it intersected before,
+ //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
+ if(this.instance.isOver) {
+
+ this.instance.isOver = 0;
+ this.instance.cancelHelperRemoval = true;
+
+ //Prevent reverting on this forced stop
+ this.instance.options.revert = false;
+
+ // The out event needs to be triggered independently
+ this.instance._trigger('out', event, this.instance._uiHash(this.instance));
+
+ this.instance._mouseStop(event, true);
+ this.instance.options.helper = this.instance.options._helper;
+
+ //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
+ this.instance.currentItem.remove();
+ if(this.instance.placeholder) this.instance.placeholder.remove();
+
+ inst._trigger("fromSortable", event);
+ inst.dropped = false; //draggable revert needs that
+ }
+
+ };
+
+ });
+
+ }
+});
+
+$.ui.plugin.add("draggable", "cursor", {
+ start: function(event, ui) {
+ var t = $('body'), o = $(this).data('draggable').options;
+ if (t.css("cursor")) o._cursor = t.css("cursor");
+ t.css("cursor", o.cursor);
+ },
+ stop: function(event, ui) {
+ var o = $(this).data('draggable').options;
+ if (o._cursor) $('body').css("cursor", o._cursor);
+ }
+});
+
+$.ui.plugin.add("draggable", "opacity", {
+ start: function(event, ui) {
+ var t = $(ui.helper), o = $(this).data('draggable').options;
+ if(t.css("opacity")) o._opacity = t.css("opacity");
+ t.css('opacity', o.opacity);
+ },
+ stop: function(event, ui) {
+ var o = $(this).data('draggable').options;
+ if(o._opacity) $(ui.helper).css('opacity', o._opacity);
+ }
+});
+
+$.ui.plugin.add("draggable", "scroll", {
+ start: function(event, ui) {
+ var i = $(this).data("draggable");
+ if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
+ },
+ drag: function(event, ui) {
+
+ var i = $(this).data("draggable"), o = i.options, scrolled = false;
+
+ if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
+
+ if(!o.axis || o.axis != 'x') {
+ if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
+ i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
+ else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
+ i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
+ }
+
+ if(!o.axis || o.axis != 'y') {
+ if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
+ i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
+ else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
+ i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
+ }
+
+ } else {
+
+ if(!o.axis || o.axis != 'x') {
+ if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
+ scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
+ else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
+ scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
+ }
+
+ if(!o.axis || o.axis != 'y') {
+ if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
+ scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
+ else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
+ scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
+ }
+
+ }
+
+ if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
+ $.ui.ddmanager.prepareOffsets(i, event);
+
+ }
+});
+
+$.ui.plugin.add("draggable", "snap", {
+ start: function(event, ui) {
+
+ var i = $(this).data("draggable"), o = i.options;
+ i.snapElements = [];
+
+ $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
+ var $t = $(this); var $o = $t.offset();
+ if(this != i.element[0]) i.snapElements.push({
+ item: this,
+ width: $t.outerWidth(), height: $t.outerHeight(),
+ top: $o.top, left: $o.left
+ });
+ });
+
+ },
+ drag: function(event, ui) {
+
+ var inst = $(this).data("draggable"), o = inst.options;
+ var d = o.snapTolerance;
+
+ var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
+ y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
+
+ for (var i = inst.snapElements.length - 1; i >= 0; i--){
+
+ var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
+ t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
+
+ //Yes, I know, this is insane ;)
+ if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
+ if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
+ inst.snapElements[i].snapping = false;
+ continue;
+ }
+
+ if(o.snapMode != 'inner') {
+ var ts = Math.abs(t - y2) <= d;
+ var bs = Math.abs(b - y1) <= d;
+ var ls = Math.abs(l - x2) <= d;
+ var rs = Math.abs(r - x1) <= d;
+ if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
+ if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
+ if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
+ if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
+ }
+
+ var first = (ts || bs || ls || rs);
+
+ if(o.snapMode != 'outer') {
+ var ts = Math.abs(t - y1) <= d;
+ var bs = Math.abs(b - y2) <= d;
+ var ls = Math.abs(l - x1) <= d;
+ var rs = Math.abs(r - x2) <= d;
+ if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
+ if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
+ if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
+ if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
+ }
+
+ if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
+ (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
+ inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
+
+ };
+
+ }
+});
+
+$.ui.plugin.add("draggable", "stack", {
+ start: function(event, ui) {
+
+ var o = $(this).data("draggable").options;
+
+ var group = $.makeArray($(o.stack)).sort(function(a,b) {
+ return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
+ });
+ if (!group.length) { return; }
+
+ var min = parseInt(group[0].style.zIndex) || 0;
+ $(group).each(function(i) {
+ this.style.zIndex = min + i;
+ });
+
+ this[0].style.zIndex = min + group.length;
+
+ }
+});
+
+$.ui.plugin.add("draggable", "zIndex", {
+ start: function(event, ui) {
+ var t = $(ui.helper), o = $(this).data("draggable").options;
+ if(t.css("zIndex")) o._zIndex = t.css("zIndex");
+ t.css('zIndex', o.zIndex);
+ },
+ stop: function(event, ui) {
+ var o = $(this).data("draggable").options;
+ if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
+ }
+});
+
+})(jQuery);
+/*
+ * jQuery UI Droppable 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Droppables
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ * jquery.ui.mouse.js
+ * jquery.ui.draggable.js
+ */
+(function( $, undefined ) {
+
+$.widget("ui.droppable", {
+ widgetEventPrefix: "drop",
+ options: {
+ accept: '*',
+ activeClass: false,
+ addClasses: true,
+ greedy: false,
+ hoverClass: false,
+ scope: 'default',
+ tolerance: 'intersect'
+ },
+ _create: function() {
+
+ var o = this.options, accept = o.accept;
+ this.isover = 0; this.isout = 1;
+
+ this.accept = $.isFunction(accept) ? accept : function(d) {
+ return d.is(accept);
+ };
+
+ //Store the droppable's proportions
+ this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
+
+ // Add the reference and positions to the manager
+ $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
+ $.ui.ddmanager.droppables[o.scope].push(this);
+
+ (o.addClasses && this.element.addClass("ui-droppable"));
+
+ },
+
+ destroy: function() {
+ var drop = $.ui.ddmanager.droppables[this.options.scope];
+ for ( var i = 0; i < drop.length; i++ )
+ if ( drop[i] == this )
+ drop.splice(i, 1);
+
+ this.element
+ .removeClass("ui-droppable ui-droppable-disabled")
+ .removeData("droppable")
+ .unbind(".droppable");
+
+ return this;
+ },
+
+ _setOption: function(key, value) {
+
+ if(key == 'accept') {
+ this.accept = $.isFunction(value) ? value : function(d) {
+ return d.is(value);
+ };
+ }
+ $.Widget.prototype._setOption.apply(this, arguments);
+ },
+
+ _activate: function(event) {
+ var draggable = $.ui.ddmanager.current;
+ if(this.options.activeClass) this.element.addClass(this.options.activeClass);
+ (draggable && this._trigger('activate', event, this.ui(draggable)));
+ },
+
+ _deactivate: function(event) {
+ var draggable = $.ui.ddmanager.current;
+ if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
+ (draggable && this._trigger('deactivate', event, this.ui(draggable)));
+ },
+
+ _over: function(event) {
+
+ var draggable = $.ui.ddmanager.current;
+ if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
+
+ if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
+ if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
+ this._trigger('over', event, this.ui(draggable));
+ }
+
+ },
+
+ _out: function(event) {
+
+ var draggable = $.ui.ddmanager.current;
+ if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
+
+ if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
+ if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
+ this._trigger('out', event, this.ui(draggable));
+ }
+
+ },
+
+ _drop: function(event,custom) {
+
+ var draggable = custom || $.ui.ddmanager.current;
+ if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
+
+ var childrenIntersection = false;
+ this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
+ var inst = $.data(this, 'droppable');
+ if(
+ inst.options.greedy
+ && !inst.options.disabled
+ && inst.options.scope == draggable.options.scope
+ && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
+ && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
+ ) { childrenIntersection = true; return false; }
+ });
+ if(childrenIntersection) return false;
+
+ if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
+ if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
+ if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
+ this._trigger('drop', event, this.ui(draggable));
+ return this.element;
+ }
+
+ return false;
+
+ },
+
+ ui: function(c) {
+ return {
+ draggable: (c.currentItem || c.element),
+ helper: c.helper,
+ position: c.position,
+ offset: c.positionAbs
+ };
+ }
+
+});
+
+$.extend($.ui.droppable, {
+ version: "1.8.18"
+});
+
+$.ui.intersect = function(draggable, droppable, toleranceMode) {
+
+ if (!droppable.offset) return false;
+
+ var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
+ y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
+ var l = droppable.offset.left, r = l + droppable.proportions.width,
+ t = droppable.offset.top, b = t + droppable.proportions.height;
+
+ switch (toleranceMode) {
+ case 'fit':
+ return (l <= x1 && x2 <= r
+ && t <= y1 && y2 <= b);
+ break;
+ case 'intersect':
+ return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
+ && x2 - (draggable.helperProportions.width / 2) < r // Left Half
+ && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
+ && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
+ break;
+ case 'pointer':
+ var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
+ draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
+ isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
+ return isOver;
+ break;
+ case 'touch':
+ return (
+ (y1 >= t && y1 <= b) || // Top edge touching
+ (y2 >= t && y2 <= b) || // Bottom edge touching
+ (y1 < t && y2 > b) // Surrounded vertically
+ ) && (
+ (x1 >= l && x1 <= r) || // Left edge touching
+ (x2 >= l && x2 <= r) || // Right edge touching
+ (x1 < l && x2 > r) // Surrounded horizontally
+ );
+ break;
+ default:
+ return false;
+ break;
+ }
+
+};
+
+/*
+ This manager tracks offsets of draggables and droppables
+*/
+$.ui.ddmanager = {
+ current: null,
+ droppables: { 'default': [] },
+ prepareOffsets: function(t, event) {
+
+ var m = $.ui.ddmanager.droppables[t.options.scope] || [];
+ var type = event ? event.type : null; // workaround for #2317
+ var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
+
+ droppablesLoop: for (var i = 0; i < m.length; i++) {
+
+ if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted
+ for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
+ m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue
+
+ if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
+
+ m[i].offset = m[i].element.offset();
+ m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
+
+ }
+
+ },
+ drop: function(draggable, event) {
+
+ var dropped = false;
+ $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
+
+ if(!this.options) return;
+ if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
+ dropped = this._drop.call(this, event) || dropped;
+
+ if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
+ this.isout = 1; this.isover = 0;
+ this._deactivate.call(this, event);
+ }
+
+ });
+ return dropped;
+
+ },
+ dragStart: function( draggable, event ) {
+ //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
+ draggable.element.parents( ":not(body,html)" ).bind( "scroll.droppable", function() {
+ if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
+ });
+ },
+ drag: function(draggable, event) {
+
+ //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
+ if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
+
+ //Run through all droppables and check their positions based on specific tolerance options
+ $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
+
+ if(this.options.disabled || this.greedyChild || !this.visible) return;
+ var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
+
+ var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
+ if(!c) return;
+
+ var parentInstance;
+ if (this.options.greedy) {
+ var parent = this.element.parents(':data(droppable):eq(0)');
+ if (parent.length) {
+ parentInstance = $.data(parent[0], 'droppable');
+ parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
+ }
+ }
+
+ // we just moved into a greedy child
+ if (parentInstance && c == 'isover') {
+ parentInstance['isover'] = 0;
+ parentInstance['isout'] = 1;
+ parentInstance._out.call(parentInstance, event);
+ }
+
+ this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
+ this[c == "isover" ? "_over" : "_out"].call(this, event);
+
+ // we just moved out of a greedy child
+ if (parentInstance && c == 'isout') {
+ parentInstance['isout'] = 0;
+ parentInstance['isover'] = 1;
+ parentInstance._over.call(parentInstance, event);
+ }
+ });
+
+ },
+ dragStop: function( draggable, event ) {
+ draggable.element.parents( ":not(body,html)" ).unbind( "scroll.droppable" );
+ //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
+ if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
+ }
+};
+
+})(jQuery);
+/*
+ * jQuery UI Resizable 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Resizables
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+$.widget("ui.resizable", $.ui.mouse, {
+ widgetEventPrefix: "resize",
+ options: {
+ alsoResize: false,
+ animate: false,
+ animateDuration: "slow",
+ animateEasing: "swing",
+ aspectRatio: false,
+ autoHide: false,
+ containment: false,
+ ghost: false,
+ grid: false,
+ handles: "e,s,se",
+ helper: false,
+ maxHeight: null,
+ maxWidth: null,
+ minHeight: 10,
+ minWidth: 10,
+ zIndex: 1000
+ },
+ _create: function() {
+
+ var self = this, o = this.options;
+ this.element.addClass("ui-resizable");
+
+ $.extend(this, {
+ _aspectRatio: !!(o.aspectRatio),
+ aspectRatio: o.aspectRatio,
+ originalElement: this.element,
+ _proportionallyResizeElements: [],
+ _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
+ });
+
+ //Wrap the element if it cannot hold child nodes
+ if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
+
+ //Create a wrapper element and set the wrapper to the new current internal element
+ this.element.wrap(
+ $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
+ position: this.element.css('position'),
+ width: this.element.outerWidth(),
+ height: this.element.outerHeight(),
+ top: this.element.css('top'),
+ left: this.element.css('left')
+ })
+ );
+
+ //Overwrite the original this.element
+ this.element = this.element.parent().data(
+ "resizable", this.element.data('resizable')
+ );
+
+ this.elementIsWrapper = true;
+
+ //Move margins to the wrapper
+ this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
+ this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
+
+ //Prevent Safari textarea resize
+ this.originalResizeStyle = this.originalElement.css('resize');
+ this.originalElement.css('resize', 'none');
+
+ //Push the actual element to our proportionallyResize internal array
+ this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
+
+ // avoid IE jump (hard set the margin)
+ this.originalElement.css({ margin: this.originalElement.css('margin') });
+
+ // fix handlers offset
+ this._proportionallyResize();
+
+ }
+
+ this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
+ if(this.handles.constructor == String) {
+
+ if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
+ var n = this.handles.split(","); this.handles = {};
+
+ for(var i = 0; i < n.length; i++) {
+
+ var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
+ var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
+
+ // increase zIndex of sw, se, ne, nw axis
+ //TODO : this modifies original option
+ if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
+
+ //TODO : What's going on here?
+ if ('se' == handle) {
+ axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
+ };
+
+ //Insert into internal handles object and append to element
+ this.handles[handle] = '.ui-resizable-'+handle;
+ this.element.append(axis);
+ }
+
+ }
+
+ this._renderAxis = function(target) {
+
+ target = target || this.element;
+
+ for(var i in this.handles) {
+
+ if(this.handles[i].constructor == String)
+ this.handles[i] = $(this.handles[i], this.element).show();
+
+ //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
+ if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
+
+ var axis = $(this.handles[i], this.element), padWrapper = 0;
+
+ //Checking the correct pad and border
+ padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
+
+ //The padding type i have to apply...
+ var padPos = [ 'padding',
+ /ne|nw|n/.test(i) ? 'Top' :
+ /se|sw|s/.test(i) ? 'Bottom' :
+ /^e$/.test(i) ? 'Right' : 'Left' ].join("");
+
+ target.css(padPos, padWrapper);
+
+ this._proportionallyResize();
+
+ }
+
+ //TODO: What's that good for? There's not anything to be executed left
+ if(!$(this.handles[i]).length)
+ continue;
+
+ }
+ };
+
+ //TODO: make renderAxis a prototype function
+ this._renderAxis(this.element);
+
+ this._handles = $('.ui-resizable-handle', this.element)
+ .disableSelection();
+
+ //Matching axis name
+ this._handles.mouseover(function() {
+ if (!self.resizing) {
+ if (this.className)
+ var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
+ //Axis, default = se
+ self.axis = axis && axis[1] ? axis[1] : 'se';
+ }
+ });
+
+ //If we want to auto hide the elements
+ if (o.autoHide) {
+ this._handles.hide();
+ $(this.element)
+ .addClass("ui-resizable-autohide")
+ .hover(function() {
+ if (o.disabled) return;
+ $(this).removeClass("ui-resizable-autohide");
+ self._handles.show();
+ },
+ function(){
+ if (o.disabled) return;
+ if (!self.resizing) {
+ $(this).addClass("ui-resizable-autohide");
+ self._handles.hide();
+ }
+ });
+ }
+
+ //Initialize the mouse interaction
+ this._mouseInit();
+
+ },
+
+ destroy: function() {
+
+ this._mouseDestroy();
+
+ var _destroy = function(exp) {
+ $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
+ .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
+ };
+
+ //TODO: Unwrap at same DOM position
+ if (this.elementIsWrapper) {
+ _destroy(this.element);
+ var wrapper = this.element;
+ wrapper.after(
+ this.originalElement.css({
+ position: wrapper.css('position'),
+ width: wrapper.outerWidth(),
+ height: wrapper.outerHeight(),
+ top: wrapper.css('top'),
+ left: wrapper.css('left')
+ })
+ ).remove();
+ }
+
+ this.originalElement.css('resize', this.originalResizeStyle);
+ _destroy(this.originalElement);
+
+ return this;
+ },
+
+ _mouseCapture: function(event) {
+ var handle = false;
+ for (var i in this.handles) {
+ if ($(this.handles[i])[0] == event.target) {
+ handle = true;
+ }
+ }
+
+ return !this.options.disabled && handle;
+ },
+
+ _mouseStart: function(event) {
+
+ var o = this.options, iniPos = this.element.position(), el = this.element;
+
+ this.resizing = true;
+ this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
+
+ // bugfix for http://dev.jquery.com/ticket/1749
+ if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
+ el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
+ }
+
+ this._renderProxy();
+
+ var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
+
+ if (o.containment) {
+ curleft += $(o.containment).scrollLeft() || 0;
+ curtop += $(o.containment).scrollTop() || 0;
+ }
+
+ //Store needed variables
+ this.offset = this.helper.offset();
+ this.position = { left: curleft, top: curtop };
+ this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
+ this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
+ this.originalPosition = { left: curleft, top: curtop };
+ this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
+ this.originalMousePosition = { left: event.pageX, top: event.pageY };
+
+ //Aspect Ratio
+ this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
+
+ var cursor = $('.ui-resizable-' + this.axis).css('cursor');
+ $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
+
+ el.addClass("ui-resizable-resizing");
+ this._propagate("start", event);
+ return true;
+ },
+
+ _mouseDrag: function(event) {
+
+ //Increase performance, avoid regex
+ var el = this.helper, o = this.options, props = {},
+ self = this, smp = this.originalMousePosition, a = this.axis;
+
+ var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
+ var trigger = this._change[a];
+ if (!trigger) return false;
+
+ // Calculate the attrs that will be change
+ var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
+
+ // Put this in the mouseDrag handler since the user can start pressing shift while resizing
+ this._updateVirtualBoundaries(event.shiftKey);
+ if (this._aspectRatio || event.shiftKey)
+ data = this._updateRatio(data, event);
+
+ data = this._respectSize(data, event);
+
+ // plugins callbacks need to be called first
+ this._propagate("resize", event);
+
+ el.css({
+ top: this.position.top + "px", left: this.position.left + "px",
+ width: this.size.width + "px", height: this.size.height + "px"
+ });
+
+ if (!this._helper && this._proportionallyResizeElements.length)
+ this._proportionallyResize();
+
+ this._updateCache(data);
+
+ // calling the user callback at the end
+ this._trigger('resize', event, this.ui());
+
+ return false;
+ },
+
+ _mouseStop: function(event) {
+
+ this.resizing = false;
+ var o = this.options, self = this;
+
+ if(this._helper) {
+ var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
+ soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
+ soffsetw = ista ? 0 : self.sizeDiff.width;
+
+ var s = { width: (self.helper.width() - soffsetw), height: (self.helper.height() - soffseth) },
+ left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
+ top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
+
+ if (!o.animate)
+ this.element.css($.extend(s, { top: top, left: left }));
+
+ self.helper.height(self.size.height);
+ self.helper.width(self.size.width);
+
+ if (this._helper && !o.animate) this._proportionallyResize();
+ }
+
+ $('body').css('cursor', 'auto');
+
+ this.element.removeClass("ui-resizable-resizing");
+
+ this._propagate("stop", event);
+
+ if (this._helper) this.helper.remove();
+ return false;
+
+ },
+
+ _updateVirtualBoundaries: function(forceAspectRatio) {
+ var o = this.options, pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b;
+
+ b = {
+ minWidth: isNumber(o.minWidth) ? o.minWidth : 0,
+ maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,
+ minHeight: isNumber(o.minHeight) ? o.minHeight : 0,
+ maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity
+ };
+
+ if(this._aspectRatio || forceAspectRatio) {
+ // We want to create an enclosing box whose aspect ration is the requested one
+ // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension
+ pMinWidth = b.minHeight * this.aspectRatio;
+ pMinHeight = b.minWidth / this.aspectRatio;
+ pMaxWidth = b.maxHeight * this.aspectRatio;
+ pMaxHeight = b.maxWidth / this.aspectRatio;
+
+ if(pMinWidth > b.minWidth) b.minWidth = pMinWidth;
+ if(pMinHeight > b.minHeight) b.minHeight = pMinHeight;
+ if(pMaxWidth < b.maxWidth) b.maxWidth = pMaxWidth;
+ if(pMaxHeight < b.maxHeight) b.maxHeight = pMaxHeight;
+ }
+ this._vBoundaries = b;
+ },
+
+ _updateCache: function(data) {
+ var o = this.options;
+ this.offset = this.helper.offset();
+ if (isNumber(data.left)) this.position.left = data.left;
+ if (isNumber(data.top)) this.position.top = data.top;
+ if (isNumber(data.height)) this.size.height = data.height;
+ if (isNumber(data.width)) this.size.width = data.width;
+ },
+
+ _updateRatio: function(data, event) {
+
+ var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
+
+ if (isNumber(data.height)) data.width = (data.height * this.aspectRatio);
+ else if (isNumber(data.width)) data.height = (data.width / this.aspectRatio);
+
+ if (a == 'sw') {
+ data.left = cpos.left + (csize.width - data.width);
+ data.top = null;
+ }
+ if (a == 'nw') {
+ data.top = cpos.top + (csize.height - data.height);
+ data.left = cpos.left + (csize.width - data.width);
+ }
+
+ return data;
+ },
+
+ _respectSize: function(data, event) {
+
+ var el = this.helper, o = this._vBoundaries, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
+ ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
+ isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
+
+ if (isminw) data.width = o.minWidth;
+ if (isminh) data.height = o.minHeight;
+ if (ismaxw) data.width = o.maxWidth;
+ if (ismaxh) data.height = o.maxHeight;
+
+ var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
+ var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
+
+ if (isminw && cw) data.left = dw - o.minWidth;
+ if (ismaxw && cw) data.left = dw - o.maxWidth;
+ if (isminh && ch) data.top = dh - o.minHeight;
+ if (ismaxh && ch) data.top = dh - o.maxHeight;
+
+ // fixing jump error on top/left - bug #2330
+ var isNotwh = !data.width && !data.height;
+ if (isNotwh && !data.left && data.top) data.top = null;
+ else if (isNotwh && !data.top && data.left) data.left = null;
+
+ return data;
+ },
+
+ _proportionallyResize: function() {
+
+ var o = this.options;
+ if (!this._proportionallyResizeElements.length) return;
+ var element = this.helper || this.element;
+
+ for (var i=0; i < this._proportionallyResizeElements.length; i++) {
+
+ var prel = this._proportionallyResizeElements[i];
+
+ if (!this.borderDif) {
+ var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
+ p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
+
+ this.borderDif = $.map(b, function(v, i) {
+ var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
+ return border + padding;
+ });
+ }
+
+ if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
+ continue;
+
+ prel.css({
+ height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
+ width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
+ });
+
+ };
+
+ },
+
+ _renderProxy: function() {
+
+ var el = this.element, o = this.options;
+ this.elementOffset = el.offset();
+
+ if(this._helper) {
+
+ this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
+
+ // fix ie6 offset TODO: This seems broken
+ var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
+ pxyoffset = ( ie6 ? 2 : -1 );
+
+ this.helper.addClass(this._helper).css({
+ width: this.element.outerWidth() + pxyoffset,
+ height: this.element.outerHeight() + pxyoffset,
+ position: 'absolute',
+ left: this.elementOffset.left - ie6offset +'px',
+ top: this.elementOffset.top - ie6offset +'px',
+ zIndex: ++o.zIndex //TODO: Don't modify option
+ });
+
+ this.helper
+ .appendTo("body")
+ .disableSelection();
+
+ } else {
+ this.helper = this.element;
+ }
+
+ },
+
+ _change: {
+ e: function(event, dx, dy) {
+ return { width: this.originalSize.width + dx };
+ },
+ w: function(event, dx, dy) {
+ var o = this.options, cs = this.originalSize, sp = this.originalPosition;
+ return { left: sp.left + dx, width: cs.width - dx };
+ },
+ n: function(event, dx, dy) {
+ var o = this.options, cs = this.originalSize, sp = this.originalPosition;
+ return { top: sp.top + dy, height: cs.height - dy };
+ },
+ s: function(event, dx, dy) {
+ return { height: this.originalSize.height + dy };
+ },
+ se: function(event, dx, dy) {
+ return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
+ },
+ sw: function(event, dx, dy) {
+ return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
+ },
+ ne: function(event, dx, dy) {
+ return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
+ },
+ nw: function(event, dx, dy) {
+ return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
+ }
+ },
+
+ _propagate: function(n, event) {
+ $.ui.plugin.call(this, n, [event, this.ui()]);
+ (n != "resize" && this._trigger(n, event, this.ui()));
+ },
+
+ plugins: {},
+
+ ui: function() {
+ return {
+ originalElement: this.originalElement,
+ element: this.element,
+ helper: this.helper,
+ position: this.position,
+ size: this.size,
+ originalSize: this.originalSize,
+ originalPosition: this.originalPosition
+ };
+ }
+
+});
+
+$.extend($.ui.resizable, {
+ version: "1.8.18"
+});
+
+/*
+ * Resizable Extensions
+ */
+
+$.ui.plugin.add("resizable", "alsoResize", {
+
+ start: function (event, ui) {
+ var self = $(this).data("resizable"), o = self.options;
+
+ var _store = function (exp) {
+ $(exp).each(function() {
+ var el = $(this);
+ el.data("resizable-alsoresize", {
+ width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
+ left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10)
+ });
+ });
+ };
+
+ if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
+ if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
+ else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
+ }else{
+ _store(o.alsoResize);
+ }
+ },
+
+ resize: function (event, ui) {
+ var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
+
+ var delta = {
+ height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
+ top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
+ },
+
+ _alsoResize = function (exp, c) {
+ $(exp).each(function() {
+ var el = $(this), start = $(this).data("resizable-alsoresize"), style = {},
+ css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
+
+ $.each(css, function (i, prop) {
+ var sum = (start[prop]||0) + (delta[prop]||0);
+ if (sum && sum >= 0)
+ style[prop] = sum || null;
+ });
+
+ el.css(style);
+ });
+ };
+
+ if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
+ $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
+ }else{
+ _alsoResize(o.alsoResize);
+ }
+ },
+
+ stop: function (event, ui) {
+ $(this).removeData("resizable-alsoresize");
+ }
+});
+
+$.ui.plugin.add("resizable", "animate", {
+
+ stop: function(event, ui) {
+ var self = $(this).data("resizable"), o = self.options;
+
+ var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
+ soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
+ soffsetw = ista ? 0 : self.sizeDiff.width;
+
+ var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
+ left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
+ top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
+
+ self.element.animate(
+ $.extend(style, top && left ? { top: top, left: left } : {}), {
+ duration: o.animateDuration,
+ easing: o.animateEasing,
+ step: function() {
+
+ var data = {
+ width: parseInt(self.element.css('width'), 10),
+ height: parseInt(self.element.css('height'), 10),
+ top: parseInt(self.element.css('top'), 10),
+ left: parseInt(self.element.css('left'), 10)
+ };
+
+ if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
+
+ // propagating resize, and updating values for each animation step
+ self._updateCache(data);
+ self._propagate("resize", event);
+
+ }
+ }
+ );
+ }
+
+});
+
+$.ui.plugin.add("resizable", "containment", {
+
+ start: function(event, ui) {
+ var self = $(this).data("resizable"), o = self.options, el = self.element;
+ var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
+ if (!ce) return;
+
+ self.containerElement = $(ce);
+
+ if (/document/.test(oc) || oc == document) {
+ self.containerOffset = { left: 0, top: 0 };
+ self.containerPosition = { left: 0, top: 0 };
+
+ self.parentData = {
+ element: $(document), left: 0, top: 0,
+ width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
+ };
+ }
+
+ // i'm a node, so compute top, left, right, bottom
+ else {
+ var element = $(ce), p = [];
+ $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
+
+ self.containerOffset = element.offset();
+ self.containerPosition = element.position();
+ self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
+
+ var co = self.containerOffset, ch = self.containerSize.height, cw = self.containerSize.width,
+ width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
+
+ self.parentData = {
+ element: ce, left: co.left, top: co.top, width: width, height: height
+ };
+ }
+ },
+
+ resize: function(event, ui) {
+ var self = $(this).data("resizable"), o = self.options,
+ ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
+ pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
+
+ if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
+
+ if (cp.left < (self._helper ? co.left : 0)) {
+ self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
+ if (pRatio) self.size.height = self.size.width / o.aspectRatio;
+ self.position.left = o.helper ? co.left : 0;
+ }
+
+ if (cp.top < (self._helper ? co.top : 0)) {
+ self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
+ if (pRatio) self.size.width = self.size.height * o.aspectRatio;
+ self.position.top = self._helper ? co.top : 0;
+ }
+
+ self.offset.left = self.parentData.left+self.position.left;
+ self.offset.top = self.parentData.top+self.position.top;
+
+ var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
+ hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
+
+ var isParent = self.containerElement.get(0) == self.element.parent().get(0),
+ isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
+
+ if(isParent && isOffsetRelative) woset -= self.parentData.left;
+
+ if (woset + self.size.width >= self.parentData.width) {
+ self.size.width = self.parentData.width - woset;
+ if (pRatio) self.size.height = self.size.width / self.aspectRatio;
+ }
+
+ if (hoset + self.size.height >= self.parentData.height) {
+ self.size.height = self.parentData.height - hoset;
+ if (pRatio) self.size.width = self.size.height * self.aspectRatio;
+ }
+ },
+
+ stop: function(event, ui){
+ var self = $(this).data("resizable"), o = self.options, cp = self.position,
+ co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
+
+ var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
+
+ if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
+ $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
+
+ if (self._helper && !o.animate && (/static/).test(ce.css('position')))
+ $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
+
+ }
+});
+
+$.ui.plugin.add("resizable", "ghost", {
+
+ start: function(event, ui) {
+
+ var self = $(this).data("resizable"), o = self.options, cs = self.size;
+
+ self.ghost = self.originalElement.clone();
+ self.ghost
+ .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
+ .addClass('ui-resizable-ghost')
+ .addClass(typeof o.ghost == 'string' ? o.ghost : '');
+
+ self.ghost.appendTo(self.helper);
+
+ },
+
+ resize: function(event, ui){
+ var self = $(this).data("resizable"), o = self.options;
+ if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
+ },
+
+ stop: function(event, ui){
+ var self = $(this).data("resizable"), o = self.options;
+ if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
+ }
+
+});
+
+$.ui.plugin.add("resizable", "grid", {
+
+ resize: function(event, ui) {
+ var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
+ o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
+ var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
+
+ if (/^(se|s|e)$/.test(a)) {
+ self.size.width = os.width + ox;
+ self.size.height = os.height + oy;
+ }
+ else if (/^(ne)$/.test(a)) {
+ self.size.width = os.width + ox;
+ self.size.height = os.height + oy;
+ self.position.top = op.top - oy;
+ }
+ else if (/^(sw)$/.test(a)) {
+ self.size.width = os.width + ox;
+ self.size.height = os.height + oy;
+ self.position.left = op.left - ox;
+ }
+ else {
+ self.size.width = os.width + ox;
+ self.size.height = os.height + oy;
+ self.position.top = op.top - oy;
+ self.position.left = op.left - ox;
+ }
+ }
+
+});
+
+var num = function(v) {
+ return parseInt(v, 10) || 0;
+};
+
+var isNumber = function(value) {
+ return !isNaN(parseInt(value, 10));
+};
+
+})(jQuery);
+/*
+ * jQuery UI Selectable 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Selectables
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+$.widget("ui.selectable", $.ui.mouse, {
+ options: {
+ appendTo: 'body',
+ autoRefresh: true,
+ distance: 0,
+ filter: '*',
+ tolerance: 'touch'
+ },
+ _create: function() {
+ var self = this;
+
+ this.element.addClass("ui-selectable");
+
+ this.dragged = false;
+
+ // cache selectee children based on filter
+ var selectees;
+ this.refresh = function() {
+ selectees = $(self.options.filter, self.element[0]);
+ selectees.addClass("ui-selectee");
+ selectees.each(function() {
+ var $this = $(this);
+ var pos = $this.offset();
+ $.data(this, "selectable-item", {
+ element: this,
+ $element: $this,
+ left: pos.left,
+ top: pos.top,
+ right: pos.left + $this.outerWidth(),
+ bottom: pos.top + $this.outerHeight(),
+ startselected: false,
+ selected: $this.hasClass('ui-selected'),
+ selecting: $this.hasClass('ui-selecting'),
+ unselecting: $this.hasClass('ui-unselecting')
+ });
+ });
+ };
+ this.refresh();
+
+ this.selectees = selectees.addClass("ui-selectee");
+
+ this._mouseInit();
+
+ this.helper = $("<div class='ui-selectable-helper'></div>");
+ },
+
+ destroy: function() {
+ this.selectees
+ .removeClass("ui-selectee")
+ .removeData("selectable-item");
+ this.element
+ .removeClass("ui-selectable ui-selectable-disabled")
+ .removeData("selectable")
+ .unbind(".selectable");
+ this._mouseDestroy();
+
+ return this;
+ },
+
+ _mouseStart: function(event) {
+ var self = this;
+
+ this.opos = [event.pageX, event.pageY];
+
+ if (this.options.disabled)
+ return;
+
+ var options = this.options;
+
+ this.selectees = $(options.filter, this.element[0]);
+
+ this._trigger("start", event);
+
+ $(options.appendTo).append(this.helper);
+ // position helper (lasso)
+ this.helper.css({
+ "left": event.clientX,
+ "top": event.clientY,
+ "width": 0,
+ "height": 0
+ });
+
+ if (options.autoRefresh) {
+ this.refresh();
+ }
+
+ this.selectees.filter('.ui-selected').each(function() {
+ var selectee = $.data(this, "selectable-item");
+ selectee.startselected = true;
+ if (!event.metaKey && !event.ctrlKey) {
+ selectee.$element.removeClass('ui-selected');
+ selectee.selected = false;
+ selectee.$element.addClass('ui-unselecting');
+ selectee.unselecting = true;
+ // selectable UNSELECTING callback
+ self._trigger("unselecting", event, {
+ unselecting: selectee.element
+ });
+ }
+ });
+
+ $(event.target).parents().andSelf().each(function() {
+ var selectee = $.data(this, "selectable-item");
+ if (selectee) {
+ var doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass('ui-selected');
+ selectee.$element
+ .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
+ .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
+ selectee.unselecting = !doSelect;
+ selectee.selecting = doSelect;
+ selectee.selected = doSelect;
+ // selectable (UN)SELECTING callback
+ if (doSelect) {
+ self._trigger("selecting", event, {
+ selecting: selectee.element
+ });
+ } else {
+ self._trigger("unselecting", event, {
+ unselecting: selectee.element
+ });
+ }
+ return false;
+ }
+ });
+
+ },
+
+ _mouseDrag: function(event) {
+ var self = this;
+ this.dragged = true;
+
+ if (this.options.disabled)
+ return;
+
+ var options = this.options;
+
+ var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
+ if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
+ if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
+ this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
+
+ this.selectees.each(function() {
+ var selectee = $.data(this, "selectable-item");
+ //prevent helper from being selected if appendTo: selectable
+ if (!selectee || selectee.element == self.element[0])
+ return;
+ var hit = false;
+ if (options.tolerance == 'touch') {
+ hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
+ } else if (options.tolerance == 'fit') {
+ hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
+ }
+
+ if (hit) {
+ // SELECT
+ if (selectee.selected) {
+ selectee.$element.removeClass('ui-selected');
+ selectee.selected = false;
+ }
+ if (selectee.unselecting) {
+ selectee.$element.removeClass('ui-unselecting');
+ selectee.unselecting = false;
+ }
+ if (!selectee.selecting) {
+ selectee.$element.addClass('ui-selecting');
+ selectee.selecting = true;
+ // selectable SELECTING callback
+ self._trigger("selecting", event, {
+ selecting: selectee.element
+ });
+ }
+ } else {
+ // UNSELECT
+ if (selectee.selecting) {
+ if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
+ selectee.$element.removeClass('ui-selecting');
+ selectee.selecting = false;
+ selectee.$element.addClass('ui-selected');
+ selectee.selected = true;
+ } else {
+ selectee.$element.removeClass('ui-selecting');
+ selectee.selecting = false;
+ if (selectee.startselected) {
+ selectee.$element.addClass('ui-unselecting');
+ selectee.unselecting = true;
+ }
+ // selectable UNSELECTING callback
+ self._trigger("unselecting", event, {
+ unselecting: selectee.element
+ });
+ }
+ }
+ if (selectee.selected) {
+ if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
+ selectee.$element.removeClass('ui-selected');
+ selectee.selected = false;
+
+ selectee.$element.addClass('ui-unselecting');
+ selectee.unselecting = true;
+ // selectable UNSELECTING callback
+ self._trigger("unselecting", event, {
+ unselecting: selectee.element
+ });
+ }
+ }
+ }
+ });
+
+ return false;
+ },
+
+ _mouseStop: function(event) {
+ var self = this;
+
+ this.dragged = false;
+
+ var options = this.options;
+
+ $('.ui-unselecting', this.element[0]).each(function() {
+ var selectee = $.data(this, "selectable-item");
+ selectee.$element.removeClass('ui-unselecting');
+ selectee.unselecting = false;
+ selectee.startselected = false;
+ self._trigger("unselected", event, {
+ unselected: selectee.element
+ });
+ });
+ $('.ui-selecting', this.element[0]).each(function() {
+ var selectee = $.data(this, "selectable-item");
+ selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
+ selectee.selecting = false;
+ selectee.selected = true;
+ selectee.startselected = true;
+ self._trigger("selected", event, {
+ selected: selectee.element
+ });
+ });
+ this._trigger("stop", event);
+
+ this.helper.remove();
+
+ return false;
+ }
+
+});
+
+$.extend($.ui.selectable, {
+ version: "1.8.18"
+});
+
+})(jQuery);
+/*
+ * jQuery UI Sortable 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Sortables
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+$.widget("ui.sortable", $.ui.mouse, {
+ widgetEventPrefix: "sort",
+ ready: false,
+ options: {
+ appendTo: "parent",
+ axis: false,
+ connectWith: false,
+ containment: false,
+ cursor: 'auto',
+ cursorAt: false,
+ dropOnEmpty: true,
+ forcePlaceholderSize: false,
+ forceHelperSize: false,
+ grid: false,
+ handle: false,
+ helper: "original",
+ items: '> *',
+ opacity: false,
+ placeholder: false,
+ revert: false,
+ scroll: true,
+ scrollSensitivity: 20,
+ scrollSpeed: 20,
+ scope: "default",
+ tolerance: "intersect",
+ zIndex: 1000
+ },
+ _create: function() {
+
+ var o = this.options;
+ this.containerCache = {};
+ this.element.addClass("ui-sortable");
+
+ //Get the items
+ this.refresh();
+
+ //Let's determine if the items are being displayed horizontally
+ this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false;
+
+ //Let's determine the parent's offset
+ this.offset = this.element.offset();
+
+ //Initialize mouse events for interaction
+ this._mouseInit();
+
+ //We're ready to go
+ this.ready = true
+
+ },
+
+ destroy: function() {
+ $.Widget.prototype.destroy.call( this );
+ this.element
+ .removeClass("ui-sortable ui-sortable-disabled");
+ this._mouseDestroy();
+
+ for ( var i = this.items.length - 1; i >= 0; i-- )
+ this.items[i].item.removeData(this.widgetName + "-item");
+
+ return this;
+ },
+
+ _setOption: function(key, value){
+ if ( key === "disabled" ) {
+ this.options[ key ] = value;
+
+ this.widget()
+ [ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
+ } else {
+ // Don't call widget base _setOption for disable as it adds ui-state-disabled class
+ $.Widget.prototype._setOption.apply(this, arguments);
+ }
+ },
+
+ _mouseCapture: function(event, overrideHandle) {
+ var that = this;
+
+ if (this.reverting) {
+ return false;
+ }
+
+ if(this.options.disabled || this.options.type == 'static') return false;
+
+ //We have to refresh the items data once first
+ this._refreshItems(event);
+
+ //Find out if the clicked node (or one of its parents) is a actual item in this.items
+ var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
+ if($.data(this, that.widgetName + '-item') == self) {
+ currentItem = $(this);
+ return false;
+ }
+ });
+ if($.data(event.target, that.widgetName + '-item') == self) currentItem = $(event.target);
+
+ if(!currentItem) return false;
+ if(this.options.handle && !overrideHandle) {
+ var validHandle = false;
+
+ $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
+ if(!validHandle) return false;
+ }
+
+ this.currentItem = currentItem;
+ this._removeCurrentsFromItems();
+ return true;
+
+ },
+
+ _mouseStart: function(event, overrideHandle, noActivation) {
+
+ var o = this.options, self = this;
+ this.currentContainer = this;
+
+ //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
+ this.refreshPositions();
+
+ //Create and append the visible helper
+ this.helper = this._createHelper(event);
+
+ //Cache the helper size
+ this._cacheHelperProportions();
+
+ /*
+ * - Position generation -
+ * This block generates everything position related - it's the core of draggables.
+ */
+
+ //Cache the margins of the original element
+ this._cacheMargins();
+
+ //Get the next scrolling parent
+ this.scrollParent = this.helper.scrollParent();
+
+ //The element's absolute position on the page minus margins
+ this.offset = this.currentItem.offset();
+ this.offset = {
+ top: this.offset.top - this.margins.top,
+ left: this.offset.left - this.margins.left
+ };
+
+ // Only after we got the offset, we can change the helper's position to absolute
+ // TODO: Still need to figure out a way to make relative sorting possible
+ this.helper.css("position", "absolute");
+ this.cssPosition = this.helper.css("position");
+
+ $.extend(this.offset, {
+ click: { //Where the click happened, relative to the element
+ left: event.pageX - this.offset.left,
+ top: event.pageY - this.offset.top
+ },
+ parent: this._getParentOffset(),
+ relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
+ });
+
+ //Generate the original position
+ this.originalPosition = this._generatePosition(event);
+ this.originalPageX = event.pageX;
+ this.originalPageY = event.pageY;
+
+ //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
+ (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
+
+ //Cache the former DOM position
+ this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
+
+ //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
+ if(this.helper[0] != this.currentItem[0]) {
+ this.currentItem.hide();
+ }
+
+ //Create the placeholder
+ this._createPlaceholder();
+
+ //Set a containment if given in the options
+ if(o.containment)
+ this._setContainment();
+
+ if(o.cursor) { // cursor option
+ if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
+ $('body').css("cursor", o.cursor);
+ }
+
+ if(o.opacity) { // opacity option
+ if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
+ this.helper.css("opacity", o.opacity);
+ }
+
+ if(o.zIndex) { // zIndex option
+ if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
+ this.helper.css("zIndex", o.zIndex);
+ }
+
+ //Prepare scrolling
+ if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
+ this.overflowOffset = this.scrollParent.offset();
+
+ //Call callbacks
+ this._trigger("start", event, this._uiHash());
+
+ //Recache the helper size
+ if(!this._preserveHelperProportions)
+ this._cacheHelperProportions();
+
+
+ //Post 'activate' events to possible containers
+ if(!noActivation) {
+ for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
+ }
+
+ //Prepare possible droppables
+ if($.ui.ddmanager)
+ $.ui.ddmanager.current = this;
+
+ if ($.ui.ddmanager && !o.dropBehaviour)
+ $.ui.ddmanager.prepareOffsets(this, event);
+
+ this.dragging = true;
+
+ this.helper.addClass("ui-sortable-helper");
+ this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
+ return true;
+
+ },
+
+ _mouseDrag: function(event) {
+
+ //Compute the helpers position
+ this.position = this._generatePosition(event);
+ this.positionAbs = this._convertPositionTo("absolute");
+
+ if (!this.lastPositionAbs) {
+ this.lastPositionAbs = this.positionAbs;
+ }
+
+ //Do scrolling
+ if(this.options.scroll) {
+ var o = this.options, scrolled = false;
+ if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
+
+ if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
+ this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
+ else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
+ this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
+
+ if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
+ this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
+ else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
+ this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
+
+ } else {
+
+ if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
+ scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
+ else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
+ scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
+
+ if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
+ scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
+ else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
+ scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
+
+ }
+
+ if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
+ $.ui.ddmanager.prepareOffsets(this, event);
+ }
+
+ //Regenerate the absolute position used for position checks
+ this.positionAbs = this._convertPositionTo("absolute");
+
+ //Set the helper position
+ if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
+ if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
+
+ //Rearrange
+ for (var i = this.items.length - 1; i >= 0; i--) {
+
+ //Cache variables and intersection, continue if no intersection
+ var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
+ if (!intersection) continue;
+
+ if(itemElement != this.currentItem[0] //cannot intersect with itself
+ && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
+ && !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
+ && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
+ //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
+ ) {
+
+ this.direction = intersection == 1 ? "down" : "up";
+
+ if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
+ this._rearrange(event, item);
+ } else {
+ break;
+ }
+
+ this._trigger("change", event, this._uiHash());
+ break;
+ }
+ }
+
+ //Post events to containers
+ this._contactContainers(event);
+
+ //Interconnect with droppables
+ if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
+
+ //Call callbacks
+ this._trigger('sort', event, this._uiHash());
+
+ this.lastPositionAbs = this.positionAbs;
+ return false;
+
+ },
+
+ _mouseStop: function(event, noPropagation) {
+
+ if(!event) return;
+
+ //If we are using droppables, inform the manager about the drop
+ if ($.ui.ddmanager && !this.options.dropBehaviour)
+ $.ui.ddmanager.drop(this, event);
+
+ if(this.options.revert) {
+ var self = this;
+ var cur = self.placeholder.offset();
+
+ self.reverting = true;
+
+ $(this.helper).animate({
+ left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
+ top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
+ }, parseInt(this.options.revert, 10) || 500, function() {
+ self._clear(event);
+ });
+ } else {
+ this._clear(event, noPropagation);
+ }
+
+ return false;
+
+ },
+
+ cancel: function() {
+
+ var self = this;
+
+ if(this.dragging) {
+
+ this._mouseUp({ target: null });
+
+ if(this.options.helper == "original")
+ this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
+ else
+ this.currentItem.show();
+
+ //Post deactivating events to containers
+ for (var i = this.containers.length - 1; i >= 0; i--){
+ this.containers[i]._trigger("deactivate", null, self._uiHash(this));
+ if(this.containers[i].containerCache.over) {
+ this.containers[i]._trigger("out", null, self._uiHash(this));
+ this.containers[i].containerCache.over = 0;
+ }
+ }
+
+ }
+
+ if (this.placeholder) {
+ //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
+ if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
+ if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
+
+ $.extend(this, {
+ helper: null,
+ dragging: false,
+ reverting: false,
+ _noFinalSort: null
+ });
+
+ if(this.domPosition.prev) {
+ $(this.domPosition.prev).after(this.currentItem);
+ } else {
+ $(this.domPosition.parent).prepend(this.currentItem);
+ }
+ }
+
+ return this;
+
+ },
+
+ serialize: function(o) {
+
+ var items = this._getItemsAsjQuery(o && o.connected);
+ var str = []; o = o || {};
+
+ $(items).each(function() {
+ var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
+ if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
+ });
+
+ if(!str.length && o.key) {
+ str.push(o.key + '=');
+ }
+
+ return str.join('&');
+
+ },
+
+ toArray: function(o) {
+
+ var items = this._getItemsAsjQuery(o && o.connected);
+ var ret = []; o = o || {};
+
+ items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
+ return ret;
+
+ },
+
+ /* Be careful with the following core functions */
+ _intersectsWith: function(item) {
+
+ var x1 = this.positionAbs.left,
+ x2 = x1 + this.helperProportions.width,
+ y1 = this.positionAbs.top,
+ y2 = y1 + this.helperProportions.height;
+
+ var l = item.left,
+ r = l + item.width,
+ t = item.top,
+ b = t + item.height;
+
+ var dyClick = this.offset.click.top,
+ dxClick = this.offset.click.left;
+
+ var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
+
+ if( this.options.tolerance == "pointer"
+ || this.options.forcePointerForContainers
+ || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
+ ) {
+ return isOverElement;
+ } else {
+
+ return (l < x1 + (this.helperProportions.width / 2) // Right Half
+ && x2 - (this.helperProportions.width / 2) < r // Left Half
+ && t < y1 + (this.helperProportions.height / 2) // Bottom Half
+ && y2 - (this.helperProportions.height / 2) < b ); // Top Half
+
+ }
+ },
+
+ _intersectsWithPointer: function(item) {
+
+ var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
+ isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
+ isOverElement = isOverElementHeight && isOverElementWidth,
+ verticalDirection = this._getDragVerticalDirection(),
+ horizontalDirection = this._getDragHorizontalDirection();
+
+ if (!isOverElement)
+ return false;
+
+ return this.floating ?
+ ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
+ : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
+
+ },
+
+ _intersectsWithSides: function(item) {
+
+ var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
+ isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
+ verticalDirection = this._getDragVerticalDirection(),
+ horizontalDirection = this._getDragHorizontalDirection();
+
+ if (this.floating && horizontalDirection) {
+ return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
+ } else {
+ return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
+ }
+
+ },
+
+ _getDragVerticalDirection: function() {
+ var delta = this.positionAbs.top - this.lastPositionAbs.top;
+ return delta != 0 && (delta > 0 ? "down" : "up");
+ },
+
+ _getDragHorizontalDirection: function() {
+ var delta = this.positionAbs.left - this.lastPositionAbs.left;
+ return delta != 0 && (delta > 0 ? "right" : "left");
+ },
+
+ refresh: function(event) {
+ this._refreshItems(event);
+ this.refreshPositions();
+ return this;
+ },
+
+ _connectWith: function() {
+ var options = this.options;
+ return options.connectWith.constructor == String
+ ? [options.connectWith]
+ : options.connectWith;
+ },
+
+ _getItemsAsjQuery: function(connected) {
+
+ var self = this;
+ var items = [];
+ var queries = [];
+ var connectWith = this._connectWith();
+
+ if(connectWith && connected) {
+ for (var i = connectWith.length - 1; i >= 0; i--){
+ var cur = $(connectWith[i]);
+ for (var j = cur.length - 1; j >= 0; j--){
+ var inst = $.data(cur[j], this.widgetName);
+ if(inst && inst != this && !inst.options.disabled) {
+ queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
+ }
+ };
+ };
+ }
+
+ queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);
+
+ for (var i = queries.length - 1; i >= 0; i--){
+ queries[i][0].each(function() {
+ items.push(this);
+ });
+ };
+
+ return $(items);
+
+ },
+
+ _removeCurrentsFromItems: function() {
+
+ var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
+
+ for (var i=0; i < this.items.length; i++) {
+
+ for (var j=0; j < list.length; j++) {
+ if(list[j] == this.items[i].item[0])
+ this.items.splice(i,1);
+ };
+
+ };
+
+ },
+
+ _refreshItems: function(event) {
+
+ this.items = [];
+ this.containers = [this];
+ var items = this.items;
+ var self = this;
+ var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
+ var connectWith = this._connectWith();
+
+ if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
+ for (var i = connectWith.length - 1; i >= 0; i--){
+ var cur = $(connectWith[i]);
+ for (var j = cur.length - 1; j >= 0; j--){
+ var inst = $.data(cur[j], this.widgetName);
+ if(inst && inst != this && !inst.options.disabled) {
+ queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
+ this.containers.push(inst);
+ }
+ };
+ };
+ }
+
+ for (var i = queries.length - 1; i >= 0; i--) {
+ var targetData = queries[i][1];
+ var _queries = queries[i][0];
+
+ for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
+ var item = $(_queries[j]);
+
+ item.data(this.widgetName + '-item', targetData); // Data for target checking (mouse manager)
+
+ items.push({
+ item: item,
+ instance: targetData,
+ width: 0, height: 0,
+ left: 0, top: 0
+ });
+ };
+ };
+
+ },
+
+ refreshPositions: function(fast) {
+
+ //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
+ if(this.offsetParent && this.helper) {
+ this.offset.parent = this._getParentOffset();
+ }
+
+ for (var i = this.items.length - 1; i >= 0; i--){
+ var item = this.items[i];
+
+ //We ignore calculating positions of all connected containers when we're not over them
+ if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0])
+ continue;
+
+ var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
+
+ if (!fast) {
+ item.width = t.outerWidth();
+ item.height = t.outerHeight();
+ }
+
+ var p = t.offset();
+ item.left = p.left;
+ item.top = p.top;
+ };
+
+ if(this.options.custom && this.options.custom.refreshContainers) {
+ this.options.custom.refreshContainers.call(this);
+ } else {
+ for (var i = this.containers.length - 1; i >= 0; i--){
+ var p = this.containers[i].element.offset();
+ this.containers[i].containerCache.left = p.left;
+ this.containers[i].containerCache.top = p.top;
+ this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
+ this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
+ };
+ }
+
+ return this;
+ },
+
+ _createPlaceholder: function(that) {
+
+ var self = that || this, o = self.options;
+
+ if(!o.placeholder || o.placeholder.constructor == String) {
+ var className = o.placeholder;
+ o.placeholder = {
+ element: function() {
+
+ var el = $(document.createElement(self.currentItem[0].nodeName))
+ .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
+ .removeClass("ui-sortable-helper")[0];
+
+ if(!className)
+ el.style.visibility = "hidden";
+
+ return el;
+ },
+ update: function(container, p) {
+
+ // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
+ // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
+ if(className && !o.forcePlaceholderSize) return;
+
+ //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
+ if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
+ if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
+ }
+ };
+ }
+
+ //Create the placeholder
+ self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
+
+ //Append it after the actual current item
+ self.currentItem.after(self.placeholder);
+
+ //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
+ o.placeholder.update(self, self.placeholder);
+
+ },
+
+ _contactContainers: function(event) {
+
+ // get innermost container that intersects with item
+ var innermostContainer = null, innermostIndex = null;
+
+
+ for (var i = this.containers.length - 1; i >= 0; i--){
+
+ // never consider a container that's located within the item itself
+ if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
+ continue;
+
+ if(this._intersectsWith(this.containers[i].containerCache)) {
+
+ // if we've already found a container and it's more "inner" than this, then continue
+ if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
+ continue;
+
+ innermostContainer = this.containers[i];
+ innermostIndex = i;
+
+ } else {
+ // container doesn't intersect. trigger "out" event if necessary
+ if(this.containers[i].containerCache.over) {
+ this.containers[i]._trigger("out", event, this._uiHash(this));
+ this.containers[i].containerCache.over = 0;
+ }
+ }
+
+ }
+
+ // if no intersecting containers found, return
+ if(!innermostContainer) return;
+
+ // move the item into the container if it's not there already
+ if(this.containers.length === 1) {
+ this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
+ this.containers[innermostIndex].containerCache.over = 1;
+ } else if(this.currentContainer != this.containers[innermostIndex]) {
+
+ //When entering a new container, we will find the item with the least distance and append our item near it
+ var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top'];
+ for (var j = this.items.length - 1; j >= 0; j--) {
+ if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue;
+ var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top'];
+ if(Math.abs(cur - base) < dist) {
+ dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
+ }
+ }
+
+ if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
+ return;
+
+ this.currentContainer = this.containers[innermostIndex];
+ itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
+ this._trigger("change", event, this._uiHash());
+ this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
+
+ //Update the placeholder
+ this.options.placeholder.update(this.currentContainer, this.placeholder);
+
+ this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
+ this.containers[innermostIndex].containerCache.over = 1;
+ }
+
+
+ },
+
+ _createHelper: function(event) {
+
+ var o = this.options;
+ var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
+
+ if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
+ $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
+
+ if(helper[0] == this.currentItem[0])
+ this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
+
+ if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
+ if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
+
+ return helper;
+
+ },
+
+ _adjustOffsetFromHelper: function(obj) {
+ if (typeof obj == 'string') {
+ obj = obj.split(' ');
+ }
+ if ($.isArray(obj)) {
+ obj = {left: +obj[0], top: +obj[1] || 0};
+ }
+ if ('left' in obj) {
+ this.offset.click.left = obj.left + this.margins.left;
+ }
+ if ('right' in obj) {
+ this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
+ }
+ if ('top' in obj) {
+ this.offset.click.top = obj.top + this.margins.top;
+ }
+ if ('bottom' in obj) {
+ this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
+ }
+ },
+
+ _getParentOffset: function() {
+
+
+ //Get the offsetParent and cache its position
+ this.offsetParent = this.helper.offsetParent();
+ var po = this.offsetParent.offset();
+
+ // This is a special case where we need to modify a offset calculated on start, since the following happened:
+ // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
+ // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
+ // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
+ if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
+ po.left += this.scrollParent.scrollLeft();
+ po.top += this.scrollParent.scrollTop();
+ }
+
+ if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
+ || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
+ po = { top: 0, left: 0 };
+
+ return {
+ top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
+ left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
+ };
+
+ },
+
+ _getRelativeOffset: function() {
+
+ if(this.cssPosition == "relative") {
+ var p = this.currentItem.position();
+ return {
+ top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
+ left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
+ };
+ } else {
+ return { top: 0, left: 0 };
+ }
+
+ },
+
+ _cacheMargins: function() {
+ this.margins = {
+ left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
+ top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
+ };
+ },
+
+ _cacheHelperProportions: function() {
+ this.helperProportions = {
+ width: this.helper.outerWidth(),
+ height: this.helper.outerHeight()
+ };
+ },
+
+ _setContainment: function() {
+
+ var o = this.options;
+ if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
+ if(o.containment == 'document' || o.containment == 'window') this.containment = [
+ 0 - this.offset.relative.left - this.offset.parent.left,
+ 0 - this.offset.relative.top - this.offset.parent.top,
+ $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
+ ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
+ ];
+
+ if(!(/^(document|window|parent)$/).test(o.containment)) {
+ var ce = $(o.containment)[0];
+ var co = $(o.containment).offset();
+ var over = ($(ce).css("overflow") != 'hidden');
+
+ this.containment = [
+ co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
+ co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
+ co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
+ co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
+ ];
+ }
+
+ },
+
+ _convertPositionTo: function(d, pos) {
+
+ if(!pos) pos = this.position;
+ var mod = d == "absolute" ? 1 : -1;
+ var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
+
+ return {
+ top: (
+ pos.top // The absolute mouse position
+ + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
+ + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
+ - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
+ ),
+ left: (
+ pos.left // The absolute mouse position
+ + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
+ + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
+ - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
+ )
+ };
+
+ },
+
+ _generatePosition: function(event) {
+
+ var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
+
+ // This is another very weird special case that only happens for relative elements:
+ // 1. If the css position is relative
+ // 2. and the scroll parent is the document or similar to the offset parent
+ // we have to refresh the relative offset during the scroll so there are no jumps
+ if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
+ this.offset.relative = this._getRelativeOffset();
+ }
+
+ var pageX = event.pageX;
+ var pageY = event.pageY;
+
+ /*
+ * - Position constraining -
+ * Constrain the position to a mix of grid, containment.
+ */
+
+ if(this.originalPosition) { //If we are not dragging yet, we won't check for options
+
+ if(this.containment) {
+ if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
+ if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
+ if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
+ if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
+ }
+
+ if(o.grid) {
+ var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
+ pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
+
+ var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
+ pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
+ }
+
+ }
+
+ return {
+ top: (
+ pageY // The absolute mouse position
+ - this.offset.click.top // Click offset (relative to the element)
+ - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
+ - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
+ + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
+ ),
+ left: (
+ pageX // The absolute mouse position
+ - this.offset.click.left // Click offset (relative to the element)
+ - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
+ - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
+ + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
+ )
+ };
+
+ },
+
+ _rearrange: function(event, i, a, hardRefresh) {
+
+ a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
+
+ //Various things done here to improve the performance:
+ // 1. we create a setTimeout, that calls refreshPositions
+ // 2. on the instance, we have a counter variable, that get's higher after every append
+ // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
+ // 4. this lets only the last addition to the timeout stack through
+ this.counter = this.counter ? ++this.counter : 1;
+ var self = this, counter = this.counter;
+
+ window.setTimeout(function() {
+ if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
+ },0);
+
+ },
+
+ _clear: function(event, noPropagation) {
+
+ this.reverting = false;
+ // We delay all events that have to be triggered to after the point where the placeholder has been removed and
+ // everything else normalized again
+ var delayedTriggers = [], self = this;
+
+ // We first have to update the dom position of the actual currentItem
+ // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
+ if(!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem);
+ this._noFinalSort = null;
+
+ if(this.helper[0] == this.currentItem[0]) {
+ for(var i in this._storedCSS) {
+ if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
+ }
+ this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
+ } else {
+ this.currentItem.show();
+ }
+
+ if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
+ if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
+ if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
+ if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
+ for (var i = this.containers.length - 1; i >= 0; i--){
+ if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
+ delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
+ delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
+ }
+ };
+ };
+
+ //Post events to containers
+ for (var i = this.containers.length - 1; i >= 0; i--){
+ if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
+ if(this.containers[i].containerCache.over) {
+ delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
+ this.containers[i].containerCache.over = 0;
+ }
+ }
+
+ //Do what was originally in plugins
+ if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
+ if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
+ if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
+
+ this.dragging = false;
+ if(this.cancelHelperRemoval) {
+ if(!noPropagation) {
+ this._trigger("beforeStop", event, this._uiHash());
+ for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
+ this._trigger("stop", event, this._uiHash());
+ }
+ return false;
+ }
+
+ if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
+
+ //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
+ this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
+
+ if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
+
+ if(!noPropagation) {
+ for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
+ this._trigger("stop", event, this._uiHash());
+ }
+
+ this.fromOutside = false;
+ return true;
+
+ },
+
+ _trigger: function() {
+ if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
+ this.cancel();
+ }
+ },
+
+ _uiHash: function(inst) {
+ var self = inst || this;
+ return {
+ helper: self.helper,
+ placeholder: self.placeholder || $([]),
+ position: self.position,
+ originalPosition: self.originalPosition,
+ offset: self.positionAbs,
+ item: self.currentItem,
+ sender: inst ? inst.element : null
+ };
+ }
+
+});
+
+$.extend($.ui.sortable, {
+ version: "1.8.18"
+});
+
+})(jQuery);
+/*
+ * jQuery UI Effects 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/
+ */
+;jQuery.effects || (function($, undefined) {
+
+$.effects = {};
+
+
+
+/******************************************************************************/
+/****************************** COLOR ANIMATIONS ******************************/
+/******************************************************************************/
+
+// override the animation for color styles
+$.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
+ 'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
+function(i, attr) {
+ $.fx.step[attr] = function(fx) {
+ if (!fx.colorInit) {
+ fx.start = getColor(fx.elem, attr);
+ fx.end = getRGB(fx.end);
+ fx.colorInit = true;
+ }
+
+ fx.elem.style[attr] = 'rgb(' +
+ Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
+ Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
+ Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
+ };
+});
+
+// Color Conversion functions from highlightFade
+// By Blair Mitchelmore
+// http://jquery.offput.ca/highlightFade/
+
+// Parse strings looking for color tuples [255,255,255]
+function getRGB(color) {
+ var result;
+
+ // Check if we're already dealing with an array of colors
+ if ( color && color.constructor == Array && color.length == 3 )
+ return color;
+
+ // Look for rgb(num,num,num)
+ if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
+ return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
+
+ // Look for rgb(num%,num%,num%)
+ if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
+ return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
+
+ // Look for #a0b1c2
+ if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
+ return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
+
+ // Look for #fff
+ if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
+ return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
+
+ // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
+ if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
+ return colors['transparent'];
+
+ // Otherwise, we're most likely dealing with a named color
+ return colors[$.trim(color).toLowerCase()];
+}
+
+function getColor(elem, attr) {
+ var color;
+
+ do {
+ color = $.curCSS(elem, attr);
+
+ // Keep going until we find an element that has color, or we hit the body
+ if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
+ break;
+
+ attr = "backgroundColor";
+ } while ( elem = elem.parentNode );
+
+ return getRGB(color);
+};
+
+// Some named colors to work with
+// From Interface by Stefan Petre
+// http://interface.eyecon.ro/
+
+var colors = {
+ aqua:[0,255,255],
+ azure:[240,255,255],
+ beige:[245,245,220],
+ black:[0,0,0],
+ blue:[0,0,255],
+ brown:[165,42,42],
+ cyan:[0,255,255],
+ darkblue:[0,0,139],
+ darkcyan:[0,139,139],
+ darkgrey:[169,169,169],
+ darkgreen:[0,100,0],
+ darkkhaki:[189,183,107],
+ darkmagenta:[139,0,139],
+ darkolivegreen:[85,107,47],
+ darkorange:[255,140,0],
+ darkorchid:[153,50,204],
+ darkred:[139,0,0],
+ darksalmon:[233,150,122],
+ darkviolet:[148,0,211],
+ fuchsia:[255,0,255],
+ gold:[255,215,0],
+ green:[0,128,0],
+ indigo:[75,0,130],
+ khaki:[240,230,140],
+ lightblue:[173,216,230],
+ lightcyan:[224,255,255],
+ lightgreen:[144,238,144],
+ lightgrey:[211,211,211],
+ lightpink:[255,182,193],
+ lightyellow:[255,255,224],
+ lime:[0,255,0],
+ magenta:[255,0,255],
+ maroon:[128,0,0],
+ navy:[0,0,128],
+ olive:[128,128,0],
+ orange:[255,165,0],
+ pink:[255,192,203],
+ purple:[128,0,128],
+ violet:[128,0,128],
+ red:[255,0,0],
+ silver:[192,192,192],
+ white:[255,255,255],
+ yellow:[255,255,0],
+ transparent: [255,255,255]
+};
+
+
+
+/******************************************************************************/
+/****************************** CLASS ANIMATIONS ******************************/
+/******************************************************************************/
+
+var classAnimationActions = ['add', 'remove', 'toggle'],
+ shorthandStyles = {
+ border: 1,
+ borderBottom: 1,
+ borderColor: 1,
+ borderLeft: 1,
+ borderRight: 1,
+ borderTop: 1,
+ borderWidth: 1,
+ margin: 1,
+ padding: 1
+ };
+
+function getElementStyles() {
+ var style = document.defaultView
+ ? document.defaultView.getComputedStyle(this, null)
+ : this.currentStyle,
+ newStyle = {},
+ key,
+ camelCase;
+
+ // webkit enumerates style porperties
+ if (style && style.length && style[0] && style[style[0]]) {
+ var len = style.length;
+ while (len--) {
+ key = style[len];
+ if (typeof style[key] == 'string') {
+ camelCase = key.replace(/\-(\w)/g, function(all, letter){
+ return letter.toUpperCase();
+ });
+ newStyle[camelCase] = style[key];
+ }
+ }
+ } else {
+ for (key in style) {
+ if (typeof style[key] === 'string') {
+ newStyle[key] = style[key];
+ }
+ }
+ }
+
+ return newStyle;
+}
+
+function filterStyles(styles) {
+ var name, value;
+ for (name in styles) {
+ value = styles[name];
+ if (
+ // ignore null and undefined values
+ value == null ||
+ // ignore functions (when does this occur?)
+ $.isFunction(value) ||
+ // shorthand styles that need to be expanded
+ name in shorthandStyles ||
+ // ignore scrollbars (break in IE)
+ (/scrollbar/).test(name) ||
+
+ // only colors or values that can be converted to numbers
+ (!(/color/i).test(name) && isNaN(parseFloat(value)))
+ ) {
+ delete styles[name];
+ }
+ }
+
+ return styles;
+}
+
+function styleDifference(oldStyle, newStyle) {
+ var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
+ name;
+
+ for (name in newStyle) {
+ if (oldStyle[name] != newStyle[name]) {
+ diff[name] = newStyle[name];
+ }
+ }
+
+ return diff;
+}
+
+$.effects.animateClass = function(value, duration, easing, callback) {
+ if ($.isFunction(easing)) {
+ callback = easing;
+ easing = null;
+ }
+
+ return this.queue(function() {
+ var that = $(this),
+ originalStyleAttr = that.attr('style') || ' ',
+ originalStyle = filterStyles(getElementStyles.call(this)),
+ newStyle,
+ className = that.attr('class');
+
+ $.each(classAnimationActions, function(i, action) {
+ if (value[action]) {
+ that[action + 'Class'](value[action]);
+ }
+ });
+ newStyle = filterStyles(getElementStyles.call(this));
+ that.attr('class', className);
+
+ that.animate(styleDifference(originalStyle, newStyle), {
+ queue: false,
+ duration: duration,
+ easing: easing,
+ complete: function() {
+ $.each(classAnimationActions, function(i, action) {
+ if (value[action]) { that[action + 'Class'](value[action]); }
+ });
+ // work around bug in IE by clearing the cssText before setting it
+ if (typeof that.attr('style') == 'object') {
+ that.attr('style').cssText = '';
+ that.attr('style').cssText = originalStyleAttr;
+ } else {
+ that.attr('style', originalStyleAttr);
+ }
+ if (callback) { callback.apply(this, arguments); }
+ $.dequeue( this );
+ }
+ });
+ });
+};
+
+$.fn.extend({
+ _addClass: $.fn.addClass,
+ addClass: function(classNames, speed, easing, callback) {
+ return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
+ },
+
+ _removeClass: $.fn.removeClass,
+ removeClass: function(classNames,speed,easing,callback) {
+ return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
+ },
+
+ _toggleClass: $.fn.toggleClass,
+ toggleClass: function(classNames, force, speed, easing, callback) {
+ if ( typeof force == "boolean" || force === undefined ) {
+ if ( !speed ) {
+ // without speed parameter;
+ return this._toggleClass(classNames, force);
+ } else {
+ return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
+ }
+ } else {
+ // without switch parameter;
+ return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
+ }
+ },
+
+ switchClass: function(remove,add,speed,easing,callback) {
+ return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
+ }
+});
+
+
+
+/******************************************************************************/
+/*********************************** EFFECTS **********************************/
+/******************************************************************************/
+
+$.extend($.effects, {
+ version: "1.8.18",
+
+ // Saves a set of properties in a data storage
+ save: function(element, set) {
+ for(var i=0; i < set.length; i++) {
+ if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
+ }
+ },
+
+ // Restores a set of previously saved properties from a data storage
+ restore: function(element, set) {
+ for(var i=0; i < set.length; i++) {
+ if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
+ }
+ },
+
+ setMode: function(el, mode) {
+ if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
+ return mode;
+ },
+
+ getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
+ // this should be a little more flexible in the future to handle a string & hash
+ var y, x;
+ switch (origin[0]) {
+ case 'top': y = 0; break;
+ case 'middle': y = 0.5; break;
+ case 'bottom': y = 1; break;
+ default: y = origin[0] / original.height;
+ };
+ switch (origin[1]) {
+ case 'left': x = 0; break;
+ case 'center': x = 0.5; break;
+ case 'right': x = 1; break;
+ default: x = origin[1] / original.width;
+ };
+ return {x: x, y: y};
+ },
+
+ // Wraps the element around a wrapper that copies position properties
+ createWrapper: function(element) {
+
+ // if the element is already wrapped, return it
+ if (element.parent().is('.ui-effects-wrapper')) {
+ return element.parent();
+ }
+
+ // wrap the element
+ var props = {
+ width: element.outerWidth(true),
+ height: element.outerHeight(true),
+ 'float': element.css('float')
+ },
+ wrapper = $('<div></div>')
+ .addClass('ui-effects-wrapper')
+ .css({
+ fontSize: '100%',
+ background: 'transparent',
+ border: 'none',
+ margin: 0,
+ padding: 0
+ }),
+ active = document.activeElement;
+
+ element.wrap(wrapper);
+
+ // Fixes #7595 - Elements lose focus when wrapped.
+ if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
+ $( active ).focus();
+ }
+
+ wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
+
+ // transfer positioning properties to the wrapper
+ if (element.css('position') == 'static') {
+ wrapper.css({ position: 'relative' });
+ element.css({ position: 'relative' });
+ } else {
+ $.extend(props, {
+ position: element.css('position'),
+ zIndex: element.css('z-index')
+ });
+ $.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
+ props[pos] = element.css(pos);
+ if (isNaN(parseInt(props[pos], 10))) {
+ props[pos] = 'auto';
+ }
+ });
+ element.css({position: 'relative', top: 0, left: 0, right: 'auto', bottom: 'auto' });
+ }
+
+ return wrapper.css(props).show();
+ },
+
+ removeWrapper: function(element) {
+ var parent,
+ active = document.activeElement;
+
+ if (element.parent().is('.ui-effects-wrapper')) {
+ parent = element.parent().replaceWith(element);
+ // Fixes #7595 - Elements lose focus when wrapped.
+ if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
+ $( active ).focus();
+ }
+ return parent;
+ }
+
+ return element;
+ },
+
+ setTransition: function(element, list, factor, value) {
+ value = value || {};
+ $.each(list, function(i, x){
+ unit = element.cssUnit(x);
+ if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
+ });
+ return value;
+ }
+});
+
+
+function _normalizeArguments(effect, options, speed, callback) {
+ // shift params for method overloading
+ if (typeof effect == 'object') {
+ callback = options;
+ speed = null;
+ options = effect;
+ effect = options.effect;
+ }
+ if ($.isFunction(options)) {
+ callback = options;
+ speed = null;
+ options = {};
+ }
+ if (typeof options == 'number' || $.fx.speeds[options]) {
+ callback = speed;
+ speed = options;
+ options = {};
+ }
+ if ($.isFunction(speed)) {
+ callback = speed;
+ speed = null;
+ }
+
+ options = options || {};
+
+ speed = speed || options.duration;
+ speed = $.fx.off ? 0 : typeof speed == 'number'
+ ? speed : speed in $.fx.speeds ? $.fx.speeds[speed] : $.fx.speeds._default;
+
+ callback = callback || options.complete;
+
+ return [effect, options, speed, callback];
+}
+
+function standardSpeed( speed ) {
+ // valid standard speeds
+ if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
+ return true;
+ }
+
+ // invalid strings - treat as "normal" speed
+ if ( typeof speed === "string" && !$.effects[ speed ] ) {
+ return true;
+ }
+
+ return false;
+}
+
+$.fn.extend({
+ effect: function(effect, options, speed, callback) {
+ var args = _normalizeArguments.apply(this, arguments),
+ // TODO: make effects take actual parameters instead of a hash
+ args2 = {
+ options: args[1],
+ duration: args[2],
+ callback: args[3]
+ },
+ mode = args2.options.mode,
+ effectMethod = $.effects[effect];
+
+ if ( $.fx.off || !effectMethod ) {
+ // delegate to the original method (e.g., .show()) if possible
+ if ( mode ) {
+ return this[ mode ]( args2.duration, args2.callback );
+ } else {
+ return this.each(function() {
+ if ( args2.callback ) {
+ args2.callback.call( this );
+ }
+ });
+ }
+ }
+
+ return effectMethod.call(this, args2);
+ },
+
+ _show: $.fn.show,
+ show: function(speed) {
+ if ( standardSpeed( speed ) ) {
+ return this._show.apply(this, arguments);
+ } else {
+ var args = _normalizeArguments.apply(this, arguments);
+ args[1].mode = 'show';
+ return this.effect.apply(this, args);
+ }
+ },
+
+ _hide: $.fn.hide,
+ hide: function(speed) {
+ if ( standardSpeed( speed ) ) {
+ return this._hide.apply(this, arguments);
+ } else {
+ var args = _normalizeArguments.apply(this, arguments);
+ args[1].mode = 'hide';
+ return this.effect.apply(this, args);
+ }
+ },
+
+ // jQuery core overloads toggle and creates _toggle
+ __toggle: $.fn.toggle,
+ toggle: function(speed) {
+ if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
+ return this.__toggle.apply(this, arguments);
+ } else {
+ var args = _normalizeArguments.apply(this, arguments);
+ args[1].mode = 'toggle';
+ return this.effect.apply(this, args);
+ }
+ },
+
+ // helper functions
+ cssUnit: function(key) {
+ var style = this.css(key), val = [];
+ $.each( ['em','px','%','pt'], function(i, unit){
+ if(style.indexOf(unit) > 0)
+ val = [parseFloat(style), unit];
+ });
+ return val;
+ }
+});
+
+
+
+/******************************************************************************/
+/*********************************** EASING ***********************************/
+/******************************************************************************/
+
+/*
+ * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
+ *
+ * Uses the built in easing capabilities added In jQuery 1.1
+ * to offer multiple easing options
+ *
+ * TERMS OF USE - jQuery Easing
+ *
+ * Open source under the BSD License.
+ *
+ * Copyright 2008 George McGinley Smith
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * Neither the name of the author nor the names of contributors may be used to endorse
+ * or promote products derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+*/
+
+// t: current time, b: begInnIng value, c: change In value, d: duration
+$.easing.jswing = $.easing.swing;
+
+$.extend($.easing,
+{
+ def: 'easeOutQuad',
+ swing: function (x, t, b, c, d) {
+ //alert($.easing.default);
+ return $.easing[$.easing.def](x, t, b, c, d);
+ },
+ easeInQuad: function (x, t, b, c, d) {
+ return c*(t/=d)*t + b;
+ },
+ easeOutQuad: function (x, t, b, c, d) {
+ return -c *(t/=d)*(t-2) + b;
+ },
+ easeInOutQuad: function (x, t, b, c, d) {
+ if ((t/=d/2) < 1) return c/2*t*t + b;
+ return -c/2 * ((--t)*(t-2) - 1) + b;
+ },
+ easeInCubic: function (x, t, b, c, d) {
+ return c*(t/=d)*t*t + b;
+ },
+ easeOutCubic: function (x, t, b, c, d) {
+ return c*((t=t/d-1)*t*t + 1) + b;
+ },
+ easeInOutCubic: function (x, t, b, c, d) {
+ if ((t/=d/2) < 1) return c/2*t*t*t + b;
+ return c/2*((t-=2)*t*t + 2) + b;
+ },
+ easeInQuart: function (x, t, b, c, d) {
+ return c*(t/=d)*t*t*t + b;
+ },
+ easeOutQuart: function (x, t, b, c, d) {
+ return -c * ((t=t/d-1)*t*t*t - 1) + b;
+ },
+ easeInOutQuart: function (x, t, b, c, d) {
+ if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
+ return -c/2 * ((t-=2)*t*t*t - 2) + b;
+ },
+ easeInQuint: function (x, t, b, c, d) {
+ return c*(t/=d)*t*t*t*t + b;
+ },
+ easeOutQuint: function (x, t, b, c, d) {
+ return c*((t=t/d-1)*t*t*t*t + 1) + b;
+ },
+ easeInOutQuint: function (x, t, b, c, d) {
+ if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
+ return c/2*((t-=2)*t*t*t*t + 2) + b;
+ },
+ easeInSine: function (x, t, b, c, d) {
+ return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
+ },
+ easeOutSine: function (x, t, b, c, d) {
+ return c * Math.sin(t/d * (Math.PI/2)) + b;
+ },
+ easeInOutSine: function (x, t, b, c, d) {
+ return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
+ },
+ easeInExpo: function (x, t, b, c, d) {
+ return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
+ },
+ easeOutExpo: function (x, t, b, c, d) {
+ return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
+ },
+ easeInOutExpo: function (x, t, b, c, d) {
+ if (t==0) return b;
+ if (t==d) return b+c;
+ if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
+ return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
+ },
+ easeInCirc: function (x, t, b, c, d) {
+ return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
+ },
+ easeOutCirc: function (x, t, b, c, d) {
+ return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
+ },
+ easeInOutCirc: function (x, t, b, c, d) {
+ if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
+ return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
+ },
+ easeInElastic: function (x, t, b, c, d) {
+ var s=1.70158;var p=0;var a=c;
+ if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
+ if (a < Math.abs(c)) { a=c; var s=p/4; }
+ else var s = p/(2*Math.PI) * Math.asin (c/a);
+ return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
+ },
+ easeOutElastic: function (x, t, b, c, d) {
+ var s=1.70158;var p=0;var a=c;
+ if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
+ if (a < Math.abs(c)) { a=c; var s=p/4; }
+ else var s = p/(2*Math.PI) * Math.asin (c/a);
+ return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
+ },
+ easeInOutElastic: function (x, t, b, c, d) {
+ var s=1.70158;var p=0;var a=c;
+ if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5);
+ if (a < Math.abs(c)) { a=c; var s=p/4; }
+ else var s = p/(2*Math.PI) * Math.asin (c/a);
+ if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
+ return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
+ },
+ easeInBack: function (x, t, b, c, d, s) {
+ if (s == undefined) s = 1.70158;
+ return c*(t/=d)*t*((s+1)*t - s) + b;
+ },
+ easeOutBack: function (x, t, b, c, d, s) {
+ if (s == undefined) s = 1.70158;
+ return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
+ },
+ easeInOutBack: function (x, t, b, c, d, s) {
+ if (s == undefined) s = 1.70158;
+ if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
+ return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
+ },
+ easeInBounce: function (x, t, b, c, d) {
+ return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
+ },
+ easeOutBounce: function (x, t, b, c, d) {
+ if ((t/=d) < (1/2.75)) {
+ return c*(7.5625*t*t) + b;
+ } else if (t < (2/2.75)) {
+ return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
+ } else if (t < (2.5/2.75)) {
+ return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
+ } else {
+ return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
+ }
+ },
+ easeInOutBounce: function (x, t, b, c, d) {
+ if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
+ return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
+ }
+});
+
+/*
+ *
+ * TERMS OF USE - EASING EQUATIONS
+ *
+ * Open source under the BSD License.
+ *
+ * Copyright 2001 Robert Penner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * Neither the name of the author nor the names of contributors may be used to endorse
+ * or promote products derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+})(jQuery);
+/*
+ * jQuery UI Effects Blind 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Blind
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.blind = function(o) {
+
+ return this.queue(function() {
+
+ // Create element
+ var el = $(this), props = ['position','top','bottom','left','right'];
+
+ // Set options
+ var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
+ var direction = o.options.direction || 'vertical'; // Default direction
+
+ // Adjust
+ $.effects.save(el, props); el.show(); // Save & Show
+ var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
+ var ref = (direction == 'vertical') ? 'height' : 'width';
+ var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
+ if(mode == 'show') wrapper.css(ref, 0); // Shift
+
+ // Animation
+ var animation = {};
+ animation[ref] = mode == 'show' ? distance : 0;
+
+ // Animate
+ wrapper.animate(animation, o.duration, o.options.easing, function() {
+ if(mode == 'hide') el.hide(); // Hide
+ $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
+ if(o.callback) o.callback.apply(el[0], arguments); // Callback
+ el.dequeue();
+ });
+
+ });
+
+};
+
+})(jQuery);
+/*
+ * jQuery UI Effects Bounce 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Bounce
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.bounce = function(o) {
+
+ return this.queue(function() {
+
+ // Create element
+ var el = $(this), props = ['position','top','bottom','left','right'];
+
+ // Set options
+ var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
+ var direction = o.options.direction || 'up'; // Default direction
+ var distance = o.options.distance || 20; // Default distance
+ var times = o.options.times || 5; // Default # of times
+ var speed = o.duration || 250; // Default speed per bounce
+ if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
+
+ // Adjust
+ $.effects.save(el, props); el.show(); // Save & Show
+ $.effects.createWrapper(el); // Create Wrapper
+ var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
+ var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
+ var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);
+ if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
+ if (mode == 'hide') distance = distance / (times * 2);
+ if (mode != 'hide') times--;
+
+ // Animate
+ if (mode == 'show') { // Show Bounce
+ var animation = {opacity: 1};
+ animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
+ el.animate(animation, speed / 2, o.options.easing);
+ distance = distance / 2;
+ times--;
+ };
+ for (var i = 0; i < times; i++) { // Bounces
+ var animation1 = {}, animation2 = {};
+ animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
+ animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
+ el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
+ distance = (mode == 'hide') ? distance * 2 : distance / 2;
+ };
+ if (mode == 'hide') { // Last Bounce
+ var animation = {opacity: 0};
+ animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
+ el.animate(animation, speed / 2, o.options.easing, function(){
+ el.hide(); // Hide
+ $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
+ if(o.callback) o.callback.apply(this, arguments); // Callback
+ });
+ } else {
+ var animation1 = {}, animation2 = {};
+ animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
+ animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
+ el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
+ $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
+ if(o.callback) o.callback.apply(this, arguments); // Callback
+ });
+ };
+ el.queue('fx', function() { el.dequeue(); });
+ el.dequeue();
+ });
+
+};
+
+})(jQuery);
+/*
+ * jQuery UI Effects Clip 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Clip
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.clip = function(o) {
+
+ return this.queue(function() {
+
+ // Create element
+ var el = $(this), props = ['position','top','bottom','left','right','height','width'];
+
+ // Set options
+ var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
+ var direction = o.options.direction || 'vertical'; // Default direction
+
+ // Adjust
+ $.effects.save(el, props); el.show(); // Save & Show
+ var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
+ var animate = el[0].tagName == 'IMG' ? wrapper : el;
+ var ref = {
+ size: (direction == 'vertical') ? 'height' : 'width',
+ position: (direction == 'vertical') ? 'top' : 'left'
+ };
+ var distance = (direction == 'vertical') ? animate.height() : animate.width();
+ if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
+
+ // Animation
+ var animation = {};
+ animation[ref.size] = mode == 'show' ? distance : 0;
+ animation[ref.position] = mode == 'show' ? 0 : distance / 2;
+
+ // Animate
+ animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
+ if(mode == 'hide') el.hide(); // Hide
+ $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
+ if(o.callback) o.callback.apply(el[0], arguments); // Callback
+ el.dequeue();
+ }});
+
+ });
+
+};
+
+})(jQuery);
+/*
+ * jQuery UI Effects Drop 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Drop
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.drop = function(o) {
+
+ return this.queue(function() {
+
+ // Create element
+ var el = $(this), props = ['position','top','bottom','left','right','opacity'];
+
+ // Set options
+ var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
+ var direction = o.options.direction || 'left'; // Default Direction
+
+ // Adjust
+ $.effects.save(el, props); el.show(); // Save & Show
+ $.effects.createWrapper(el); // Create Wrapper
+ var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
+ var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
+ var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);
+ if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
+
+ // Animation
+ var animation = {opacity: mode == 'show' ? 1 : 0};
+ animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
+
+ // Animate
+ el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
+ if(mode == 'hide') el.hide(); // Hide
+ $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
+ if(o.callback) o.callback.apply(this, arguments); // Callback
+ el.dequeue();
+ }});
+
+ });
+
+};
+
+})(jQuery);
+/*
+ * jQuery UI Effects Explode 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Explode
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.explode = function(o) {
+
+ return this.queue(function() {
+
+ var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
+ var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
+
+ o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
+ var el = $(this).show().css('visibility', 'hidden');
+ var offset = el.offset();
+
+ //Substract the margins - not fixing the problem yet.
+ offset.top -= parseInt(el.css("marginTop"),10) || 0;
+ offset.left -= parseInt(el.css("marginLeft"),10) || 0;
+
+ var width = el.outerWidth(true);
+ var height = el.outerHeight(true);
+
+ for(var i=0;i<rows;i++) { // =
+ for(var j=0;j<cells;j++) { // ||
+ el
+ .clone()
+ .appendTo('body')
+ .wrap('<div></div>')
+ .css({
+ position: 'absolute',
+ visibility: 'visible',
+ left: -j*(width/cells),
+ top: -i*(height/rows)
+ })
+ .parent()
+ .addClass('ui-effects-explode')
+ .css({
+ position: 'absolute',
+ overflow: 'hidden',
+ width: width/cells,
+ height: height/rows,
+ left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
+ top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
+ opacity: o.options.mode == 'show' ? 0 : 1
+ }).animate({
+ left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
+ top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
+ opacity: o.options.mode == 'show' ? 1 : 0
+ }, o.duration || 500);
+ }
+ }
+
+ // Set a timeout, to call the callback approx. when the other animations have finished
+ setTimeout(function() {
+
+ o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
+ if(o.callback) o.callback.apply(el[0]); // Callback
+ el.dequeue();
+
+ $('div.ui-effects-explode').remove();
+
+ }, o.duration || 500);
+
+
+ });
+
+};
+
+})(jQuery);
+/*
+ * jQuery UI Effects Fade 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Fade
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.fade = function(o) {
+ return this.queue(function() {
+ var elem = $(this),
+ mode = $.effects.setMode(elem, o.options.mode || 'hide');
+
+ elem.animate({ opacity: mode }, {
+ queue: false,
+ duration: o.duration,
+ easing: o.options.easing,
+ complete: function() {
+ (o.callback && o.callback.apply(this, arguments));
+ elem.dequeue();
+ }
+ });
+ });
+};
+
+})(jQuery);
+/*
+ * jQuery UI Effects Fold 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Fold
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.fold = function(o) {
+
+ return this.queue(function() {
+
+ // Create element
+ var el = $(this), props = ['position','top','bottom','left','right'];
+
+ // Set options
+ var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
+ var size = o.options.size || 15; // Default fold size
+ var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
+ var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
+
+ // Adjust
+ $.effects.save(el, props); el.show(); // Save & Show
+ var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
+ var widthFirst = ((mode == 'show') != horizFirst);
+ var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
+ var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
+ var percent = /([0-9]+)%/.exec(size);
+ if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
+ if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
+
+ // Animation
+ var animation1 = {}, animation2 = {};
+ animation1[ref[0]] = mode == 'show' ? distance[0] : size;
+ animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
+
+ // Animate
+ wrapper.animate(animation1, duration, o.options.easing)
+ .animate(animation2, duration, o.options.easing, function() {
+ if(mode == 'hide') el.hide(); // Hide
+ $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
+ if(o.callback) o.callback.apply(el[0], arguments); // Callback
+ el.dequeue();
+ });
+
+ });
+
+};
+
+})(jQuery);
+/*
+ * jQuery UI Effects Highlight 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Highlight
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.highlight = function(o) {
+ return this.queue(function() {
+ var elem = $(this),
+ props = ['backgroundImage', 'backgroundColor', 'opacity'],
+ mode = $.effects.setMode(elem, o.options.mode || 'show'),
+ animation = {
+ backgroundColor: elem.css('backgroundColor')
+ };
+
+ if (mode == 'hide') {
+ animation.opacity = 0;
+ }
+
+ $.effects.save(elem, props);
+ elem
+ .show()
+ .css({
+ backgroundImage: 'none',
+ backgroundColor: o.options.color || '#ffff99'
+ })
+ .animate(animation, {
+ queue: false,
+ duration: o.duration,
+ easing: o.options.easing,
+ complete: function() {
+ (mode == 'hide' && elem.hide());
+ $.effects.restore(elem, props);
+ (mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
+ (o.callback && o.callback.apply(this, arguments));
+ elem.dequeue();
+ }
+ });
+ });
+};
+
+})(jQuery);
+/*
+ * jQuery UI Effects Pulsate 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Pulsate
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.pulsate = function(o) {
+ return this.queue(function() {
+ var elem = $(this),
+ mode = $.effects.setMode(elem, o.options.mode || 'show');
+ times = ((o.options.times || 5) * 2) - 1;
+ duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
+ isVisible = elem.is(':visible'),
+ animateTo = 0;
+
+ if (!isVisible) {
+ elem.css('opacity', 0).show();
+ animateTo = 1;
+ }
+
+ if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
+ times--;
+ }
+
+ for (var i = 0; i < times; i++) {
+ elem.animate({ opacity: animateTo }, duration, o.options.easing);
+ animateTo = (animateTo + 1) % 2;
+ }
+
+ elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
+ if (animateTo == 0) {
+ elem.hide();
+ }
+ (o.callback && o.callback.apply(this, arguments));
+ });
+
+ elem
+ .queue('fx', function() { elem.dequeue(); })
+ .dequeue();
+ });
+};
+
+})(jQuery);
+/*
+ * jQuery UI Effects Scale 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Scale
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.puff = function(o) {
+ return this.queue(function() {
+ var elem = $(this),
+ mode = $.effects.setMode(elem, o.options.mode || 'hide'),
+ percent = parseInt(o.options.percent, 10) || 150,
+ factor = percent / 100,
+ original = { height: elem.height(), width: elem.width() };
+
+ $.extend(o.options, {
+ fade: true,
+ mode: mode,
+ percent: mode == 'hide' ? percent : 100,
+ from: mode == 'hide'
+ ? original
+ : {
+ height: original.height * factor,
+ width: original.width * factor
+ }
+ });
+
+ elem.effect('scale', o.options, o.duration, o.callback);
+ elem.dequeue();
+ });
+};
+
+$.effects.scale = function(o) {
+
+ return this.queue(function() {
+
+ // Create element
+ var el = $(this);
+
+ // Set options
+ var options = $.extend(true, {}, o.options);
+ var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
+ var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
+ var direction = o.options.direction || 'both'; // Set default axis
+ var origin = o.options.origin; // The origin of the scaling
+ if (mode != 'effect') { // Set default origin and restore for show/hide
+ options.origin = origin || ['middle','center'];
+ options.restore = true;
+ }
+ var original = {height: el.height(), width: el.width()}; // Save original
+ el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
+
+ // Adjust
+ var factor = { // Set scaling factor
+ y: direction != 'horizontal' ? (percent / 100) : 1,
+ x: direction != 'vertical' ? (percent / 100) : 1
+ };
+ el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
+
+ if (o.options.fade) { // Fade option to support puff
+ if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
+ if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
+ };
+
+ // Animation
+ options.from = el.from; options.to = el.to; options.mode = mode;
+
+ // Animate
+ el.effect('size', options, o.duration, o.callback);
+ el.dequeue();
+ });
+
+};
+
+$.effects.size = function(o) {
+
+ return this.queue(function() {
+
+ // Create element
+ var el = $(this), props = ['position','top','bottom','left','right','width','height','overflow','opacity'];
+ var props1 = ['position','top','bottom','left','right','overflow','opacity']; // Always restore
+ var props2 = ['width','height','overflow']; // Copy for children
+ var cProps = ['fontSize'];
+ var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
+ var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
+
+ // Set options
+ var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
+ var restore = o.options.restore || false; // Default restore
+ var scale = o.options.scale || 'both'; // Default scale mode
+ var origin = o.options.origin; // The origin of the sizing
+ var original = {height: el.height(), width: el.width()}; // Save original
+ el.from = o.options.from || original; // Default from state
+ el.to = o.options.to || original; // Default to state
+ // Adjust
+ if (origin) { // Calculate baseline shifts
+ var baseline = $.effects.getBaseline(origin, original);
+ el.from.top = (original.height - el.from.height) * baseline.y;
+ el.from.left = (original.width - el.from.width) * baseline.x;
+ el.to.top = (original.height - el.to.height) * baseline.y;
+ el.to.left = (original.width - el.to.width) * baseline.x;
+ };
+ var factor = { // Set scaling factor
+ from: {y: el.from.height / original.height, x: el.from.width / original.width},
+ to: {y: el.to.height / original.height, x: el.to.width / original.width}
+ };
+ if (scale == 'box' || scale == 'both') { // Scale the css box
+ if (factor.from.y != factor.to.y) { // Vertical props scaling
+ props = props.concat(vProps);
+ el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
+ el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
+ };
+ if (factor.from.x != factor.to.x) { // Horizontal props scaling
+ props = props.concat(hProps);
+ el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
+ el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
+ };
+ };
+ if (scale == 'content' || scale == 'both') { // Scale the content
+ if (factor.from.y != factor.to.y) { // Vertical props scaling
+ props = props.concat(cProps);
+ el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
+ el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
+ };
+ };
+ $.effects.save(el, restore ? props : props1); el.show(); // Save & Show
+ $.effects.createWrapper(el); // Create Wrapper
+ el.css('overflow','hidden').css(el.from); // Shift
+
+ // Animate
+ if (scale == 'content' || scale == 'both') { // Scale the children
+ vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
+ hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
+ props2 = props.concat(vProps).concat(hProps); // Concat
+ el.find("*[width]").each(function(){
+ child = $(this);
+ if (restore) $.effects.save(child, props2);
+ var c_original = {height: child.height(), width: child.width()}; // Save original
+ child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
+ child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
+ if (factor.from.y != factor.to.y) { // Vertical props scaling
+ child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
+ child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
+ };
+ if (factor.from.x != factor.to.x) { // Horizontal props scaling
+ child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
+ child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
+ };
+ child.css(child.from); // Shift children
+ child.animate(child.to, o.duration, o.options.easing, function(){
+ if (restore) $.effects.restore(child, props2); // Restore children
+ }); // Animate children
+ });
+ };
+
+ // Animate
+ el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
+ if (el.to.opacity === 0) {
+ el.css('opacity', el.from.opacity);
+ }
+ if(mode == 'hide') el.hide(); // Hide
+ $.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
+ if(o.callback) o.callback.apply(this, arguments); // Callback
+ el.dequeue();
+ }});
+
+ });
+
+};
+
+})(jQuery);
+/*
+ * jQuery UI Effects Shake 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Shake
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.shake = function(o) {
+
+ return this.queue(function() {
+
+ // Create element
+ var el = $(this), props = ['position','top','bottom','left','right'];
+
+ // Set options
+ var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
+ var direction = o.options.direction || 'left'; // Default direction
+ var distance = o.options.distance || 20; // Default distance
+ var times = o.options.times || 3; // Default # of times
+ var speed = o.duration || o.options.duration || 140; // Default speed per shake
+
+ // Adjust
+ $.effects.save(el, props); el.show(); // Save & Show
+ $.effects.createWrapper(el); // Create Wrapper
+ var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
+ var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
+
+ // Animation
+ var animation = {}, animation1 = {}, animation2 = {};
+ animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
+ animation1[ref] = (motion == 'pos' ? '+=' : '-=') + distance * 2;
+ animation2[ref] = (motion == 'pos' ? '-=' : '+=') + distance * 2;
+
+ // Animate
+ el.animate(animation, speed, o.options.easing);
+ for (var i = 1; i < times; i++) { // Shakes
+ el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
+ };
+ el.animate(animation1, speed, o.options.easing).
+ animate(animation, speed / 2, o.options.easing, function(){ // Last shake
+ $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
+ if(o.callback) o.callback.apply(this, arguments); // Callback
+ });
+ el.queue('fx', function() { el.dequeue(); });
+ el.dequeue();
+ });
+
+};
+
+})(jQuery);
+/*
+ * jQuery UI Effects Slide 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Slide
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.slide = function(o) {
+
+ return this.queue(function() {
+
+ // Create element
+ var el = $(this), props = ['position','top','bottom','left','right'];
+
+ // Set options
+ var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
+ var direction = o.options.direction || 'left'; // Default Direction
+
+ // Adjust
+ $.effects.save(el, props); el.show(); // Save & Show
+ $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
+ var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
+ var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
+ var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));
+ if (mode == 'show') el.css(ref, motion == 'pos' ? (isNaN(distance) ? "-" + distance : -distance) : distance); // Shift
+
+ // Animation
+ var animation = {};
+ animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
+
+ // Animate
+ el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
+ if(mode == 'hide') el.hide(); // Hide
+ $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
+ if(o.callback) o.callback.apply(this, arguments); // Callback
+ el.dequeue();
+ }});
+
+ });
+
+};
+
+})(jQuery);
+/*
+ * jQuery UI Effects Transfer 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Transfer
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.transfer = function(o) {
+ return this.queue(function() {
+ var elem = $(this),
+ target = $(o.options.to),
+ endPosition = target.offset(),
+ animation = {
+ top: endPosition.top,
+ left: endPosition.left,
+ height: target.innerHeight(),
+ width: target.innerWidth()
+ },
+ startPosition = elem.offset(),
+ transfer = $('<div class="ui-effects-transfer"></div>')
+ .appendTo(document.body)
+ .addClass(o.options.className)
+ .css({
+ top: startPosition.top,
+ left: startPosition.left,
+ height: elem.innerHeight(),
+ width: elem.innerWidth(),
+ position: 'absolute'
+ })
+ .animate(animation, o.duration, o.options.easing, function() {
+ transfer.remove();
+ (o.callback && o.callback.apply(elem[0], arguments));
+ elem.dequeue();
+ });
+ });
+};
+
+})(jQuery);
+/*
+ * jQuery UI Accordion 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Accordion
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+$.widget( "ui.accordion", {
+ options: {
+ active: 0,
+ animated: "slide",
+ autoHeight: true,
+ clearStyle: false,
+ collapsible: false,
+ event: "click",
+ fillSpace: false,
+ header: "> li > :first-child,> :not(li):even",
+ icons: {
+ header: "ui-icon-triangle-1-e",
+ headerSelected: "ui-icon-triangle-1-s"
+ },
+ navigation: false,
+ navigationFilter: function() {
+ return this.href.toLowerCase() === location.href.toLowerCase();
+ }
+ },
+
+ _create: function() {
+ var self = this,
+ options = self.options;
+
+ self.running = 0;
+
+ self.element
+ .addClass( "ui-accordion ui-widget ui-helper-reset" )
+ // in lack of child-selectors in CSS
+ // we need to mark top-LIs in a UL-accordion for some IE-fix
+ .children( "li" )
+ .addClass( "ui-accordion-li-fix" );
+
+ self.headers = self.element.find( options.header )
+ .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
+ .bind( "mouseenter.accordion", function() {
+ if ( options.disabled ) {
+ return;
+ }
+ $( this ).addClass( "ui-state-hover" );
+ })
+ .bind( "mouseleave.accordion", function() {
+ if ( options.disabled ) {
+ return;
+ }
+ $( this ).removeClass( "ui-state-hover" );
+ })
+ .bind( "focus.accordion", function() {
+ if ( options.disabled ) {
+ return;
+ }
+ $( this ).addClass( "ui-state-focus" );
+ })
+ .bind( "blur.accordion", function() {
+ if ( options.disabled ) {
+ return;
+ }
+ $( this ).removeClass( "ui-state-focus" );
+ });
+
+ self.headers.next()
+ .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
+
+ if ( options.navigation ) {
+ var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
+ if ( current.length ) {
+ var header = current.closest( ".ui-accordion-header" );
+ if ( header.length ) {
+ // anchor within header
+ self.active = header;
+ } else {
+ // anchor within content
+ self.active = current.closest( ".ui-accordion-content" ).prev();
+ }
+ }
+ }
+
+ self.active = self._findActive( self.active || options.active )
+ .addClass( "ui-state-default ui-state-active" )
+ .toggleClass( "ui-corner-all" )
+ .toggleClass( "ui-corner-top" );
+ self.active.next().addClass( "ui-accordion-content-active" );
+
+ self._createIcons();
+ self.resize();
+
+ // ARIA
+ self.element.attr( "role", "tablist" );
+
+ self.headers
+ .attr( "role", "tab" )
+ .bind( "keydown.accordion", function( event ) {
+ return self._keydown( event );
+ })
+ .next()
+ .attr( "role", "tabpanel" );
+
+ self.headers
+ .not( self.active || "" )
+ .attr({
+ "aria-expanded": "false",
+ "aria-selected": "false",
+ tabIndex: -1
+ })
+ .next()
+ .hide();
+
+ // make sure at least one header is in the tab order
+ if ( !self.active.length ) {
+ self.headers.eq( 0 ).attr( "tabIndex", 0 );
+ } else {
+ self.active
+ .attr({
+ "aria-expanded": "true",
+ "aria-selected": "true",
+ tabIndex: 0
+ });
+ }
+
+ // only need links in tab order for Safari
+ if ( !$.browser.safari ) {
+ self.headers.find( "a" ).attr( "tabIndex", -1 );
+ }
+
+ if ( options.event ) {
+ self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
+ self._clickHandler.call( self, event, this );
+ event.preventDefault();
+ });
+ }
+ },
+
+ _createIcons: function() {
+ var options = this.options;
+ if ( options.icons ) {
+ $( "<span></span>" )
+ .addClass( "ui-icon " + options.icons.header )
+ .prependTo( this.headers );
+ this.active.children( ".ui-icon" )
+ .toggleClass(options.icons.header)
+ .toggleClass(options.icons.headerSelected);
+ this.element.addClass( "ui-accordion-icons" );
+ }
+ },
+
+ _destroyIcons: function() {
+ this.headers.children( ".ui-icon" ).remove();
+ this.element.removeClass( "ui-accordion-icons" );
+ },
+
+ destroy: function() {
+ var options = this.options;
+
+ this.element
+ .removeClass( "ui-accordion ui-widget ui-helper-reset" )
+ .removeAttr( "role" );
+
+ this.headers
+ .unbind( ".accordion" )
+ .removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
+ .removeAttr( "role" )
+ .removeAttr( "aria-expanded" )
+ .removeAttr( "aria-selected" )
+ .removeAttr( "tabIndex" );
+
+ this.headers.find( "a" ).removeAttr( "tabIndex" );
+ this._destroyIcons();
+ var contents = this.headers.next()
+ .css( "display", "" )
+ .removeAttr( "role" )
+ .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
+ if ( options.autoHeight || options.fillHeight ) {
+ contents.css( "height", "" );
+ }
+
+ return $.Widget.prototype.destroy.call( this );
+ },
+
+ _setOption: function( key, value ) {
+ $.Widget.prototype._setOption.apply( this, arguments );
+
+ if ( key == "active" ) {
+ this.activate( value );
+ }
+ if ( key == "icons" ) {
+ this._destroyIcons();
+ if ( value ) {
+ this._createIcons();
+ }
+ }
+ // #5332 - opacity doesn't cascade to positioned elements in IE
+ // so we need to add the disabled class to the headers and panels
+ if ( key == "disabled" ) {
+ this.headers.add(this.headers.next())
+ [ value ? "addClass" : "removeClass" ](
+ "ui-accordion-disabled ui-state-disabled" );
+ }
+ },
+
+ _keydown: function( event ) {
+ if ( this.options.disabled || event.altKey || event.ctrlKey ) {
+ return;
+ }
+
+ var keyCode = $.ui.keyCode,
+ length = this.headers.length,
+ currentIndex = this.headers.index( event.target ),
+ toFocus = false;
+
+ switch ( event.keyCode ) {
+ case keyCode.RIGHT:
+ case keyCode.DOWN:
+ toFocus = this.headers[ ( currentIndex + 1 ) % length ];
+ break;
+ case keyCode.LEFT:
+ case keyCode.UP:
+ toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
+ break;
+ case keyCode.SPACE:
+ case keyCode.ENTER:
+ this._clickHandler( { target: event.target }, event.target );
+ event.preventDefault();
+ }
+
+ if ( toFocus ) {
+ $( event.target ).attr( "tabIndex", -1 );
+ $( toFocus ).attr( "tabIndex", 0 );
+ toFocus.focus();
+ return false;
+ }
+
+ return true;
+ },
+
+ resize: function() {
+ var options = this.options,
+ maxHeight;
+
+ if ( options.fillSpace ) {
+ if ( $.browser.msie ) {
+ var defOverflow = this.element.parent().css( "overflow" );
+ this.element.parent().css( "overflow", "hidden");
+ }
+ maxHeight = this.element.parent().height();
+ if ($.browser.msie) {
+ this.element.parent().css( "overflow", defOverflow );
+ }
+
+ this.headers.each(function() {
+ maxHeight -= $( this ).outerHeight( true );
+ });
+
+ this.headers.next()
+ .each(function() {
+ $( this ).height( Math.max( 0, maxHeight -
+ $( this ).innerHeight() + $( this ).height() ) );
+ })
+ .css( "overflow", "auto" );
+ } else if ( options.autoHeight ) {
+ maxHeight = 0;
+ this.headers.next()
+ .each(function() {
+ maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
+ })
+ .height( maxHeight );
+ }
+
+ return this;
+ },
+
+ activate: function( index ) {
+ // TODO this gets called on init, changing the option without an explicit call for that
+ this.options.active = index;
+ // call clickHandler with custom event
+ var active = this._findActive( index )[ 0 ];
+ this._clickHandler( { target: active }, active );
+
+ return this;
+ },
+
+ _findActive: function( selector ) {
+ return selector
+ ? typeof selector === "number"
+ ? this.headers.filter( ":eq(" + selector + ")" )
+ : this.headers.not( this.headers.not( selector ) )
+ : selector === false
+ ? $( [] )
+ : this.headers.filter( ":eq(0)" );
+ },
+
+ // TODO isn't event.target enough? why the separate target argument?
+ _clickHandler: function( event, target ) {
+ var options = this.options;
+ if ( options.disabled ) {
+ return;
+ }
+
+ // called only when using activate(false) to close all parts programmatically
+ if ( !event.target ) {
+ if ( !options.collapsible ) {
+ return;
+ }
+ this.active
+ .removeClass( "ui-state-active ui-corner-top" )
+ .addClass( "ui-state-default ui-corner-all" )
+ .children( ".ui-icon" )
+ .removeClass( options.icons.headerSelected )
+ .addClass( options.icons.header );
+ this.active.next().addClass( "ui-accordion-content-active" );
+ var toHide = this.active.next(),
+ data = {
+ options: options,
+ newHeader: $( [] ),
+ oldHeader: options.active,
+ newContent: $( [] ),
+ oldContent: toHide
+ },
+ toShow = ( this.active = $( [] ) );
+ this._toggle( toShow, toHide, data );
+ return;
+ }
+
+ // get the click target
+ var clicked = $( event.currentTarget || target ),
+ clickedIsActive = clicked[0] === this.active[0];
+
+ // TODO the option is changed, is that correct?
+ // TODO if it is correct, shouldn't that happen after determining that the click is valid?
+ options.active = options.collapsible && clickedIsActive ?
+ false :
+ this.headers.index( clicked );
+
+ // if animations are still active, or the active header is the target, ignore click
+ if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
+ return;
+ }
+
+ // find elements to show and hide
+ var active = this.active,
+ toShow = clicked.next(),
+ toHide = this.active.next(),
+ data = {
+ options: options,
+ newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
+ oldHeader: this.active,
+ newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
+ oldContent: toHide
+ },
+ down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
+
+ // when the call to ._toggle() comes after the class changes
+ // it causes a very odd bug in IE 8 (see #6720)
+ this.active = clickedIsActive ? $([]) : clicked;
+ this._toggle( toShow, toHide, data, clickedIsActive, down );
+
+ // switch classes
+ active
+ .removeClass( "ui-state-active ui-corner-top" )
+ .addClass( "ui-state-default ui-corner-all" )
+ .children( ".ui-icon" )
+ .removeClass( options.icons.headerSelected )
+ .addClass( options.icons.header );
+ if ( !clickedIsActive ) {
+ clicked
+ .removeClass( "ui-state-default ui-corner-all" )
+ .addClass( "ui-state-active ui-corner-top" )
+ .children( ".ui-icon" )
+ .removeClass( options.icons.header )
+ .addClass( options.icons.headerSelected );
+ clicked
+ .next()
+ .addClass( "ui-accordion-content-active" );
+ }
+
+ return;
+ },
+
+ _toggle: function( toShow, toHide, data, clickedIsActive, down ) {
+ var self = this,
+ options = self.options;
+
+ self.toShow = toShow;
+ self.toHide = toHide;
+ self.data = data;
+
+ var complete = function() {
+ if ( !self ) {
+ return;
+ }
+ return self._completed.apply( self, arguments );
+ };
+
+ // trigger changestart event
+ self._trigger( "changestart", null, self.data );
+
+ // count elements to animate
+ self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
+
+ if ( options.animated ) {
+ var animOptions = {};
+
+ if ( options.collapsible && clickedIsActive ) {
+ animOptions = {
+ toShow: $( [] ),
+ toHide: toHide,
+ complete: complete,
+ down: down,
+ autoHeight: options.autoHeight || options.fillSpace
+ };
+ } else {
+ animOptions = {
+ toShow: toShow,
+ toHide: toHide,
+ complete: complete,
+ down: down,
+ autoHeight: options.autoHeight || options.fillSpace
+ };
+ }
+
+ if ( !options.proxied ) {
+ options.proxied = options.animated;
+ }
+
+ if ( !options.proxiedDuration ) {
+ options.proxiedDuration = options.duration;
+ }
+
+ options.animated = $.isFunction( options.proxied ) ?
+ options.proxied( animOptions ) :
+ options.proxied;
+
+ options.duration = $.isFunction( options.proxiedDuration ) ?
+ options.proxiedDuration( animOptions ) :
+ options.proxiedDuration;
+
+ var animations = $.ui.accordion.animations,
+ duration = options.duration,
+ easing = options.animated;
+
+ if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
+ easing = "slide";
+ }
+ if ( !animations[ easing ] ) {
+ animations[ easing ] = function( options ) {
+ this.slide( options, {
+ easing: easing,
+ duration: duration || 700
+ });
+ };
+ }
+
+ animations[ easing ]( animOptions );
+ } else {
+ if ( options.collapsible && clickedIsActive ) {
+ toShow.toggle();
+ } else {
+ toHide.hide();
+ toShow.show();
+ }
+
+ complete( true );
+ }
+
+ // TODO assert that the blur and focus triggers are really necessary, remove otherwise
+ toHide.prev()
+ .attr({
+ "aria-expanded": "false",
+ "aria-selected": "false",
+ tabIndex: -1
+ })
+ .blur();
+ toShow.prev()
+ .attr({
+ "aria-expanded": "true",
+ "aria-selected": "true",
+ tabIndex: 0
+ })
+ .focus();
+ },
+
+ _completed: function( cancel ) {
+ this.running = cancel ? 0 : --this.running;
+ if ( this.running ) {
+ return;
+ }
+
+ if ( this.options.clearStyle ) {
+ this.toShow.add( this.toHide ).css({
+ height: "",
+ overflow: ""
+ });
+ }
+
+ // other classes are removed before the animation; this one needs to stay until completed
+ this.toHide.removeClass( "ui-accordion-content-active" );
+ // Work around for rendering bug in IE (#5421)
+ if ( this.toHide.length ) {
+ this.toHide.parent()[0].className = this.toHide.parent()[0].className;
+ }
+
+ this._trigger( "change", null, this.data );
+ }
+});
+
+$.extend( $.ui.accordion, {
+ version: "1.8.18",
+ animations: {
+ slide: function( options, additions ) {
+ options = $.extend({
+ easing: "swing",
+ duration: 300
+ }, options, additions );
+ if ( !options.toHide.size() ) {
+ options.toShow.animate({
+ height: "show",
+ paddingTop: "show",
+ paddingBottom: "show"
+ }, options );
+ return;
+ }
+ if ( !options.toShow.size() ) {
+ options.toHide.animate({
+ height: "hide",
+ paddingTop: "hide",
+ paddingBottom: "hide"
+ }, options );
+ return;
+ }
+ var overflow = options.toShow.css( "overflow" ),
+ percentDone = 0,
+ showProps = {},
+ hideProps = {},
+ fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
+ originalWidth;
+ // fix width before calculating height of hidden element
+ var s = options.toShow;
+ originalWidth = s[0].style.width;
+ s.width( s.parent().width()
+ - parseFloat( s.css( "paddingLeft" ) )
+ - parseFloat( s.css( "paddingRight" ) )
+ - ( parseFloat( s.css( "borderLeftWidth" ) ) || 0 )
+ - ( parseFloat( s.css( "borderRightWidth" ) ) || 0 ) );
+
+ $.each( fxAttrs, function( i, prop ) {
+ hideProps[ prop ] = "hide";
+
+ var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
+ showProps[ prop ] = {
+ value: parts[ 1 ],
+ unit: parts[ 2 ] || "px"
+ };
+ });
+ options.toShow.css({ height: 0, overflow: "hidden" }).show();
+ options.toHide
+ .filter( ":hidden" )
+ .each( options.complete )
+ .end()
+ .filter( ":visible" )
+ .animate( hideProps, {
+ step: function( now, settings ) {
+ // only calculate the percent when animating height
+ // IE gets very inconsistent results when animating elements
+ // with small values, which is common for padding
+ if ( settings.prop == "height" ) {
+ percentDone = ( settings.end - settings.start === 0 ) ? 0 :
+ ( settings.now - settings.start ) / ( settings.end - settings.start );
+ }
+
+ options.toShow[ 0 ].style[ settings.prop ] =
+ ( percentDone * showProps[ settings.prop ].value )
+ + showProps[ settings.prop ].unit;
+ },
+ duration: options.duration,
+ easing: options.easing,
+ complete: function() {
+ if ( !options.autoHeight ) {
+ options.toShow.css( "height", "" );
+ }
+ options.toShow.css({
+ width: originalWidth,
+ overflow: overflow
+ });
+ options.complete();
+ }
+ });
+ },
+ bounceslide: function( options ) {
+ this.slide( options, {
+ easing: options.down ? "easeOutBounce" : "swing",
+ duration: options.down ? 1000 : 200
+ });
+ }
+ }
+});
+
+})( jQuery );
+/*
+ * jQuery UI Autocomplete 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Autocomplete
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ * jquery.ui.position.js
+ */
+(function( $, undefined ) {
+
+// used to prevent race conditions with remote data sources
+var requestIndex = 0;
+
+$.widget( "ui.autocomplete", {
+ options: {
+ appendTo: "body",
+ autoFocus: false,
+ delay: 300,
+ minLength: 1,
+ position: {
+ my: "left top",
+ at: "left bottom",
+ collision: "none"
+ },
+ source: null
+ },
+
+ pending: 0,
+
+ _create: function() {
+ var self = this,
+ doc = this.element[ 0 ].ownerDocument,
+ suppressKeyPress;
+
+ this.element
+ .addClass( "ui-autocomplete-input" )
+ .attr( "autocomplete", "off" )
+ // TODO verify these actually work as intended
+ .attr({
+ role: "textbox",
+ "aria-autocomplete": "list",
+ "aria-haspopup": "true"
+ })
+ .bind( "keydown.autocomplete", function( event ) {
+ if ( self.options.disabled || self.element.propAttr( "readOnly" ) ) {
+ return;
+ }
+
+ suppressKeyPress = false;
+ var keyCode = $.ui.keyCode;
+ switch( event.keyCode ) {
+ case keyCode.PAGE_UP:
+ self._move( "previousPage", event );
+ break;
+ case keyCode.PAGE_DOWN:
+ self._move( "nextPage", event );
+ break;
+ case keyCode.UP:
+ self._move( "previous", event );
+ // prevent moving cursor to beginning of text field in some browsers
+ event.preventDefault();
+ break;
+ case keyCode.DOWN:
+ self._move( "next", event );
+ // prevent moving cursor to end of text field in some browsers
+ event.preventDefault();
+ break;
+ case keyCode.ENTER:
+ case keyCode.NUMPAD_ENTER:
+ // when menu is open and has focus
+ if ( self.menu.active ) {
+ // #6055 - Opera still allows the keypress to occur
+ // which causes forms to submit
+ suppressKeyPress = true;
+ event.preventDefault();
+ }
+ //passthrough - ENTER and TAB both select the current element
+ case keyCode.TAB:
+ if ( !self.menu.active ) {
+ return;
+ }
+ self.menu.select( event );
+ break;
+ case keyCode.ESCAPE:
+ self.element.val( self.term );
+ self.close( event );
+ break;
+ default:
+ // keypress is triggered before the input value is changed
+ clearTimeout( self.searching );
+ self.searching = setTimeout(function() {
+ // only search if the value has changed
+ if ( self.term != self.element.val() ) {
+ self.selectedItem = null;
+ self.search( null, event );
+ }
+ }, self.options.delay );
+ break;
+ }
+ })
+ .bind( "keypress.autocomplete", function( event ) {
+ if ( suppressKeyPress ) {
+ suppressKeyPress = false;
+ event.preventDefault();
+ }
+ })
+ .bind( "focus.autocomplete", function() {
+ if ( self.options.disabled ) {
+ return;
+ }
+
+ self.selectedItem = null;
+ self.previous = self.element.val();
+ })
+ .bind( "blur.autocomplete", function( event ) {
+ if ( self.options.disabled ) {
+ return;
+ }
+
+ clearTimeout( self.searching );
+ // clicks on the menu (or a button to trigger a search) will cause a blur event
+ self.closing = setTimeout(function() {
+ self.close( event );
+ self._change( event );
+ }, 150 );
+ });
+ this._initSource();
+ this.response = function() {
+ return self._response.apply( self, arguments );
+ };
+ this.menu = $( "<ul></ul>" )
+ .addClass( "ui-autocomplete" )
+ .appendTo( $( this.options.appendTo || "body", doc )[0] )
+ // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
+ .mousedown(function( event ) {
+ // clicking on the scrollbar causes focus to shift to the body
+ // but we can't detect a mouseup or a click immediately afterward
+ // so we have to track the next mousedown and close the menu if
+ // the user clicks somewhere outside of the autocomplete
+ var menuElement = self.menu.element[ 0 ];
+ if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
+ setTimeout(function() {
+ $( document ).one( 'mousedown', function( event ) {
+ if ( event.target !== self.element[ 0 ] &&
+ event.target !== menuElement &&
+ !$.ui.contains( menuElement, event.target ) ) {
+ self.close();
+ }
+ });
+ }, 1 );
+ }
+
+ // use another timeout to make sure the blur-event-handler on the input was already triggered
+ setTimeout(function() {
+ clearTimeout( self.closing );
+ }, 13);
+ })
+ .menu({
+ focus: function( event, ui ) {
+ var item = ui.item.data( "item.autocomplete" );
+ if ( false !== self._trigger( "focus", event, { item: item } ) ) {
+ // use value to match what will end up in the input, if it was a key event
+ if ( /^key/.test(event.originalEvent.type) ) {
+ self.element.val( item.value );
+ }
+ }
+ },
+ selected: function( event, ui ) {
+ var item = ui.item.data( "item.autocomplete" ),
+ previous = self.previous;
+
+ // only trigger when focus was lost (click on menu)
+ if ( self.element[0] !== doc.activeElement ) {
+ self.element.focus();
+ self.previous = previous;
+ // #6109 - IE triggers two focus events and the second
+ // is asynchronous, so we need to reset the previous
+ // term synchronously and asynchronously :-(
+ setTimeout(function() {
+ self.previous = previous;
+ self.selectedItem = item;
+ }, 1);
+ }
+
+ if ( false !== self._trigger( "select", event, { item: item } ) ) {
+ self.element.val( item.value );
+ }
+ // reset the term after the select event
+ // this allows custom select handling to work properly
+ self.term = self.element.val();
+
+ self.close( event );
+ self.selectedItem = item;
+ },
+ blur: function( event, ui ) {
+ // don't set the value of the text field if it's already correct
+ // this prevents moving the cursor unnecessarily
+ if ( self.menu.element.is(":visible") &&
+ ( self.element.val() !== self.term ) ) {
+ self.element.val( self.term );
+ }
+ }
+ })
+ .zIndex( this.element.zIndex() + 1 )
+ // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
+ .css({ top: 0, left: 0 })
+ .hide()
+ .data( "menu" );
+ if ( $.fn.bgiframe ) {
+ this.menu.element.bgiframe();
+ }
+ // turning off autocomplete prevents the browser from remembering the
+ // value when navigating through history, so we re-enable autocomplete
+ // if the page is unloaded before the widget is destroyed. #7790
+ self.beforeunloadHandler = function() {
+ self.element.removeAttr( "autocomplete" );
+ };
+ $( window ).bind( "beforeunload", self.beforeunloadHandler );
+ },
+
+ destroy: function() {
+ this.element
+ .removeClass( "ui-autocomplete-input" )
+ .removeAttr( "autocomplete" )
+ .removeAttr( "role" )
+ .removeAttr( "aria-autocomplete" )
+ .removeAttr( "aria-haspopup" );
+ this.menu.element.remove();
+ $( window ).unbind( "beforeunload", this.beforeunloadHandler );
+ $.Widget.prototype.destroy.call( this );
+ },
+
+ _setOption: function( key, value ) {
+ $.Widget.prototype._setOption.apply( this, arguments );
+ if ( key === "source" ) {
+ this._initSource();
+ }
+ if ( key === "appendTo" ) {
+ this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
+ }
+ if ( key === "disabled" && value && this.xhr ) {
+ this.xhr.abort();
+ }
+ },
+
+ _initSource: function() {
+ var self = this,
+ array,
+ url;
+ if ( $.isArray(this.options.source) ) {
+ array = this.options.source;
+ this.source = function( request, response ) {
+ response( $.ui.autocomplete.filter(array, request.term) );
+ };
+ } else if ( typeof this.options.source === "string" ) {
+ url = this.options.source;
+ this.source = function( request, response ) {
+ if ( self.xhr ) {
+ self.xhr.abort();
+ }
+ self.xhr = $.ajax({
+ url: url,
+ data: request,
+ dataType: "json",
+ context: {
+ autocompleteRequest: ++requestIndex
+ },
+ success: function( data, status ) {
+ if ( this.autocompleteRequest === requestIndex ) {
+ response( data );
+ }
+ },
+ error: function() {
+ if ( this.autocompleteRequest === requestIndex ) {
+ response( [] );
+ }
+ }
+ });
+ };
+ } else {
+ this.source = this.options.source;
+ }
+ },
+
+ search: function( value, event ) {
+ value = value != null ? value : this.element.val();
+
+ // always save the actual value, not the one passed as an argument
+ this.term = this.element.val();
+
+ if ( value.length < this.options.minLength ) {
+ return this.close( event );
+ }
+
+ clearTimeout( this.closing );
+ if ( this._trigger( "search", event ) === false ) {
+ return;
+ }
+
+ return this._search( value );
+ },
+
+ _search: function( value ) {
+ this.pending++;
+ this.element.addClass( "ui-autocomplete-loading" );
+
+ this.source( { term: value }, this.response );
+ },
+
+ _response: function( content ) {
+ if ( !this.options.disabled && content && content.length ) {
+ content = this._normalize( content );
+ this._suggest( content );
+ this._trigger( "open" );
+ } else {
+ this.close();
+ }
+ this.pending--;
+ if ( !this.pending ) {
+ this.element.removeClass( "ui-autocomplete-loading" );
+ }
+ },
+
+ close: function( event ) {
+ clearTimeout( this.closing );
+ if ( this.menu.element.is(":visible") ) {
+ this.menu.element.hide();
+ this.menu.deactivate();
+ this._trigger( "close", event );
+ }
+ },
+
+ _change: function( event ) {
+ if ( this.previous !== this.element.val() ) {
+ this._trigger( "change", event, { item: this.selectedItem } );
+ }
+ },
+
+ _normalize: function( items ) {
+ // assume all items have the right format when the first item is complete
+ if ( items.length && items[0].label && items[0].value ) {
+ return items;
+ }
+ return $.map( items, function(item) {
+ if ( typeof item === "string" ) {
+ return {
+ label: item,
+ value: item
+ };
+ }
+ return $.extend({
+ label: item.label || item.value,
+ value: item.value || item.label
+ }, item );
+ });
+ },
+
+ _suggest: function( items ) {
+ var ul = this.menu.element
+ .empty()
+ .zIndex( this.element.zIndex() + 1 );
+ this._renderMenu( ul, items );
+ // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
+ this.menu.deactivate();
+ this.menu.refresh();
+
+ // size and position menu
+ ul.show();
+ this._resizeMenu();
+ ul.position( $.extend({
+ of: this.element
+ }, this.options.position ));
+
+ if ( this.options.autoFocus ) {
+ this.menu.next( new $.Event("mouseover") );
+ }
+ },
+
+ _resizeMenu: function() {
+ var ul = this.menu.element;
+ ul.outerWidth( Math.max(
+ // Firefox wraps long text (possibly a rounding bug)
+ // so we add 1px to avoid the wrapping (#7513)
+ ul.width( "" ).outerWidth() + 1,
+ this.element.outerWidth()
+ ) );
+ },
+
+ _renderMenu: function( ul, items ) {
+ var self = this;
+ $.each( items, function( index, item ) {
+ self._renderItem( ul, item );
+ });
+ },
+
+ _renderItem: function( ul, item) {
+ return $( "<li></li>" )
+ .data( "item.autocomplete", item )
+ .append( $( "<a></a>" ).text( item.label ) )
+ .appendTo( ul );
+ },
+
+ _move: function( direction, event ) {
+ if ( !this.menu.element.is(":visible") ) {
+ this.search( null, event );
+ return;
+ }
+ if ( this.menu.first() && /^previous/.test(direction) ||
+ this.menu.last() && /^next/.test(direction) ) {
+ this.element.val( this.term );
+ this.menu.deactivate();
+ return;
+ }
+ this.menu[ direction ]( event );
+ },
+
+ widget: function() {
+ return this.menu.element;
+ }
+});
+
+$.extend( $.ui.autocomplete, {
+ escapeRegex: function( value ) {
+ return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
+ },
+ filter: function(array, term) {
+ var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
+ return $.grep( array, function(value) {
+ return matcher.test( value.label || value.value || value );
+ });
+ }
+});
+
+}( jQuery ));
+
+/*
+ * jQuery UI Menu (not officially released)
+ *
+ * This widget isn't yet finished and the API is subject to change. We plan to finish
+ * it for the next release. You're welcome to give it a try anyway and give us feedback,
+ * as long as you're okay with migrating your code later on. We can help with that, too.
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Menu
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ */
+(function($) {
+
+$.widget("ui.menu", {
+ _create: function() {
+ var self = this;
+ this.element
+ .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
+ .attr({
+ role: "listbox",
+ "aria-activedescendant": "ui-active-menuitem"
+ })
+ .click(function( event ) {
+ if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
+ return;
+ }
+ // temporary
+ event.preventDefault();
+ self.select( event );
+ });
+ this.refresh();
+ },
+
+ refresh: function() {
+ var self = this;
+
+ // don't refresh list items that are already adapted
+ var items = this.element.children("li:not(.ui-menu-item):has(a)")
+ .addClass("ui-menu-item")
+ .attr("role", "menuitem");
+
+ items.children("a")
+ .addClass("ui-corner-all")
+ .attr("tabindex", -1)
+ // mouseenter doesn't work with event delegation
+ .mouseenter(function( event ) {
+ self.activate( event, $(this).parent() );
+ })
+ .mouseleave(function() {
+ self.deactivate();
+ });
+ },
+
+ activate: function( event, item ) {
+ this.deactivate();
+ if (this.hasScroll()) {
+ var offset = item.offset().top - this.element.offset().top,
+ scroll = this.element.scrollTop(),
+ elementHeight = this.element.height();
+ if (offset < 0) {
+ this.element.scrollTop( scroll + offset);
+ } else if (offset >= elementHeight) {
+ this.element.scrollTop( scroll + offset - elementHeight + item.height());
+ }
+ }
+ this.active = item.eq(0)
+ .children("a")
+ .addClass("ui-state-hover")
+ .attr("id", "ui-active-menuitem")
+ .end();
+ this._trigger("focus", event, { item: item });
+ },
+
+ deactivate: function() {
+ if (!this.active) { return; }
+
+ this.active.children("a")
+ .removeClass("ui-state-hover")
+ .removeAttr("id");
+ this._trigger("blur");
+ this.active = null;
+ },
+
+ next: function(event) {
+ this.move("next", ".ui-menu-item:first", event);
+ },
+
+ previous: function(event) {
+ this.move("prev", ".ui-menu-item:last", event);
+ },
+
+ first: function() {
+ return this.active && !this.active.prevAll(".ui-menu-item").length;
+ },
+
+ last: function() {
+ return this.active && !this.active.nextAll(".ui-menu-item").length;
+ },
+
+ move: function(direction, edge, event) {
+ if (!this.active) {
+ this.activate(event, this.element.children(edge));
+ return;
+ }
+ var next = this.active[direction + "All"](".ui-menu-item").eq(0);
+ if (next.length) {
+ this.activate(event, next);
+ } else {
+ this.activate(event, this.element.children(edge));
+ }
+ },
+
+ // TODO merge with previousPage
+ nextPage: function(event) {
+ if (this.hasScroll()) {
+ // TODO merge with no-scroll-else
+ if (!this.active || this.last()) {
+ this.activate(event, this.element.children(".ui-menu-item:first"));
+ return;
+ }
+ var base = this.active.offset().top,
+ height = this.element.height(),
+ result = this.element.children(".ui-menu-item").filter(function() {
+ var close = $(this).offset().top - base - height + $(this).height();
+ // TODO improve approximation
+ return close < 10 && close > -10;
+ });
+
+ // TODO try to catch this earlier when scrollTop indicates the last page anyway
+ if (!result.length) {
+ result = this.element.children(".ui-menu-item:last");
+ }
+ this.activate(event, result);
+ } else {
+ this.activate(event, this.element.children(".ui-menu-item")
+ .filter(!this.active || this.last() ? ":first" : ":last"));
+ }
+ },
+
+ // TODO merge with nextPage
+ previousPage: function(event) {
+ if (this.hasScroll()) {
+ // TODO merge with no-scroll-else
+ if (!this.active || this.first()) {
+ this.activate(event, this.element.children(".ui-menu-item:last"));
+ return;
+ }
+
+ var base = this.active.offset().top,
+ height = this.element.height();
+ result = this.element.children(".ui-menu-item").filter(function() {
+ var close = $(this).offset().top - base + height - $(this).height();
+ // TODO improve approximation
+ return close < 10 && close > -10;
+ });
+
+ // TODO try to catch this earlier when scrollTop indicates the last page anyway
+ if (!result.length) {
+ result = this.element.children(".ui-menu-item:first");
+ }
+ this.activate(event, result);
+ } else {
+ this.activate(event, this.element.children(".ui-menu-item")
+ .filter(!this.active || this.first() ? ":last" : ":first"));
+ }
+ },
+
+ hasScroll: function() {
+ return this.element.height() < this.element[ $.fn.prop ? "prop" : "attr" ]("scrollHeight");
+ },
+
+ select: function( event ) {
+ this._trigger("selected", event, { item: this.active });
+ }
+});
+
+}(jQuery));
+/*
+ * jQuery UI Button 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Button
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+var lastActive, startXPos, startYPos, clickDragged,
+ baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
+ stateClasses = "ui-state-hover ui-state-active ",
+ typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
+ formResetHandler = function() {
+ var buttons = $( this ).find( ":ui-button" );
+ setTimeout(function() {
+ buttons.button( "refresh" );
+ }, 1 );
+ },
+ radioGroup = function( radio ) {
+ var name = radio.name,
+ form = radio.form,
+ radios = $( [] );
+ if ( name ) {
+ if ( form ) {
+ radios = $( form ).find( "[name='" + name + "']" );
+ } else {
+ radios = $( "[name='" + name + "']", radio.ownerDocument )
+ .filter(function() {
+ return !this.form;
+ });
+ }
+ }
+ return radios;
+ };
+
+$.widget( "ui.button", {
+ options: {
+ disabled: null,
+ text: true,
+ label: null,
+ icons: {
+ primary: null,
+ secondary: null
+ }
+ },
+ _create: function() {
+ this.element.closest( "form" )
+ .unbind( "reset.button" )
+ .bind( "reset.button", formResetHandler );
+
+ if ( typeof this.options.disabled !== "boolean" ) {
+ this.options.disabled = !!this.element.propAttr( "disabled" );
+ } else {
+ this.element.propAttr( "disabled", this.options.disabled );
+ }
+
+ this._determineButtonType();
+ this.hasTitle = !!this.buttonElement.attr( "title" );
+
+ var self = this,
+ options = this.options,
+ toggleButton = this.type === "checkbox" || this.type === "radio",
+ hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
+ focusClass = "ui-state-focus";
+
+ if ( options.label === null ) {
+ options.label = this.buttonElement.html();
+ }
+
+ this.buttonElement
+ .addClass( baseClasses )
+ .attr( "role", "button" )
+ .bind( "mouseenter.button", function() {
+ if ( options.disabled ) {
+ return;
+ }
+ $( this ).addClass( "ui-state-hover" );
+ if ( this === lastActive ) {
+ $( this ).addClass( "ui-state-active" );
+ }
+ })
+ .bind( "mouseleave.button", function() {
+ if ( options.disabled ) {
+ return;
+ }
+ $( this ).removeClass( hoverClass );
+ })
+ .bind( "click.button", function( event ) {
+ if ( options.disabled ) {
+ event.preventDefault();
+ event.stopImmediatePropagation();
+ }
+ });
+
+ this.element
+ .bind( "focus.button", function() {
+ // no need to check disabled, focus won't be triggered anyway
+ self.buttonElement.addClass( focusClass );
+ })
+ .bind( "blur.button", function() {
+ self.buttonElement.removeClass( focusClass );
+ });
+
+ if ( toggleButton ) {
+ this.element.bind( "change.button", function() {
+ if ( clickDragged ) {
+ return;
+ }
+ self.refresh();
+ });
+ // if mouse moves between mousedown and mouseup (drag) set clickDragged flag
+ // prevents issue where button state changes but checkbox/radio checked state
+ // does not in Firefox (see ticket #6970)
+ this.buttonElement
+ .bind( "mousedown.button", function( event ) {
+ if ( options.disabled ) {
+ return;
+ }
+ clickDragged = false;
+ startXPos = event.pageX;
+ startYPos = event.pageY;
+ })
+ .bind( "mouseup.button", function( event ) {
+ if ( options.disabled ) {
+ return;
+ }
+ if ( startXPos !== event.pageX || startYPos !== event.pageY ) {
+ clickDragged = true;
+ }
+ });
+ }
+
+ if ( this.type === "checkbox" ) {
+ this.buttonElement.bind( "click.button", function() {
+ if ( options.disabled || clickDragged ) {
+ return false;
+ }
+ $( this ).toggleClass( "ui-state-active" );
+ self.buttonElement.attr( "aria-pressed", self.element[0].checked );
+ });
+ } else if ( this.type === "radio" ) {
+ this.buttonElement.bind( "click.button", function() {
+ if ( options.disabled || clickDragged ) {
+ return false;
+ }
+ $( this ).addClass( "ui-state-active" );
+ self.buttonElement.attr( "aria-pressed", "true" );
+
+ var radio = self.element[ 0 ];
+ radioGroup( radio )
+ .not( radio )
+ .map(function() {
+ return $( this ).button( "widget" )[ 0 ];
+ })
+ .removeClass( "ui-state-active" )
+ .attr( "aria-pressed", "false" );
+ });
+ } else {
+ this.buttonElement
+ .bind( "mousedown.button", function() {
+ if ( options.disabled ) {
+ return false;
+ }
+ $( this ).addClass( "ui-state-active" );
+ lastActive = this;
+ $( document ).one( "mouseup", function() {
+ lastActive = null;
+ });
+ })
+ .bind( "mouseup.button", function() {
+ if ( options.disabled ) {
+ return false;
+ }
+ $( this ).removeClass( "ui-state-active" );
+ })
+ .bind( "keydown.button", function(event) {
+ if ( options.disabled ) {
+ return false;
+ }
+ if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
+ $( this ).addClass( "ui-state-active" );
+ }
+ })
+ .bind( "keyup.button", function() {
+ $( this ).removeClass( "ui-state-active" );
+ });
+
+ if ( this.buttonElement.is("a") ) {
+ this.buttonElement.keyup(function(event) {
+ if ( event.keyCode === $.ui.keyCode.SPACE ) {
+ // TODO pass through original event correctly (just as 2nd argument doesn't work)
+ $( this ).click();
+ }
+ });
+ }
+ }
+
+ // TODO: pull out $.Widget's handling for the disabled option into
+ // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
+ // be overridden by individual plugins
+ this._setOption( "disabled", options.disabled );
+ this._resetButton();
+ },
+
+ _determineButtonType: function() {
+
+ if ( this.element.is(":checkbox") ) {
+ this.type = "checkbox";
+ } else if ( this.element.is(":radio") ) {
+ this.type = "radio";
+ } else if ( this.element.is("input") ) {
+ this.type = "input";
+ } else {
+ this.type = "button";
+ }
+
+ if ( this.type === "checkbox" || this.type === "radio" ) {
+ // we don't search against the document in case the element
+ // is disconnected from the DOM
+ var ancestor = this.element.parents().filter(":last"),
+ labelSelector = "label[for='" + this.element.attr("id") + "']";
+ this.buttonElement = ancestor.find( labelSelector );
+ if ( !this.buttonElement.length ) {
+ ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
+ this.buttonElement = ancestor.filter( labelSelector );
+ if ( !this.buttonElement.length ) {
+ this.buttonElement = ancestor.find( labelSelector );
+ }
+ }
+ this.element.addClass( "ui-helper-hidden-accessible" );
+
+ var checked = this.element.is( ":checked" );
+ if ( checked ) {
+ this.buttonElement.addClass( "ui-state-active" );
+ }
+ this.buttonElement.attr( "aria-pressed", checked );
+ } else {
+ this.buttonElement = this.element;
+ }
+ },
+
+ widget: function() {
+ return this.buttonElement;
+ },
+
+ destroy: function() {
+ this.element
+ .removeClass( "ui-helper-hidden-accessible" );
+ this.buttonElement
+ .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
+ .removeAttr( "role" )
+ .removeAttr( "aria-pressed" )
+ .html( this.buttonElement.find(".ui-button-text").html() );
+
+ if ( !this.hasTitle ) {
+ this.buttonElement.removeAttr( "title" );
+ }
+
+ $.Widget.prototype.destroy.call( this );
+ },
+
+ _setOption: function( key, value ) {
+ $.Widget.prototype._setOption.apply( this, arguments );
+ if ( key === "disabled" ) {
+ if ( value ) {
+ this.element.propAttr( "disabled", true );
+ } else {
+ this.element.propAttr( "disabled", false );
+ }
+ return;
+ }
+ this._resetButton();
+ },
+
+ refresh: function() {
+ var isDisabled = this.element.is( ":disabled" );
+ if ( isDisabled !== this.options.disabled ) {
+ this._setOption( "disabled", isDisabled );
+ }
+ if ( this.type === "radio" ) {
+ radioGroup( this.element[0] ).each(function() {
+ if ( $( this ).is( ":checked" ) ) {
+ $( this ).button( "widget" )
+ .addClass( "ui-state-active" )
+ .attr( "aria-pressed", "true" );
+ } else {
+ $( this ).button( "widget" )
+ .removeClass( "ui-state-active" )
+ .attr( "aria-pressed", "false" );
+ }
+ });
+ } else if ( this.type === "checkbox" ) {
+ if ( this.element.is( ":checked" ) ) {
+ this.buttonElement
+ .addClass( "ui-state-active" )
+ .attr( "aria-pressed", "true" );
+ } else {
+ this.buttonElement
+ .removeClass( "ui-state-active" )
+ .attr( "aria-pressed", "false" );
+ }
+ }
+ },
+
+ _resetButton: function() {
+ if ( this.type === "input" ) {
+ if ( this.options.label ) {
+ this.element.val( this.options.label );
+ }
+ return;
+ }
+ var buttonElement = this.buttonElement.removeClass( typeClasses ),
+ buttonText = $( "<span></span>", this.element[0].ownerDocument )
+ .addClass( "ui-button-text" )
+ .html( this.options.label )
+ .appendTo( buttonElement.empty() )
+ .text(),
+ icons = this.options.icons,
+ multipleIcons = icons.primary && icons.secondary,
+ buttonClasses = [];
+
+ if ( icons.primary || icons.secondary ) {
+ if ( this.options.text ) {
+ buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
+ }
+
+ if ( icons.primary ) {
+ buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
+ }
+
+ if ( icons.secondary ) {
+ buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
+ }
+
+ if ( !this.options.text ) {
+ buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
+
+ if ( !this.hasTitle ) {
+ buttonElement.attr( "title", buttonText );
+ }
+ }
+ } else {
+ buttonClasses.push( "ui-button-text-only" );
+ }
+ buttonElement.addClass( buttonClasses.join( " " ) );
+ }
+});
+
+$.widget( "ui.buttonset", {
+ options: {
+ items: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)"
+ },
+
+ _create: function() {
+ this.element.addClass( "ui-buttonset" );
+ },
+
+ _init: function() {
+ this.refresh();
+ },
+
+ _setOption: function( key, value ) {
+ if ( key === "disabled" ) {
+ this.buttons.button( "option", key, value );
+ }
+
+ $.Widget.prototype._setOption.apply( this, arguments );
+ },
+
+ refresh: function() {
+ var rtl = this.element.css( "direction" ) === "rtl";
+
+ this.buttons = this.element.find( this.options.items )
+ .filter( ":ui-button" )
+ .button( "refresh" )
+ .end()
+ .not( ":ui-button" )
+ .button()
+ .end()
+ .map(function() {
+ return $( this ).button( "widget" )[ 0 ];
+ })
+ .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
+ .filter( ":first" )
+ .addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
+ .end()
+ .filter( ":last" )
+ .addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
+ .end()
+ .end();
+ },
+
+ destroy: function() {
+ this.element.removeClass( "ui-buttonset" );
+ this.buttons
+ .map(function() {
+ return $( this ).button( "widget" )[ 0 ];
+ })
+ .removeClass( "ui-corner-left ui-corner-right" )
+ .end()
+ .button( "destroy" );
+
+ $.Widget.prototype.destroy.call( this );
+ }
+});
+
+}( jQuery ) );
+/*
+ * jQuery UI Datepicker 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Datepicker
+ *
+ * Depends:
+ * jquery.ui.core.js
+ */
+(function( $, undefined ) {
+
+$.extend($.ui, { datepicker: { version: "1.8.18" } });
+
+var PROP_NAME = 'datepicker';
+var dpuuid = new Date().getTime();
+var instActive;
+
+/* Date picker manager.
+ Use the singleton instance of this class, $.datepicker, to interact with the date picker.
+ Settings for (groups of) date pickers are maintained in an instance object,
+ allowing multiple different settings on the same page. */
+
+function Datepicker() {
+ this.debug = false; // Change this to true to start debugging
+ this._curInst = null; // The current instance in use
+ this._keyEvent = false; // If the last event was a key event
+ this._disabledInputs = []; // List of date picker inputs that have been disabled
+ this._datepickerShowing = false; // True if the popup picker is showing , false if not
+ this._inDialog = false; // True if showing within a "dialog", false if not
+ this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
+ this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
+ this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
+ this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
+ this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
+ this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
+ this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
+ this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
+ this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
+ this.regional = []; // Available regional settings, indexed by language code
+ this.regional[''] = { // Default regional settings
+ closeText: 'Done', // Display text for close link
+ prevText: 'Prev', // Display text for previous month link
+ nextText: 'Next', // Display text for next month link
+ currentText: 'Today', // Display text for current month link
+ monthNames: ['January','February','March','April','May','June',
+ 'July','August','September','October','November','December'], // Names of months for drop-down and formatting
+ monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
+ dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
+ dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
+ dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
+ weekHeader: 'Wk', // Column header for week of the year
+ dateFormat: 'mm/dd/yy', // See format options on parseDate
+ firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
+ isRTL: false, // True if right-to-left language, false if left-to-right
+ showMonthAfterYear: false, // True if the year select precedes month, false for month then year
+ yearSuffix: '' // Additional text to append to the year in the month headers
+ };
+ this._defaults = { // Global defaults for all the date picker instances
+ showOn: 'focus', // 'focus' for popup on focus,
+ // 'button' for trigger button, or 'both' for either
+ showAnim: 'fadeIn', // Name of jQuery animation for popup
+ showOptions: {}, // Options for enhanced animations
+ defaultDate: null, // Used when field is blank: actual date,
+ // +/-number for offset from today, null for today
+ appendText: '', // Display text following the input box, e.g. showing the format
+ buttonText: '...', // Text for trigger button
+ buttonImage: '', // URL for trigger button image
+ buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
+ hideIfNoPrevNext: false, // True to hide next/previous month links
+ // if not applicable, false to just disable them
+ navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
+ gotoCurrent: false, // True if today link goes back to current selection instead
+ changeMonth: false, // True if month can be selected directly, false if only prev/next
+ changeYear: false, // True if year can be selected directly, false if only prev/next
+ yearRange: 'c-10:c+10', // Range of years to display in drop-down,
+ // either relative to today's year (-nn:+nn), relative to currently displayed year
+ // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
+ showOtherMonths: false, // True to show dates in other months, false to leave blank
+ selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
+ showWeek: false, // True to show week of the year, false to not show it
+ calculateWeek: this.iso8601Week, // How to calculate the week of the year,
+ // takes a Date and returns the number of the week for it
+ shortYearCutoff: '+10', // Short year values < this are in the current century,
+ // > this are in the previous century,
+ // string value starting with '+' for current year + value
+ minDate: null, // The earliest selectable date, or null for no limit
+ maxDate: null, // The latest selectable date, or null for no limit
+ duration: 'fast', // Duration of display/closure
+ beforeShowDay: null, // Function that takes a date and returns an array with
+ // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
+ // [2] = cell title (optional), e.g. $.datepicker.noWeekends
+ beforeShow: null, // Function that takes an input field and
+ // returns a set of custom settings for the date picker
+ onSelect: null, // Define a callback function when a date is selected
+ onChangeMonthYear: null, // Define a callback function when the month or year is changed
+ onClose: null, // Define a callback function when the datepicker is closed
+ numberOfMonths: 1, // Number of months to show at a time
+ showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
+ stepMonths: 1, // Number of months to step back/forward
+ stepBigMonths: 12, // Number of months to step back/forward for the big links
+ altField: '', // Selector for an alternate field to store selected dates into
+ altFormat: '', // The date format to use for the alternate field
+ constrainInput: true, // The input is constrained by the current date format
+ showButtonPanel: false, // True to show button panel, false to not show it
+ autoSize: false, // True to size the input for the date format, false to leave as is
+ disabled: false // The initial disabled state
+ };
+ $.extend(this._defaults, this.regional['']);
+ this.dpDiv = bindHover($('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'));
+}
+
+$.extend(Datepicker.prototype, {
+ /* Class name added to elements to indicate already configured with a date picker. */
+ markerClassName: 'hasDatepicker',
+
+ //Keep track of the maximum number of rows displayed (see #7043)
+ maxRows: 4,
+
+ /* Debug logging (if enabled). */
+ log: function () {
+ if (this.debug)
+ console.log.apply('', arguments);
+ },
+
+ // TODO rename to "widget" when switching to widget factory
+ _widgetDatepicker: function() {
+ return this.dpDiv;
+ },
+
+ /* Override the default settings for all instances of the date picker.
+ @param settings object - the new settings to use as defaults (anonymous object)
+ @return the manager object */
+ setDefaults: function(settings) {
+ extendRemove(this._defaults, settings || {});
+ return this;
+ },
+
+ /* Attach the date picker to a jQuery selection.
+ @param target element - the target input field or division or span
+ @param settings object - the new settings to use for this date picker instance (anonymous) */
+ _attachDatepicker: function(target, settings) {
+ // check for settings on the control itself - in namespace 'date:'
+ var inlineSettings = null;
+ for (var attrName in this._defaults) {
+ var attrValue = target.getAttribute('date:' + attrName);
+ if (attrValue) {
+ inlineSettings = inlineSettings || {};
+ try {
+ inlineSettings[attrName] = eval(attrValue);
+ } catch (err) {
+ inlineSettings[attrName] = attrValue;
+ }
+ }
+ }
+ var nodeName = target.nodeName.toLowerCase();
+ var inline = (nodeName == 'div' || nodeName == 'span');
+ if (!target.id) {
+ this.uuid += 1;
+ target.id = 'dp' + this.uuid;
+ }
+ var inst = this._newInst($(target), inline);
+ inst.settings = $.extend({}, settings || {}, inlineSettings || {});
+ if (nodeName == 'input') {
+ this._connectDatepicker(target, inst);
+ } else if (inline) {
+ this._inlineDatepicker(target, inst);
+ }
+ },
+
+ /* Create a new instance object. */
+ _newInst: function(target, inline) {
+ var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
+ return {id: id, input: target, // associated target
+ selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
+ drawMonth: 0, drawYear: 0, // month being drawn
+ inline: inline, // is datepicker inline or not
+ dpDiv: (!inline ? this.dpDiv : // presentation div
+ bindHover($('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')))};
+ },
+
+ /* Attach the date picker to an input field. */
+ _connectDatepicker: function(target, inst) {
+ var input = $(target);
+ inst.append = $([]);
+ inst.trigger = $([]);
+ if (input.hasClass(this.markerClassName))
+ return;
+ this._attachments(input, inst);
+ input.addClass(this.markerClassName).keydown(this._doKeyDown).
+ keypress(this._doKeyPress).keyup(this._doKeyUp).
+ bind("setData.datepicker", function(event, key, value) {
+ inst.settings[key] = value;
+ }).bind("getData.datepicker", function(event, key) {
+ return this._get(inst, key);
+ });
+ this._autoSize(inst);
+ $.data(target, PROP_NAME, inst);
+ //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
+ if( inst.settings.disabled ) {
+ this._disableDatepicker( target );
+ }
+ },
+
+ /* Make attachments based on settings. */
+ _attachments: function(input, inst) {
+ var appendText = this._get(inst, 'appendText');
+ var isRTL = this._get(inst, 'isRTL');
+ if (inst.append)
+ inst.append.remove();
+ if (appendText) {
+ inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
+ input[isRTL ? 'before' : 'after'](inst.append);
+ }
+ input.unbind('focus', this._showDatepicker);
+ if (inst.trigger)
+ inst.trigger.remove();
+ var showOn = this._get(inst, 'showOn');
+ if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
+ input.focus(this._showDatepicker);
+ if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
+ var buttonText = this._get(inst, 'buttonText');
+ var buttonImage = this._get(inst, 'buttonImage');
+ inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
+ $('<img/>').addClass(this._triggerClass).
+ attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
+ $('<button type="button"></button>').addClass(this._triggerClass).
+ html(buttonImage == '' ? buttonText : $('<img/>').attr(
+ { src:buttonImage, alt:buttonText, title:buttonText })));
+ input[isRTL ? 'before' : 'after'](inst.trigger);
+ inst.trigger.click(function() {
+ if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
+ $.datepicker._hideDatepicker();
+ else if ($.datepicker._datepickerShowing && $.datepicker._lastInput != input[0]) {
+ $.datepicker._hideDatepicker();
+ $.datepicker._showDatepicker(input[0]);
+ } else
+ $.datepicker._showDatepicker(input[0]);
+ return false;
+ });
+ }
+ },
+
+ /* Apply the maximum length for the date format. */
+ _autoSize: function(inst) {
+ if (this._get(inst, 'autoSize') && !inst.inline) {
+ var date = new Date(2009, 12 - 1, 20); // Ensure double digits
+ var dateFormat = this._get(inst, 'dateFormat');
+ if (dateFormat.match(/[DM]/)) {
+ var findMax = function(names) {
+ var max = 0;
+ var maxI = 0;
+ for (var i = 0; i < names.length; i++) {
+ if (names[i].length > max) {
+ max = names[i].length;
+ maxI = i;
+ }
+ }
+ return maxI;
+ };
+ date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
+ 'monthNames' : 'monthNamesShort'))));
+ date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
+ 'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
+ }
+ inst.input.attr('size', this._formatDate(inst, date).length);
+ }
+ },
+
+ /* Attach an inline date picker to a div. */
+ _inlineDatepicker: function(target, inst) {
+ var divSpan = $(target);
+ if (divSpan.hasClass(this.markerClassName))
+ return;
+ divSpan.addClass(this.markerClassName).append(inst.dpDiv).
+ bind("setData.datepicker", function(event, key, value){
+ inst.settings[key] = value;
+ }).bind("getData.datepicker", function(event, key){
+ return this._get(inst, key);
+ });
+ $.data(target, PROP_NAME, inst);
+ this._setDate(inst, this._getDefaultDate(inst), true);
+ this._updateDatepicker(inst);
+ this._updateAlternate(inst);
+ //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
+ if( inst.settings.disabled ) {
+ this._disableDatepicker( target );
+ }
+ // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
+ // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
+ inst.dpDiv.css( "display", "block" );
+ },
+
+ /* Pop-up the date picker in a "dialog" box.
+ @param input element - ignored
+ @param date string or Date - the initial date to display
+ @param onSelect function - the function to call when a date is selected
+ @param settings object - update the dialog date picker instance's settings (anonymous object)
+ @param pos int[2] - coordinates for the dialog's position within the screen or
+ event - with x/y coordinates or
+ leave empty for default (screen centre)
+ @return the manager object */
+ _dialogDatepicker: function(input, date, onSelect, settings, pos) {
+ var inst = this._dialogInst; // internal instance
+ if (!inst) {
+ this.uuid += 1;
+ var id = 'dp' + this.uuid;
+ this._dialogInput = $('<input type="text" id="' + id +
+ '" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
+ this._dialogInput.keydown(this._doKeyDown);
+ $('body').append(this._dialogInput);
+ inst = this._dialogInst = this._newInst(this._dialogInput, false);
+ inst.settings = {};
+ $.data(this._dialogInput[0], PROP_NAME, inst);
+ }
+ extendRemove(inst.settings, settings || {});
+ date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
+ this._dialogInput.val(date);
+
+ this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
+ if (!this._pos) {
+ var browserWidth = document.documentElement.clientWidth;
+ var browserHeight = document.documentElement.clientHeight;
+ var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
+ var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
+ this._pos = // should use actual width/height below
+ [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
+ }
+
+ // move input on screen for focus, but hidden behind dialog
+ this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
+ inst.settings.onSelect = onSelect;
+ this._inDialog = true;
+ this.dpDiv.addClass(this._dialogClass);
+ this._showDatepicker(this._dialogInput[0]);
+ if ($.blockUI)
+ $.blockUI(this.dpDiv);
+ $.data(this._dialogInput[0], PROP_NAME, inst);
+ return this;
+ },
+
+ /* Detach a datepicker from its control.
+ @param target element - the target input field or division or span */
+ _destroyDatepicker: function(target) {
+ var $target = $(target);
+ var inst = $.data(target, PROP_NAME);
+ if (!$target.hasClass(this.markerClassName)) {
+ return;
+ }
+ var nodeName = target.nodeName.toLowerCase();
+ $.removeData(target, PROP_NAME);
+ if (nodeName == 'input') {
+ inst.append.remove();
+ inst.trigger.remove();
+ $target.removeClass(this.markerClassName).
+ unbind('focus', this._showDatepicker).
+ unbind('keydown', this._doKeyDown).
+ unbind('keypress', this._doKeyPress).
+ unbind('keyup', this._doKeyUp);
+ } else if (nodeName == 'div' || nodeName == 'span')
+ $target.removeClass(this.markerClassName).empty();
+ },
+
+ /* Enable the date picker to a jQuery selection.
+ @param target element - the target input field or division or span */
+ _enableDatepicker: function(target) {
+ var $target = $(target);
+ var inst = $.data(target, PROP_NAME);
+ if (!$target.hasClass(this.markerClassName)) {
+ return;
+ }
+ var nodeName = target.nodeName.toLowerCase();
+ if (nodeName == 'input') {
+ target.disabled = false;
+ inst.trigger.filter('button').
+ each(function() { this.disabled = false; }).end().
+ filter('img').css({opacity: '1.0', cursor: ''});
+ }
+ else if (nodeName == 'div' || nodeName == 'span') {
+ var inline = $target.children('.' + this._inlineClass);
+ inline.children().removeClass('ui-state-disabled');
+ inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
+ removeAttr("disabled");
+ }
+ this._disabledInputs = $.map(this._disabledInputs,
+ function(value) { return (value == target ? null : value); }); // delete entry
+ },
+
+ /* Disable the date picker to a jQuery selection.
+ @param target element - the target input field or division or span */
+ _disableDatepicker: function(target) {
+ var $target = $(target);
+ var inst = $.data(target, PROP_NAME);
+ if (!$target.hasClass(this.markerClassName)) {
+ return;
+ }
+ var nodeName = target.nodeName.toLowerCase();
+ if (nodeName == 'input') {
+ target.disabled = true;
+ inst.trigger.filter('button').
+ each(function() { this.disabled = true; }).end().
+ filter('img').css({opacity: '0.5', cursor: 'default'});
+ }
+ else if (nodeName == 'div' || nodeName == 'span') {
+ var inline = $target.children('.' + this._inlineClass);
+ inline.children().addClass('ui-state-disabled');
+ inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
+ attr("disabled", "disabled");
+ }
+ this._disabledInputs = $.map(this._disabledInputs,
+ function(value) { return (value == target ? null : value); }); // delete entry
+ this._disabledInputs[this._disabledInputs.length] = target;
+ },
+
+ /* Is the first field in a jQuery collection disabled as a datepicker?
+ @param target element - the target input field or division or span
+ @return boolean - true if disabled, false if enabled */
+ _isDisabledDatepicker: function(target) {
+ if (!target) {
+ return false;
+ }
+ for (var i = 0; i < this._disabledInputs.length; i++) {
+ if (this._disabledInputs[i] == target)
+ return true;
+ }
+ return false;
+ },
+
+ /* Retrieve the instance data for the target control.
+ @param target element - the target input field or division or span
+ @return object - the associated instance data
+ @throws error if a jQuery problem getting data */
+ _getInst: function(target) {
+ try {
+ return $.data(target, PROP_NAME);
+ }
+ catch (err) {
+ throw 'Missing instance data for this datepicker';
+ }
+ },
+
+ /* Update or retrieve the settings for a date picker attached to an input field or division.
+ @param target element - the target input field or division or span
+ @param name object - the new settings to update or
+ string - the name of the setting to change or retrieve,
+ when retrieving also 'all' for all instance settings or
+ 'defaults' for all global defaults
+ @param value any - the new value for the setting
+ (omit if above is an object or to retrieve a value) */
+ _optionDatepicker: function(target, name, value) {
+ var inst = this._getInst(target);
+ if (arguments.length == 2 && typeof name == 'string') {
+ return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
+ (inst ? (name == 'all' ? $.extend({}, inst.settings) :
+ this._get(inst, name)) : null));
+ }
+ var settings = name || {};
+ if (typeof name == 'string') {
+ settings = {};
+ settings[name] = value;
+ }
+ if (inst) {
+ if (this._curInst == inst) {
+ this._hideDatepicker();
+ }
+ var date = this._getDateDatepicker(target, true);
+ var minDate = this._getMinMaxDate(inst, 'min');
+ var maxDate = this._getMinMaxDate(inst, 'max');
+ extendRemove(inst.settings, settings);
+ // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
+ if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined)
+ inst.settings.minDate = this._formatDate(inst, minDate);
+ if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined)
+ inst.settings.maxDate = this._formatDate(inst, maxDate);
+ this._attachments($(target), inst);
+ this._autoSize(inst);
+ this._setDate(inst, date);
+ this._updateAlternate(inst);
+ this._updateDatepicker(inst);
+ }
+ },
+
+ // change method deprecated
+ _changeDatepicker: function(target, name, value) {
+ this._optionDatepicker(target, name, value);
+ },
+
+ /* Redraw the date picker attached to an input field or division.
+ @param target element - the target input field or division or span */
+ _refreshDatepicker: function(target) {
+ var inst = this._getInst(target);
+ if (inst) {
+ this._updateDatepicker(inst);
+ }
+ },
+
+ /* Set the dates for a jQuery selection.
+ @param target element - the target input field or division or span
+ @param date Date - the new date */
+ _setDateDatepicker: function(target, date) {
+ var inst = this._getInst(target);
+ if (inst) {
+ this._setDate(inst, date);
+ this._updateDatepicker(inst);
+ this._updateAlternate(inst);
+ }
+ },
+
+ /* Get the date(s) for the first entry in a jQuery selection.
+ @param target element - the target input field or division or span
+ @param noDefault boolean - true if no default date is to be used
+ @return Date - the current date */
+ _getDateDatepicker: function(target, noDefault) {
+ var inst = this._getInst(target);
+ if (inst && !inst.inline)
+ this._setDateFromField(inst, noDefault);
+ return (inst ? this._getDate(inst) : null);
+ },
+
+ /* Handle keystrokes. */
+ _doKeyDown: function(event) {
+ var inst = $.datepicker._getInst(event.target);
+ var handled = true;
+ var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
+ inst._keyEvent = true;
+ if ($.datepicker._datepickerShowing)
+ switch (event.keyCode) {
+ case 9: $.datepicker._hideDatepicker();
+ handled = false;
+ break; // hide on tab out
+ case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' +
+ $.datepicker._currentClass + ')', inst.dpDiv);
+ if (sel[0])
+ $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
+ var onSelect = $.datepicker._get(inst, 'onSelect');
+ if (onSelect) {
+ var dateStr = $.datepicker._formatDate(inst);
+
+ // trigger custom callback
+ onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
+ }
+ else
+ $.datepicker._hideDatepicker();
+ return false; // don't submit the form
+ break; // select the value on enter
+ case 27: $.datepicker._hideDatepicker();
+ break; // hide on escape
+ case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
+ -$.datepicker._get(inst, 'stepBigMonths') :
+ -$.datepicker._get(inst, 'stepMonths')), 'M');
+ break; // previous month/year on page up/+ ctrl
+ case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
+ +$.datepicker._get(inst, 'stepBigMonths') :
+ +$.datepicker._get(inst, 'stepMonths')), 'M');
+ break; // next month/year on page down/+ ctrl
+ case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
+ handled = event.ctrlKey || event.metaKey;
+ break; // clear on ctrl or command +end
+ case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
+ handled = event.ctrlKey || event.metaKey;
+ break; // current on ctrl or command +home
+ case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
+ handled = event.ctrlKey || event.metaKey;
+ // -1 day on ctrl or command +left
+ if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
+ -$.datepicker._get(inst, 'stepBigMonths') :
+ -$.datepicker._get(inst, 'stepMonths')), 'M');
+ // next month/year on alt +left on Mac
+ break;
+ case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
+ handled = event.ctrlKey || event.metaKey;
+ break; // -1 week on ctrl or command +up
+ case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
+ handled = event.ctrlKey || event.metaKey;
+ // +1 day on ctrl or command +right
+ if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
+ +$.datepicker._get(inst, 'stepBigMonths') :
+ +$.datepicker._get(inst, 'stepMonths')), 'M');
+ // next month/year on alt +right
+ break;
+ case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
+ handled = event.ctrlKey || event.metaKey;
+ break; // +1 week on ctrl or command +down
+ default: handled = false;
+ }
+ else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
+ $.datepicker._showDatepicker(this);
+ else {
+ handled = false;
+ }
+ if (handled) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ },
+
+ /* Filter entered characters - based on date format. */
+ _doKeyPress: function(event) {
+ var inst = $.datepicker._getInst(event.target);
+ if ($.datepicker._get(inst, 'constrainInput')) {
+ var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
+ var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
+ return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
+ }
+ },
+
+ /* Synchronise manual entry and field/alternate field. */
+ _doKeyUp: function(event) {
+ var inst = $.datepicker._getInst(event.target);
+ if (inst.input.val() != inst.lastVal) {
+ try {
+ var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
+ (inst.input ? inst.input.val() : null),
+ $.datepicker._getFormatConfig(inst));
+ if (date) { // only if valid
+ $.datepicker._setDateFromField(inst);
+ $.datepicker._updateAlternate(inst);
+ $.datepicker._updateDatepicker(inst);
+ }
+ }
+ catch (event) {
+ $.datepicker.log(event);
+ }
+ }
+ return true;
+ },
+
+ /* Pop-up the date picker for a given input field.
+ If false returned from beforeShow event handler do not show.
+ @param input element - the input field attached to the date picker or
+ event - if triggered by focus */
+ _showDatepicker: function(input) {
+ input = input.target || input;
+ if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
+ input = $('input', input.parentNode)[0];
+ if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
+ return;
+ var inst = $.datepicker._getInst(input);
+ if ($.datepicker._curInst && $.datepicker._curInst != inst) {
+ $.datepicker._curInst.dpDiv.stop(true, true);
+ if ( inst && $.datepicker._datepickerShowing ) {
+ $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
+ }
+ }
+ var beforeShow = $.datepicker._get(inst, 'beforeShow');
+ var beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
+ if(beforeShowSettings === false){
+ //false
+ return;
+ }
+ extendRemove(inst.settings, beforeShowSettings);
+ inst.lastVal = null;
+ $.datepicker._lastInput = input;
+ $.datepicker._setDateFromField(inst);
+ if ($.datepicker._inDialog) // hide cursor
+ input.value = '';
+ if (!$.datepicker._pos) { // position below input
+ $.datepicker._pos = $.datepicker._findPos(input);
+ $.datepicker._pos[1] += input.offsetHeight; // add the height
+ }
+ var isFixed = false;
+ $(input).parents().each(function() {
+ isFixed |= $(this).css('position') == 'fixed';
+ return !isFixed;
+ });
+ if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
+ $.datepicker._pos[0] -= document.documentElement.scrollLeft;
+ $.datepicker._pos[1] -= document.documentElement.scrollTop;
+ }
+ var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
+ $.datepicker._pos = null;
+ //to avoid flashes on Firefox
+ inst.dpDiv.empty();
+ // determine sizing offscreen
+ inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
+ $.datepicker._updateDatepicker(inst);
+ // fix width for dynamic number of date pickers
+ // and adjust position before showing
+ offset = $.datepicker._checkOffset(inst, offset, isFixed);
+ inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
+ 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
+ left: offset.left + 'px', top: offset.top + 'px'});
+ if (!inst.inline) {
+ var showAnim = $.datepicker._get(inst, 'showAnim');
+ var duration = $.datepicker._get(inst, 'duration');
+ var postProcess = function() {
+ var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
+ if( !! cover.length ){
+ var borders = $.datepicker._getBorders(inst.dpDiv);
+ cover.css({left: -borders[0], top: -borders[1],
+ width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
+ }
+ };
+ inst.dpDiv.zIndex($(input).zIndex()+1);
+ $.datepicker._datepickerShowing = true;
+ if ($.effects && $.effects[showAnim])
+ inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
+ else
+ inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
+ if (!showAnim || !duration)
+ postProcess();
+ if (inst.input.is(':visible') && !inst.input.is(':disabled'))
+ inst.input.focus();
+ $.datepicker._curInst = inst;
+ }
+ },
+
+ /* Generate the date picker content. */
+ _updateDatepicker: function(inst) {
+ var self = this;
+ self.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
+ var borders = $.datepicker._getBorders(inst.dpDiv);
+ instActive = inst; // for delegate hover events
+ inst.dpDiv.empty().append(this._generateHTML(inst));
+ var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
+ if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6
+ cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
+ }
+ inst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover();
+ var numMonths = this._getNumberOfMonths(inst);
+ var cols = numMonths[1];
+ var width = 17;
+ inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
+ if (cols > 1)
+ inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
+ inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
+ 'Class']('ui-datepicker-multi');
+ inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
+ 'Class']('ui-datepicker-rtl');
+ if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
+ // #6694 - don't focus the input if it's already focused
+ // this breaks the change event in IE
+ inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement)
+ inst.input.focus();
+ // deffered render of the years select (to avoid flashes on Firefox)
+ if( inst.yearshtml ){
+ var origyearshtml = inst.yearshtml;
+ setTimeout(function(){
+ //assure that inst.yearshtml didn't change.
+ if( origyearshtml === inst.yearshtml && inst.yearshtml ){
+ inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml);
+ }
+ origyearshtml = inst.yearshtml = null;
+ }, 0);
+ }
+ },
+
+ /* Retrieve the size of left and top borders for an element.
+ @param elem (jQuery object) the element of interest
+ @return (number[2]) the left and top borders */
+ _getBorders: function(elem) {
+ var convert = function(value) {
+ return {thin: 1, medium: 2, thick: 3}[value] || value;
+ };
+ return [parseFloat(convert(elem.css('border-left-width'))),
+ parseFloat(convert(elem.css('border-top-width')))];
+ },
+
+ /* Check positioning to remain on screen. */
+ _checkOffset: function(inst, offset, isFixed) {
+ var dpWidth = inst.dpDiv.outerWidth();
+ var dpHeight = inst.dpDiv.outerHeight();
+ var inputWidth = inst.input ? inst.input.outerWidth() : 0;
+ var inputHeight = inst.input ? inst.input.outerHeight() : 0;
+ var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
+ var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
+
+ offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
+ offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
+ offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
+
+ // now check if datepicker is showing outside window viewport - move to a better place if so.
+ offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
+ Math.abs(offset.left + dpWidth - viewWidth) : 0);
+ offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
+ Math.abs(dpHeight + inputHeight) : 0);
+
+ return offset;
+ },
+
+ /* Find an object's position on the screen. */
+ _findPos: function(obj) {
+ var inst = this._getInst(obj);
+ var isRTL = this._get(inst, 'isRTL');
+ while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) {
+ obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
+ }
+ var position = $(obj).offset();
+ return [position.left, position.top];
+ },
+
+ /* Hide the date picker from view.
+ @param input element - the input field attached to the date picker */
+ _hideDatepicker: function(input) {
+ var inst = this._curInst;
+ if (!inst || (input && inst != $.data(input, PROP_NAME)))
+ return;
+ if (this._datepickerShowing) {
+ var showAnim = this._get(inst, 'showAnim');
+ var duration = this._get(inst, 'duration');
+ var self = this;
+ var postProcess = function() {
+ $.datepicker._tidyDialog(inst);
+ self._curInst = null;
+ };
+ if ($.effects && $.effects[showAnim])
+ inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
+ else
+ inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
+ (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
+ if (!showAnim)
+ postProcess();
+ this._datepickerShowing = false;
+ var onClose = this._get(inst, 'onClose');
+ if (onClose)
+ onClose.apply((inst.input ? inst.input[0] : null),
+ [(inst.input ? inst.input.val() : ''), inst]);
+ this._lastInput = null;
+ if (this._inDialog) {
+ this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
+ if ($.blockUI) {
+ $.unblockUI();
+ $('body').append(this.dpDiv);
+ }
+ }
+ this._inDialog = false;
+ }
+ },
+
+ /* Tidy up after a dialog display. */
+ _tidyDialog: function(inst) {
+ inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
+ },
+
+ /* Close date picker if clicked elsewhere. */
+ _checkExternalClick: function(event) {
+ if (!$.datepicker._curInst)
+ return;
+
+ var $target = $(event.target),
+ inst = $.datepicker._getInst($target[0]);
+
+ if ( ( ( $target[0].id != $.datepicker._mainDivId &&
+ $target.parents('#' + $.datepicker._mainDivId).length == 0 &&
+ !$target.hasClass($.datepicker.markerClassName) &&
+ !$target.closest("." + $.datepicker._triggerClass).length &&
+ $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
+ ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst != inst ) )
+ $.datepicker._hideDatepicker();
+ },
+
+ /* Adjust one of the date sub-fields. */
+ _adjustDate: function(id, offset, period) {
+ var target = $(id);
+ var inst = this._getInst(target[0]);
+ if (this._isDisabledDatepicker(target[0])) {
+ return;
+ }
+ this._adjustInstDate(inst, offset +
+ (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
+ period);
+ this._updateDatepicker(inst);
+ },
+
+ /* Action for current link. */
+ _gotoToday: function(id) {
+ var target = $(id);
+ var inst = this._getInst(target[0]);
+ if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
+ inst.selectedDay = inst.currentDay;
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth;
+ inst.drawYear = inst.selectedYear = inst.currentYear;
+ }
+ else {
+ var date = new Date();
+ inst.selectedDay = date.getDate();
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
+ inst.drawYear = inst.selectedYear = date.getFullYear();
+ }
+ this._notifyChange(inst);
+ this._adjustDate(target);
+ },
+
+ /* Action for selecting a new month/year. */
+ _selectMonthYear: function(id, select, period) {
+ var target = $(id);
+ var inst = this._getInst(target[0]);
+ inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
+ inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
+ parseInt(select.options[select.selectedIndex].value,10);
+ this._notifyChange(inst);
+ this._adjustDate(target);
+ },
+
+ /* Action for selecting a day. */
+ _selectDay: function(id, month, year, td) {
+ var target = $(id);
+ if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
+ return;
+ }
+ var inst = this._getInst(target[0]);
+ inst.selectedDay = inst.currentDay = $('a', td).html();
+ inst.selectedMonth = inst.currentMonth = month;
+ inst.selectedYear = inst.currentYear = year;
+ this._selectDate(id, this._formatDate(inst,
+ inst.currentDay, inst.currentMonth, inst.currentYear));
+ },
+
+ /* Erase the input field and hide the date picker. */
+ _clearDate: function(id) {
+ var target = $(id);
+ var inst = this._getInst(target[0]);
+ this._selectDate(target, '');
+ },
+
+ /* Update the input field with the selected date. */
+ _selectDate: function(id, dateStr) {
+ var target = $(id);
+ var inst = this._getInst(target[0]);
+ dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
+ if (inst.input)
+ inst.input.val(dateStr);
+ this._updateAlternate(inst);
+ var onSelect = this._get(inst, 'onSelect');
+ if (onSelect)
+ onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
+ else if (inst.input)
+ inst.input.trigger('change'); // fire the change event
+ if (inst.inline)
+ this._updateDatepicker(inst);
+ else {
+ this._hideDatepicker();
+ this._lastInput = inst.input[0];
+ if (typeof(inst.input[0]) != 'object')
+ inst.input.focus(); // restore focus
+ this._lastInput = null;
+ }
+ },
+
+ /* Update any alternate field to synchronise with the main field. */
+ _updateAlternate: function(inst) {
+ var altField = this._get(inst, 'altField');
+ if (altField) { // update alternate field too
+ var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
+ var date = this._getDate(inst);
+ var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
+ $(altField).each(function() { $(this).val(dateStr); });
+ }
+ },
+
+ /* Set as beforeShowDay function to prevent selection of weekends.
+ @param date Date - the date to customise
+ @return [boolean, string] - is this date selectable?, what is its CSS class? */
+ noWeekends: function(date) {
+ var day = date.getDay();
+ return [(day > 0 && day < 6), ''];
+ },
+
+ /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
+ @param date Date - the date to get the week for
+ @return number - the number of the week within the year that contains this date */
+ iso8601Week: function(date) {
+ var checkDate = new Date(date.getTime());
+ // Find Thursday of this week starting on Monday
+ checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
+ var time = checkDate.getTime();
+ checkDate.setMonth(0); // Compare with Jan 1
+ checkDate.setDate(1);
+ return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
+ },
+
+ /* Parse a string value into a date object.
+ See formatDate below for the possible formats.
+
+ @param format string - the expected format of the date
+ @param value string - the date in the above format
+ @param settings Object - attributes include:
+ shortYearCutoff number - the cutoff year for determining the century (optional)
+ dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
+ dayNames string[7] - names of the days from Sunday (optional)
+ monthNamesShort string[12] - abbreviated names of the months (optional)
+ monthNames string[12] - names of the months (optional)
+ @return Date - the extracted date value or null if value is blank */
+ parseDate: function (format, value, settings) {
+ if (format == null || value == null)
+ throw 'Invalid arguments';
+ value = (typeof value == 'object' ? value.toString() : value + '');
+ if (value == '')
+ return null;
+ var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
+ shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
+ new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
+ var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
+ var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
+ var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
+ var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
+ var year = -1;
+ var month = -1;
+ var day = -1;
+ var doy = -1;
+ var literal = false;
+ // Check whether a format character is doubled
+ var lookAhead = function(match) {
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
+ if (matches)
+ iFormat++;
+ return matches;
+ };
+ // Extract a number from the string value
+ var getNumber = function(match) {
+ var isDoubled = lookAhead(match);
+ var size = (match == '@' ? 14 : (match == '!' ? 20 :
+ (match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2))));
+ var digits = new RegExp('^\\d{1,' + size + '}');
+ var num = value.substring(iValue).match(digits);
+ if (!num)
+ throw 'Missing number at position ' + iValue;
+ iValue += num[0].length;
+ return parseInt(num[0], 10);
+ };
+ // Extract a name from the string value and convert to an index
+ var getName = function(match, shortNames, longNames) {
+ var names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
+ return [ [k, v] ];
+ }).sort(function (a, b) {
+ return -(a[1].length - b[1].length);
+ });
+ var index = -1;
+ $.each(names, function (i, pair) {
+ var name = pair[1];
+ if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) {
+ index = pair[0];
+ iValue += name.length;
+ return false;
+ }
+ });
+ if (index != -1)
+ return index + 1;
+ else
+ throw 'Unknown name at position ' + iValue;
+ };
+ // Confirm that a literal character matches the string value
+ var checkLiteral = function() {
+ if (value.charAt(iValue) != format.charAt(iFormat))
+ throw 'Unexpected literal at position ' + iValue;
+ iValue++;
+ };
+ var iValue = 0;
+ for (var iFormat = 0; iFormat < format.length; iFormat++) {
+ if (literal)
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
+ literal = false;
+ else
+ checkLiteral();
+ else
+ switch (format.charAt(iFormat)) {
+ case 'd':
+ day = getNumber('d');
+ break;
+ case 'D':
+ getName('D', dayNamesShort, dayNames);
+ break;
+ case 'o':
+ doy = getNumber('o');
+ break;
+ case 'm':
+ month = getNumber('m');
+ break;
+ case 'M':
+ month = getName('M', monthNamesShort, monthNames);
+ break;
+ case 'y':
+ year = getNumber('y');
+ break;
+ case '@':
+ var date = new Date(getNumber('@'));
+ year = date.getFullYear();
+ month = date.getMonth() + 1;
+ day = date.getDate();
+ break;
+ case '!':
+ var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
+ year = date.getFullYear();
+ month = date.getMonth() + 1;
+ day = date.getDate();
+ break;
+ case "'":
+ if (lookAhead("'"))
+ checkLiteral();
+ else
+ literal = true;
+ break;
+ default:
+ checkLiteral();
+ }
+ }
+ if (iValue < value.length){
+ throw "Extra/unparsed characters found in date: " + value.substring(iValue);
+ }
+ if (year == -1)
+ year = new Date().getFullYear();
+ else if (year < 100)
+ year += new Date().getFullYear() - new Date().getFullYear() % 100 +
+ (year <= shortYearCutoff ? 0 : -100);
+ if (doy > -1) {
+ month = 1;
+ day = doy;
+ do {
+ var dim = this._getDaysInMonth(year, month - 1);
+ if (day <= dim)
+ break;
+ month++;
+ day -= dim;
+ } while (true);
+ }
+ var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
+ if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
+ throw 'Invalid date'; // E.g. 31/02/00
+ return date;
+ },
+
+ /* Standard date formats. */
+ ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
+ COOKIE: 'D, dd M yy',
+ ISO_8601: 'yy-mm-dd',
+ RFC_822: 'D, d M y',
+ RFC_850: 'DD, dd-M-y',
+ RFC_1036: 'D, d M y',
+ RFC_1123: 'D, d M yy',
+ RFC_2822: 'D, d M yy',
+ RSS: 'D, d M y', // RFC 822
+ TICKS: '!',
+ TIMESTAMP: '@',
+ W3C: 'yy-mm-dd', // ISO 8601
+
+ _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
+ Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
+
+ /* Format a date object into a string value.
+ The format can be combinations of the following:
+ d - day of month (no leading zero)
+ dd - day of month (two digit)
+ o - day of year (no leading zeros)
+ oo - day of year (three digit)
+ D - day name short
+ DD - day name long
+ m - month of year (no leading zero)
+ mm - month of year (two digit)
+ M - month name short
+ MM - month name long
+ y - year (two digit)
+ yy - year (four digit)
+ @ - Unix timestamp (ms since 01/01/1970)
+ ! - Windows ticks (100ns since 01/01/0001)
+ '...' - literal text
+ '' - single quote
+
+ @param format string - the desired format of the date
+ @param date Date - the date value to format
+ @param settings Object - attributes include:
+ dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
+ dayNames string[7] - names of the days from Sunday (optional)
+ monthNamesShort string[12] - abbreviated names of the months (optional)
+ monthNames string[12] - names of the months (optional)
+ @return string - the date in the above format */
+ formatDate: function (format, date, settings) {
+ if (!date)
+ return '';
+ var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
+ var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
+ var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
+ var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
+ // Check whether a format character is doubled
+ var lookAhead = function(match) {
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
+ if (matches)
+ iFormat++;
+ return matches;
+ };
+ // Format a number, with leading zero if necessary
+ var formatNumber = function(match, value, len) {
+ var num = '' + value;
+ if (lookAhead(match))
+ while (num.length < len)
+ num = '0' + num;
+ return num;
+ };
+ // Format a name, short or long as requested
+ var formatName = function(match, value, shortNames, longNames) {
+ return (lookAhead(match) ? longNames[value] : shortNames[value]);
+ };
+ var output = '';
+ var literal = false;
+ if (date)
+ for (var iFormat = 0; iFormat < format.length; iFormat++) {
+ if (literal)
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
+ literal = false;
+ else
+ output += format.charAt(iFormat);
+ else
+ switch (format.charAt(iFormat)) {
+ case 'd':
+ output += formatNumber('d', date.getDate(), 2);
+ break;
+ case 'D':
+ output += formatName('D', date.getDay(), dayNamesShort, dayNames);
+ break;
+ case 'o':
+ output += formatNumber('o',
+ Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
+ break;
+ case 'm':
+ output += formatNumber('m', date.getMonth() + 1, 2);
+ break;
+ case 'M':
+ output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
+ break;
+ case 'y':
+ output += (lookAhead('y') ? date.getFullYear() :
+ (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
+ break;
+ case '@':
+ output += date.getTime();
+ break;
+ case '!':
+ output += date.getTime() * 10000 + this._ticksTo1970;
+ break;
+ case "'":
+ if (lookAhead("'"))
+ output += "'";
+ else
+ literal = true;
+ break;
+ default:
+ output += format.charAt(iFormat);
+ }
+ }
+ return output;
+ },
+
+ /* Extract all possible characters from the date format. */
+ _possibleChars: function (format) {
+ var chars = '';
+ var literal = false;
+ // Check whether a format character is doubled
+ var lookAhead = function(match) {
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
+ if (matches)
+ iFormat++;
+ return matches;
+ };
+ for (var iFormat = 0; iFormat < format.length; iFormat++)
+ if (literal)
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
+ literal = false;
+ else
+ chars += format.charAt(iFormat);
+ else
+ switch (format.charAt(iFormat)) {
+ case 'd': case 'm': case 'y': case '@':
+ chars += '0123456789';
+ break;
+ case 'D': case 'M':
+ return null; // Accept anything
+ case "'":
+ if (lookAhead("'"))
+ chars += "'";
+ else
+ literal = true;
+ break;
+ default:
+ chars += format.charAt(iFormat);
+ }
+ return chars;
+ },
+
+ /* Get a setting value, defaulting if necessary. */
+ _get: function(inst, name) {
+ return inst.settings[name] !== undefined ?
+ inst.settings[name] : this._defaults[name];
+ },
+
+ /* Parse existing date and initialise date picker. */
+ _setDateFromField: function(inst, noDefault) {
+ if (inst.input.val() == inst.lastVal) {
+ return;
+ }
+ var dateFormat = this._get(inst, 'dateFormat');
+ var dates = inst.lastVal = inst.input ? inst.input.val() : null;
+ var date, defaultDate;
+ date = defaultDate = this._getDefaultDate(inst);
+ var settings = this._getFormatConfig(inst);
+ try {
+ date = this.parseDate(dateFormat, dates, settings) || defaultDate;
+ } catch (event) {
+ this.log(event);
+ dates = (noDefault ? '' : dates);
+ }
+ inst.selectedDay = date.getDate();
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
+ inst.drawYear = inst.selectedYear = date.getFullYear();
+ inst.currentDay = (dates ? date.getDate() : 0);
+ inst.currentMonth = (dates ? date.getMonth() : 0);
+ inst.currentYear = (dates ? date.getFullYear() : 0);
+ this._adjustInstDate(inst);
+ },
+
+ /* Retrieve the default date shown on opening. */
+ _getDefaultDate: function(inst) {
+ return this._restrictMinMax(inst,
+ this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
+ },
+
+ /* A date may be specified as an exact value or a relative one. */
+ _determineDate: function(inst, date, defaultDate) {
+ var offsetNumeric = function(offset) {
+ var date = new Date();
+ date.setDate(date.getDate() + offset);
+ return date;
+ };
+ var offsetString = function(offset) {
+ try {
+ return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
+ offset, $.datepicker._getFormatConfig(inst));
+ }
+ catch (e) {
+ // Ignore
+ }
+ var date = (offset.toLowerCase().match(/^c/) ?
+ $.datepicker._getDate(inst) : null) || new Date();
+ var year = date.getFullYear();
+ var month = date.getMonth();
+ var day = date.getDate();
+ var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
+ var matches = pattern.exec(offset);
+ while (matches) {
+ switch (matches[2] || 'd') {
+ case 'd' : case 'D' :
+ day += parseInt(matches[1],10); break;
+ case 'w' : case 'W' :
+ day += parseInt(matches[1],10) * 7; break;
+ case 'm' : case 'M' :
+ month += parseInt(matches[1],10);
+ day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
+ break;
+ case 'y': case 'Y' :
+ year += parseInt(matches[1],10);
+ day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
+ break;
+ }
+ matches = pattern.exec(offset);
+ }
+ return new Date(year, month, day);
+ };
+ var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) :
+ (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
+ newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate);
+ if (newDate) {
+ newDate.setHours(0);
+ newDate.setMinutes(0);
+ newDate.setSeconds(0);
+ newDate.setMilliseconds(0);
+ }
+ return this._daylightSavingAdjust(newDate);
+ },
+
+ /* Handle switch to/from daylight saving.
+ Hours may be non-zero on daylight saving cut-over:
+ > 12 when midnight changeover, but then cannot generate
+ midnight datetime, so jump to 1AM, otherwise reset.
+ @param date (Date) the date to check
+ @return (Date) the corrected date */
+ _daylightSavingAdjust: function(date) {
+ if (!date) return null;
+ date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
+ return date;
+ },
+
+ /* Set the date(s) directly. */
+ _setDate: function(inst, date, noChange) {
+ var clear = !date;
+ var origMonth = inst.selectedMonth;
+ var origYear = inst.selectedYear;
+ var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
+ inst.selectedDay = inst.currentDay = newDate.getDate();
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
+ inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
+ if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
+ this._notifyChange(inst);
+ this._adjustInstDate(inst);
+ if (inst.input) {
+ inst.input.val(clear ? '' : this._formatDate(inst));
+ }
+ },
+
+ /* Retrieve the date(s) directly. */
+ _getDate: function(inst) {
+ var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
+ this._daylightSavingAdjust(new Date(
+ inst.currentYear, inst.currentMonth, inst.currentDay)));
+ return startDate;
+ },
+
+ /* Generate the HTML for the current state of the date picker. */
+ _generateHTML: function(inst) {
+ var today = new Date();
+ today = this._daylightSavingAdjust(
+ new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
+ var isRTL = this._get(inst, 'isRTL');
+ var showButtonPanel = this._get(inst, 'showButtonPanel');
+ var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
+ var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
+ var numMonths = this._getNumberOfMonths(inst);
+ var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
+ var stepMonths = this._get(inst, 'stepMonths');
+ var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
+ var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
+ new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
+ var minDate = this._getMinMaxDate(inst, 'min');
+ var maxDate = this._getMinMaxDate(inst, 'max');
+ var drawMonth = inst.drawMonth - showCurrentAtPos;
+ var drawYear = inst.drawYear;
+ if (drawMonth < 0) {
+ drawMonth += 12;
+ drawYear--;
+ }
+ if (maxDate) {
+ var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
+ maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
+ maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
+ while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
+ drawMonth--;
+ if (drawMonth < 0) {
+ drawMonth = 11;
+ drawYear--;
+ }
+ }
+ }
+ inst.drawMonth = drawMonth;
+ inst.drawYear = drawYear;
+ var prevText = this._get(inst, 'prevText');
+ prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
+ this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
+ this._getFormatConfig(inst)));
+ var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
+ '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
+ '.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
+ ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
+ (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
+ var nextText = this._get(inst, 'nextText');
+ nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
+ this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
+ this._getFormatConfig(inst)));
+ var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
+ '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
+ '.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
+ ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
+ (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
+ var currentText = this._get(inst, 'currentText');
+ var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
+ currentText = (!navigationAsDateFormat ? currentText :
+ this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
+ var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
+ '.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
+ var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
+ (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
+ '.datepicker._gotoToday(\'#' + inst.id + '\');"' +
+ '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
+ var firstDay = parseInt(this._get(inst, 'firstDay'),10);
+ firstDay = (isNaN(firstDay) ? 0 : firstDay);
+ var showWeek = this._get(inst, 'showWeek');
+ var dayNames = this._get(inst, 'dayNames');
+ var dayNamesShort = this._get(inst, 'dayNamesShort');
+ var dayNamesMin = this._get(inst, 'dayNamesMin');
+ var monthNames = this._get(inst, 'monthNames');
+ var monthNamesShort = this._get(inst, 'monthNamesShort');
+ var beforeShowDay = this._get(inst, 'beforeShowDay');
+ var showOtherMonths = this._get(inst, 'showOtherMonths');
+ var selectOtherMonths = this._get(inst, 'selectOtherMonths');
+ var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
+ var defaultDate = this._getDefaultDate(inst);
+ var html = '';
+ for (var row = 0; row < numMonths[0]; row++) {
+ var group = '';
+ this.maxRows = 4;
+ for (var col = 0; col < numMonths[1]; col++) {
+ var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
+ var cornerClass = ' ui-corner-all';
+ var calender = '';
+ if (isMultiMonth) {
+ calender += '<div class="ui-datepicker-group';
+ if (numMonths[1] > 1)
+ switch (col) {
+ case 0: calender += ' ui-datepicker-group-first';
+ cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
+ case numMonths[1]-1: calender += ' ui-datepicker-group-last';
+ cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
+ default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
+ }
+ calender += '">';
+ }
+ calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
+ (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
+ (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
+ this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
+ row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
+ '</div><table class="ui-datepicker-calendar"><thead>' +
+ '<tr>';
+ var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
+ for (var dow = 0; dow < 7; dow++) { // days of the week
+ var day = (dow + firstDay) % 7;
+ thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
+ '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
+ }
+ calender += thead + '</tr></thead><tbody>';
+ var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
+ if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
+ inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
+ var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
+ var curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
+ var numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
+ this.maxRows = numRows;
+ var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
+ for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
+ calender += '<tr>';
+ var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
+ this._get(inst, 'calculateWeek')(printDate) + '</td>');
+ for (var dow = 0; dow < 7; dow++) { // create date picker days
+ var daySettings = (beforeShowDay ?
+ beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
+ var otherMonth = (printDate.getMonth() != drawMonth);
+ var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
+ (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
+ tbody += '<td class="' +
+ ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
+ (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
+ ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
+ (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
+ // or defaultDate is current printedDate and defaultDate is selectedDate
+ ' ' + this._dayOverClass : '') + // highlight selected day
+ (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') + // highlight unselectable days
+ (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
+ (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
+ (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
+ ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
+ (unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
+ inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
+ (otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
+ (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
+ (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
+ (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
+ (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
+ '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
+ printDate.setDate(printDate.getDate() + 1);
+ printDate = this._daylightSavingAdjust(printDate);
+ }
+ calender += tbody + '</tr>';
+ }
+ drawMonth++;
+ if (drawMonth > 11) {
+ drawMonth = 0;
+ drawYear++;
+ }
+ calender += '</tbody></table>' + (isMultiMonth ? '</div>' +
+ ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
+ group += calender;
+ }
+ html += group;
+ }
+ html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
+ '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
+ inst._keyEvent = false;
+ return html;
+ },
+
+ /* Generate the month and year header. */
+ _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
+ secondary, monthNames, monthNamesShort) {
+ var changeMonth = this._get(inst, 'changeMonth');
+ var changeYear = this._get(inst, 'changeYear');
+ var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
+ var html = '<div class="ui-datepicker-title">';
+ var monthHtml = '';
+ // month selection
+ if (secondary || !changeMonth)
+ monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
+ else {
+ var inMinYear = (minDate && minDate.getFullYear() == drawYear);
+ var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
+ monthHtml += '<select class="ui-datepicker-month" ' +
+ 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
+ '>';
+ for (var month = 0; month < 12; month++) {
+ if ((!inMinYear || month >= minDate.getMonth()) &&
+ (!inMaxYear || month <= maxDate.getMonth()))
+ monthHtml += '<option value="' + month + '"' +
+ (month == drawMonth ? ' selected="selected"' : '') +
+ '>' + monthNamesShort[month] + '</option>';
+ }
+ monthHtml += '</select>';
+ }
+ if (!showMonthAfterYear)
+ html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
+ // year selection
+ if ( !inst.yearshtml ) {
+ inst.yearshtml = '';
+ if (secondary || !changeYear)
+ html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
+ else {
+ // determine range of years to display
+ var years = this._get(inst, 'yearRange').split(':');
+ var thisYear = new Date().getFullYear();
+ var determineYear = function(value) {
+ var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
+ (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
+ parseInt(value, 10)));
+ return (isNaN(year) ? thisYear : year);
+ };
+ var year = determineYear(years[0]);
+ var endYear = Math.max(year, determineYear(years[1] || ''));
+ year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
+ endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
+ inst.yearshtml += '<select class="ui-datepicker-year" ' +
+ 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
+ '>';
+ for (; year <= endYear; year++) {
+ inst.yearshtml += '<option value="' + year + '"' +
+ (year == drawYear ? ' selected="selected"' : '') +
+ '>' + year + '</option>';
+ }
+ inst.yearshtml += '</select>';
+
+ html += inst.yearshtml;
+ inst.yearshtml = null;
+ }
+ }
+ html += this._get(inst, 'yearSuffix');
+ if (showMonthAfterYear)
+ html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
+ html += '</div>'; // Close datepicker_header
+ return html;
+ },
+
+ /* Adjust one of the date sub-fields. */
+ _adjustInstDate: function(inst, offset, period) {
+ var year = inst.drawYear + (period == 'Y' ? offset : 0);
+ var month = inst.drawMonth + (period == 'M' ? offset : 0);
+ var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
+ (period == 'D' ? offset : 0);
+ var date = this._restrictMinMax(inst,
+ this._daylightSavingAdjust(new Date(year, month, day)));
+ inst.selectedDay = date.getDate();
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
+ inst.drawYear = inst.selectedYear = date.getFullYear();
+ if (period == 'M' || period == 'Y')
+ this._notifyChange(inst);
+ },
+
+ /* Ensure a date is within any min/max bounds. */
+ _restrictMinMax: function(inst, date) {
+ var minDate = this._getMinMaxDate(inst, 'min');
+ var maxDate = this._getMinMaxDate(inst, 'max');
+ var newDate = (minDate && date < minDate ? minDate : date);
+ newDate = (maxDate && newDate > maxDate ? maxDate : newDate);
+ return newDate;
+ },
+
+ /* Notify change of month/year. */
+ _notifyChange: function(inst) {
+ var onChange = this._get(inst, 'onChangeMonthYear');
+ if (onChange)
+ onChange.apply((inst.input ? inst.input[0] : null),
+ [inst.selectedYear, inst.selectedMonth + 1, inst]);
+ },
+
+ /* Determine the number of months to show. */
+ _getNumberOfMonths: function(inst) {
+ var numMonths = this._get(inst, 'numberOfMonths');
+ return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
+ },
+
+ /* Determine the current maximum date - ensure no time components are set. */
+ _getMinMaxDate: function(inst, minMax) {
+ return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
+ },
+
+ /* Find the number of days in a given month. */
+ _getDaysInMonth: function(year, month) {
+ return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
+ },
+
+ /* Find the day of the week of the first of a month. */
+ _getFirstDayOfMonth: function(year, month) {
+ return new Date(year, month, 1).getDay();
+ },
+
+ /* Determines if we should allow a "next/prev" month display change. */
+ _canAdjustMonth: function(inst, offset, curYear, curMonth) {
+ var numMonths = this._getNumberOfMonths(inst);
+ var date = this._daylightSavingAdjust(new Date(curYear,
+ curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
+ if (offset < 0)
+ date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
+ return this._isInRange(inst, date);
+ },
+
+ /* Is the given date in the accepted range? */
+ _isInRange: function(inst, date) {
+ var minDate = this._getMinMaxDate(inst, 'min');
+ var maxDate = this._getMinMaxDate(inst, 'max');
+ return ((!minDate || date.getTime() >= minDate.getTime()) &&
+ (!maxDate || date.getTime() <= maxDate.getTime()));
+ },
+
+ /* Provide the configuration settings for formatting/parsing. */
+ _getFormatConfig: function(inst) {
+ var shortYearCutoff = this._get(inst, 'shortYearCutoff');
+ shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
+ new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
+ return {shortYearCutoff: shortYearCutoff,
+ dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
+ monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
+ },
+
+ /* Format the given date for display. */
+ _formatDate: function(inst, day, month, year) {
+ if (!day) {
+ inst.currentDay = inst.selectedDay;
+ inst.currentMonth = inst.selectedMonth;
+ inst.currentYear = inst.selectedYear;
+ }
+ var date = (day ? (typeof day == 'object' ? day :
+ this._daylightSavingAdjust(new Date(year, month, day))) :
+ this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
+ return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
+ }
+});
+
+/*
+ * Bind hover events for datepicker elements.
+ * Done via delegate so the binding only occurs once in the lifetime of the parent div.
+ * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
+ */
+function bindHover(dpDiv) {
+ var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a';
+ return dpDiv.bind('mouseout', function(event) {
+ var elem = $( event.target ).closest( selector );
+ if ( !elem.length ) {
+ return;
+ }
+ elem.removeClass( "ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover" );
+ })
+ .bind('mouseover', function(event) {
+ var elem = $( event.target ).closest( selector );
+ if ($.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0]) ||
+ !elem.length ) {
+ return;
+ }
+ elem.parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
+ elem.addClass('ui-state-hover');
+ if (elem.hasClass('ui-datepicker-prev')) elem.addClass('ui-datepicker-prev-hover');
+ if (elem.hasClass('ui-datepicker-next')) elem.addClass('ui-datepicker-next-hover');
+ });
+}
+
+/* jQuery extend now ignores nulls! */
+function extendRemove(target, props) {
+ $.extend(target, props);
+ for (var name in props)
+ if (props[name] == null || props[name] == undefined)
+ target[name] = props[name];
+ return target;
+};
+
+/* Determine whether an object is an array. */
+function isArray(a) {
+ return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
+ (a.constructor && a.constructor.toString().match(/\Array\(\)/))));
+};
+
+/* Invoke the datepicker functionality.
+ @param options string - a command, optionally followed by additional parameters or
+ Object - settings for attaching new datepicker functionality
+ @return jQuery object */
+$.fn.datepicker = function(options){
+
+ /* Verify an empty collection wasn't passed - Fixes #6976 */
+ if ( !this.length ) {
+ return this;
+ }
+
+ /* Initialise the date picker. */
+ if (!$.datepicker.initialized) {
+ $(document).mousedown($.datepicker._checkExternalClick).
+ find('body').append($.datepicker.dpDiv);
+ $.datepicker.initialized = true;
+ }
+
+ var otherArgs = Array.prototype.slice.call(arguments, 1);
+ if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
+ return $.datepicker['_' + options + 'Datepicker'].
+ apply($.datepicker, [this[0]].concat(otherArgs));
+ if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
+ return $.datepicker['_' + options + 'Datepicker'].
+ apply($.datepicker, [this[0]].concat(otherArgs));
+ return this.each(function() {
+ typeof options == 'string' ?
+ $.datepicker['_' + options + 'Datepicker'].
+ apply($.datepicker, [this].concat(otherArgs)) :
+ $.datepicker._attachDatepicker(this, options);
+ });
+};
+
+$.datepicker = new Datepicker(); // singleton instance
+$.datepicker.initialized = false;
+$.datepicker.uuid = new Date().getTime();
+$.datepicker.version = "1.8.18";
+
+// Workaround for #4055
+// Add another global to avoid noConflict issues with inline event handlers
+window['DP_jQuery_' + dpuuid] = $;
+
+})(jQuery);
+/*
+ * jQuery UI Dialog 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Dialog
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ * jquery.ui.button.js
+ * jquery.ui.draggable.js
+ * jquery.ui.mouse.js
+ * jquery.ui.position.js
+ * jquery.ui.resizable.js
+ */
+(function( $, undefined ) {
+
+var uiDialogClasses =
+ 'ui-dialog ' +
+ 'ui-widget ' +
+ 'ui-widget-content ' +
+ 'ui-corner-all ',
+ sizeRelatedOptions = {
+ buttons: true,
+ height: true,
+ maxHeight: true,
+ maxWidth: true,
+ minHeight: true,
+ minWidth: true,
+ width: true
+ },
+ resizableRelatedOptions = {
+ maxHeight: true,
+ maxWidth: true,
+ minHeight: true,
+ minWidth: true
+ },
+ // support for jQuery 1.3.2 - handle common attrFn methods for dialog
+ attrFn = $.attrFn || {
+ val: true,
+ css: true,
+ html: true,
+ text: true,
+ data: true,
+ width: true,
+ height: true,
+ offset: true,
+ click: true
+ };
+
+$.widget("ui.dialog", {
+ options: {
+ autoOpen: true,
+ buttons: {},
+ closeOnEscape: true,
+ closeText: 'close',
+ dialogClass: '',
+ draggable: true,
+ hide: null,
+ height: 'auto',
+ maxHeight: false,
+ maxWidth: false,
+ minHeight: 150,
+ minWidth: 150,
+ modal: false,
+ position: {
+ my: 'center',
+ at: 'center',
+ collision: 'fit',
+ // ensure that the titlebar is never outside the document
+ using: function(pos) {
+ var topOffset = $(this).css(pos).offset().top;
+ if (topOffset < 0) {
+ $(this).css('top', pos.top - topOffset);
+ }
+ }
+ },
+ resizable: true,
+ show: null,
+ stack: true,
+ title: '',
+ width: 300,
+ zIndex: 1000
+ },
+
+ _create: function() {
+ this.originalTitle = this.element.attr('title');
+ // #5742 - .attr() might return a DOMElement
+ if ( typeof this.originalTitle !== "string" ) {
+ this.originalTitle = "";
+ }
+
+ this.options.title = this.options.title || this.originalTitle;
+ var self = this,
+ options = self.options,
+
+ title = options.title || '&#160;',
+ titleId = $.ui.dialog.getTitleId(self.element),
+
+ uiDialog = (self.uiDialog = $('<div></div>'))
+ .appendTo(document.body)
+ .hide()
+ .addClass(uiDialogClasses + options.dialogClass)
+ .css({
+ zIndex: options.zIndex
+ })
+ // setting tabIndex makes the div focusable
+ // setting outline to 0 prevents a border on focus in Mozilla
+ .attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
+ if (options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
+ event.keyCode === $.ui.keyCode.ESCAPE) {
+
+ self.close(event);
+ event.preventDefault();
+ }
+ })
+ .attr({
+ role: 'dialog',
+ 'aria-labelledby': titleId
+ })
+ .mousedown(function(event) {
+ self.moveToTop(false, event);
+ }),
+
+ uiDialogContent = self.element
+ .show()
+ .removeAttr('title')
+ .addClass(
+ 'ui-dialog-content ' +
+ 'ui-widget-content')
+ .appendTo(uiDialog),
+
+ uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
+ .addClass(
+ 'ui-dialog-titlebar ' +
+ 'ui-widget-header ' +
+ 'ui-corner-all ' +
+ 'ui-helper-clearfix'
+ )
+ .prependTo(uiDialog),
+
+ uiDialogTitlebarClose = $('<a href="#"></a>')
+ .addClass(
+ 'ui-dialog-titlebar-close ' +
+ 'ui-corner-all'
+ )
+ .attr('role', 'button')
+ .hover(
+ function() {
+ uiDialogTitlebarClose.addClass('ui-state-hover');
+ },
+ function() {
+ uiDialogTitlebarClose.removeClass('ui-state-hover');
+ }
+ )
+ .focus(function() {
+ uiDialogTitlebarClose.addClass('ui-state-focus');
+ })
+ .blur(function() {
+ uiDialogTitlebarClose.removeClass('ui-state-focus');
+ })
+ .click(function(event) {
+ self.close(event);
+ return false;
+ })
+ .appendTo(uiDialogTitlebar),
+
+ uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
+ .addClass(
+ 'ui-icon ' +
+ 'ui-icon-closethick'
+ )
+ .text(options.closeText)
+ .appendTo(uiDialogTitlebarClose),
+
+ uiDialogTitle = $('<span></span>')
+ .addClass('ui-dialog-title')
+ .attr('id', titleId)
+ .html(title)
+ .prependTo(uiDialogTitlebar);
+
+ //handling of deprecated beforeclose (vs beforeClose) option
+ //Ticket #4669 http://dev.jqueryui.com/ticket/4669
+ //TODO: remove in 1.9pre
+ if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
+ options.beforeClose = options.beforeclose;
+ }
+
+ uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
+
+ if (options.draggable && $.fn.draggable) {
+ self._makeDraggable();
+ }
+ if (options.resizable && $.fn.resizable) {
+ self._makeResizable();
+ }
+
+ self._createButtons(options.buttons);
+ self._isOpen = false;
+
+ if ($.fn.bgiframe) {
+ uiDialog.bgiframe();
+ }
+ },
+
+ _init: function() {
+ if ( this.options.autoOpen ) {
+ this.open();
+ }
+ },
+
+ destroy: function() {
+ var self = this;
+
+ if (self.overlay) {
+ self.overlay.destroy();
+ }
+ self.uiDialog.hide();
+ self.element
+ .unbind('.dialog')
+ .removeData('dialog')
+ .removeClass('ui-dialog-content ui-widget-content')
+ .hide().appendTo('body');
+ self.uiDialog.remove();
+
+ if (self.originalTitle) {
+ self.element.attr('title', self.originalTitle);
+ }
+
+ return self;
+ },
+
+ widget: function() {
+ return this.uiDialog;
+ },
+
+ close: function(event) {
+ var self = this,
+ maxZ, thisZ;
+
+ if (false === self._trigger('beforeClose', event)) {
+ return;
+ }
+
+ if (self.overlay) {
+ self.overlay.destroy();
+ }
+ self.uiDialog.unbind('keypress.ui-dialog');
+
+ self._isOpen = false;
+
+ if (self.options.hide) {
+ self.uiDialog.hide(self.options.hide, function() {
+ self._trigger('close', event);
+ });
+ } else {
+ self.uiDialog.hide();
+ self._trigger('close', event);
+ }
+
+ $.ui.dialog.overlay.resize();
+
+ // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
+ if (self.options.modal) {
+ maxZ = 0;
+ $('.ui-dialog').each(function() {
+ if (this !== self.uiDialog[0]) {
+ thisZ = $(this).css('z-index');
+ if(!isNaN(thisZ)) {
+ maxZ = Math.max(maxZ, thisZ);
+ }
+ }
+ });
+ $.ui.dialog.maxZ = maxZ;
+ }
+
+ return self;
+ },
+
+ isOpen: function() {
+ return this._isOpen;
+ },
+
+ // the force parameter allows us to move modal dialogs to their correct
+ // position on open
+ moveToTop: function(force, event) {
+ var self = this,
+ options = self.options,
+ saveScroll;
+
+ if ((options.modal && !force) ||
+ (!options.stack && !options.modal)) {
+ return self._trigger('focus', event);
+ }
+
+ if (options.zIndex > $.ui.dialog.maxZ) {
+ $.ui.dialog.maxZ = options.zIndex;
+ }
+ if (self.overlay) {
+ $.ui.dialog.maxZ += 1;
+ self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
+ }
+
+ //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
+ // http://ui.jquery.com/bugs/ticket/3193
+ saveScroll = { scrollTop: self.element.scrollTop(), scrollLeft: self.element.scrollLeft() };
+ $.ui.dialog.maxZ += 1;
+ self.uiDialog.css('z-index', $.ui.dialog.maxZ);
+ self.element.attr(saveScroll);
+ self._trigger('focus', event);
+
+ return self;
+ },
+
+ open: function() {
+ if (this._isOpen) { return; }
+
+ var self = this,
+ options = self.options,
+ uiDialog = self.uiDialog;
+
+ self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
+ self._size();
+ self._position(options.position);
+ uiDialog.show(options.show);
+ self.moveToTop(true);
+
+ // prevent tabbing out of modal dialogs
+ if ( options.modal ) {
+ uiDialog.bind( "keydown.ui-dialog", function( event ) {
+ if ( event.keyCode !== $.ui.keyCode.TAB ) {
+ return;
+ }
+
+ var tabbables = $(':tabbable', this),
+ first = tabbables.filter(':first'),
+ last = tabbables.filter(':last');
+
+ if (event.target === last[0] && !event.shiftKey) {
+ first.focus(1);
+ return false;
+ } else if (event.target === first[0] && event.shiftKey) {
+ last.focus(1);
+ return false;
+ }
+ });
+ }
+
+ // set focus to the first tabbable element in the content area or the first button
+ // if there are no tabbable elements, set focus on the dialog itself
+ $(self.element.find(':tabbable').get().concat(
+ uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
+ uiDialog.get()))).eq(0).focus();
+
+ self._isOpen = true;
+ self._trigger('open');
+
+ return self;
+ },
+
+ _createButtons: function(buttons) {
+ var self = this,
+ hasButtons = false,
+ uiDialogButtonPane = $('<div></div>')
+ .addClass(
+ 'ui-dialog-buttonpane ' +
+ 'ui-widget-content ' +
+ 'ui-helper-clearfix'
+ ),
+ uiButtonSet = $( "<div></div>" )
+ .addClass( "ui-dialog-buttonset" )
+ .appendTo( uiDialogButtonPane );
+
+ // if we already have a button pane, remove it
+ self.uiDialog.find('.ui-dialog-buttonpane').remove();
+
+ if (typeof buttons === 'object' && buttons !== null) {
+ $.each(buttons, function() {
+ return !(hasButtons = true);
+ });
+ }
+ if (hasButtons) {
+ $.each(buttons, function(name, props) {
+ props = $.isFunction( props ) ?
+ { click: props, text: name } :
+ props;
+ var button = $('<button type="button"></button>')
+ .click(function() {
+ props.click.apply(self.element[0], arguments);
+ })
+ .appendTo(uiButtonSet);
+ // can't use .attr( props, true ) with jQuery 1.3.2.
+ $.each( props, function( key, value ) {
+ if ( key === "click" ) {
+ return;
+ }
+ if ( key in attrFn ) {
+ button[ key ]( value );
+ } else {
+ button.attr( key, value );
+ }
+ });
+ if ($.fn.button) {
+ button.button();
+ }
+ });
+ uiDialogButtonPane.appendTo(self.uiDialog);
+ }
+ },
+
+ _makeDraggable: function() {
+ var self = this,
+ options = self.options,
+ doc = $(document),
+ heightBeforeDrag;
+
+ function filteredUi(ui) {
+ return {
+ position: ui.position,
+ offset: ui.offset
+ };
+ }
+
+ self.uiDialog.draggable({
+ cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
+ handle: '.ui-dialog-titlebar',
+ containment: 'document',
+ start: function(event, ui) {
+ heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
+ $(this).height($(this).height()).addClass("ui-dialog-dragging");
+ self._trigger('dragStart', event, filteredUi(ui));
+ },
+ drag: function(event, ui) {
+ self._trigger('drag', event, filteredUi(ui));
+ },
+ stop: function(event, ui) {
+ options.position = [ui.position.left - doc.scrollLeft(),
+ ui.position.top - doc.scrollTop()];
+ $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
+ self._trigger('dragStop', event, filteredUi(ui));
+ $.ui.dialog.overlay.resize();
+ }
+ });
+ },
+
+ _makeResizable: function(handles) {
+ handles = (handles === undefined ? this.options.resizable : handles);
+ var self = this,
+ options = self.options,
+ // .ui-resizable has position: relative defined in the stylesheet
+ // but dialogs have to use absolute or fixed positioning
+ position = self.uiDialog.css('position'),
+ resizeHandles = (typeof handles === 'string' ?
+ handles :
+ 'n,e,s,w,se,sw,ne,nw'
+ );
+
+ function filteredUi(ui) {
+ return {
+ originalPosition: ui.originalPosition,
+ originalSize: ui.originalSize,
+ position: ui.position,
+ size: ui.size
+ };
+ }
+
+ self.uiDialog.resizable({
+ cancel: '.ui-dialog-content',
+ containment: 'document',
+ alsoResize: self.element,
+ maxWidth: options.maxWidth,
+ maxHeight: options.maxHeight,
+ minWidth: options.minWidth,
+ minHeight: self._minHeight(),
+ handles: resizeHandles,
+ start: function(event, ui) {
+ $(this).addClass("ui-dialog-resizing");
+ self._trigger('resizeStart', event, filteredUi(ui));
+ },
+ resize: function(event, ui) {
+ self._trigger('resize', event, filteredUi(ui));
+ },
+ stop: function(event, ui) {
+ $(this).removeClass("ui-dialog-resizing");
+ options.height = $(this).height();
+ options.width = $(this).width();
+ self._trigger('resizeStop', event, filteredUi(ui));
+ $.ui.dialog.overlay.resize();
+ }
+ })
+ .css('position', position)
+ .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
+ },
+
+ _minHeight: function() {
+ var options = this.options;
+
+ if (options.height === 'auto') {
+ return options.minHeight;
+ } else {
+ return Math.min(options.minHeight, options.height);
+ }
+ },
+
+ _position: function(position) {
+ var myAt = [],
+ offset = [0, 0],
+ isVisible;
+
+ if (position) {
+ // deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
+ // if (typeof position == 'string' || $.isArray(position)) {
+ // myAt = $.isArray(position) ? position : position.split(' ');
+
+ if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
+ myAt = position.split ? position.split(' ') : [position[0], position[1]];
+ if (myAt.length === 1) {
+ myAt[1] = myAt[0];
+ }
+
+ $.each(['left', 'top'], function(i, offsetPosition) {
+ if (+myAt[i] === myAt[i]) {
+ offset[i] = myAt[i];
+ myAt[i] = offsetPosition;
+ }
+ });
+
+ position = {
+ my: myAt.join(" "),
+ at: myAt.join(" "),
+ offset: offset.join(" ")
+ };
+ }
+
+ position = $.extend({}, $.ui.dialog.prototype.options.position, position);
+ } else {
+ position = $.ui.dialog.prototype.options.position;
+ }
+
+ // need to show the dialog to get the actual offset in the position plugin
+ isVisible = this.uiDialog.is(':visible');
+ if (!isVisible) {
+ this.uiDialog.show();
+ }
+ this.uiDialog
+ // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
+ .css({ top: 0, left: 0 })
+ .position($.extend({ of: window }, position));
+ if (!isVisible) {
+ this.uiDialog.hide();
+ }
+ },
+
+ _setOptions: function( options ) {
+ var self = this,
+ resizableOptions = {},
+ resize = false;
+
+ $.each( options, function( key, value ) {
+ self._setOption( key, value );
+
+ if ( key in sizeRelatedOptions ) {
+ resize = true;
+ }
+ if ( key in resizableRelatedOptions ) {
+ resizableOptions[ key ] = value;
+ }
+ });
+
+ if ( resize ) {
+ this._size();
+ }
+ if ( this.uiDialog.is( ":data(resizable)" ) ) {
+ this.uiDialog.resizable( "option", resizableOptions );
+ }
+ },
+
+ _setOption: function(key, value){
+ var self = this,
+ uiDialog = self.uiDialog;
+
+ switch (key) {
+ //handling of deprecated beforeclose (vs beforeClose) option
+ //Ticket #4669 http://dev.jqueryui.com/ticket/4669
+ //TODO: remove in 1.9pre
+ case "beforeclose":
+ key = "beforeClose";
+ break;
+ case "buttons":
+ self._createButtons(value);
+ break;
+ case "closeText":
+ // ensure that we always pass a string
+ self.uiDialogTitlebarCloseText.text("" + value);
+ break;
+ case "dialogClass":
+ uiDialog
+ .removeClass(self.options.dialogClass)
+ .addClass(uiDialogClasses + value);
+ break;
+ case "disabled":
+ if (value) {
+ uiDialog.addClass('ui-dialog-disabled');
+ } else {
+ uiDialog.removeClass('ui-dialog-disabled');
+ }
+ break;
+ case "draggable":
+ var isDraggable = uiDialog.is( ":data(draggable)" );
+ if ( isDraggable && !value ) {
+ uiDialog.draggable( "destroy" );
+ }
+
+ if ( !isDraggable && value ) {
+ self._makeDraggable();
+ }
+ break;
+ case "position":
+ self._position(value);
+ break;
+ case "resizable":
+ // currently resizable, becoming non-resizable
+ var isResizable = uiDialog.is( ":data(resizable)" );
+ if (isResizable && !value) {
+ uiDialog.resizable('destroy');
+ }
+
+ // currently resizable, changing handles
+ if (isResizable && typeof value === 'string') {
+ uiDialog.resizable('option', 'handles', value);
+ }
+
+ // currently non-resizable, becoming resizable
+ if (!isResizable && value !== false) {
+ self._makeResizable(value);
+ }
+ break;
+ case "title":
+ // convert whatever was passed in o a string, for html() to not throw up
+ $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
+ break;
+ }
+
+ $.Widget.prototype._setOption.apply(self, arguments);
+ },
+
+ _size: function() {
+ /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
+ * divs will both have width and height set, so we need to reset them
+ */
+ var options = this.options,
+ nonContentHeight,
+ minContentHeight,
+ isVisible = this.uiDialog.is( ":visible" );
+
+ // reset content sizing
+ this.element.show().css({
+ width: 'auto',
+ minHeight: 0,
+ height: 0
+ });
+
+ if (options.minWidth > options.width) {
+ options.width = options.minWidth;
+ }
+
+ // reset wrapper sizing
+ // determine the height of all the non-content elements
+ nonContentHeight = this.uiDialog.css({
+ height: 'auto',
+ width: options.width
+ })
+ .height();
+ minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
+
+ if ( options.height === "auto" ) {
+ // only needed for IE6 support
+ if ( $.support.minHeight ) {
+ this.element.css({
+ minHeight: minContentHeight,
+ height: "auto"
+ });
+ } else {
+ this.uiDialog.show();
+ var autoHeight = this.element.css( "height", "auto" ).height();
+ if ( !isVisible ) {
+ this.uiDialog.hide();
+ }
+ this.element.height( Math.max( autoHeight, minContentHeight ) );
+ }
+ } else {
+ this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
+ }
+
+ if (this.uiDialog.is(':data(resizable)')) {
+ this.uiDialog.resizable('option', 'minHeight', this._minHeight());
+ }
+ }
+});
+
+$.extend($.ui.dialog, {
+ version: "1.8.18",
+
+ uuid: 0,
+ maxZ: 0,
+
+ getTitleId: function($el) {
+ var id = $el.attr('id');
+ if (!id) {
+ this.uuid += 1;
+ id = this.uuid;
+ }
+ return 'ui-dialog-title-' + id;
+ },
+
+ overlay: function(dialog) {
+ this.$el = $.ui.dialog.overlay.create(dialog);
+ }
+});
+
+$.extend($.ui.dialog.overlay, {
+ instances: [],
+ // reuse old instances due to IE memory leak with alpha transparency (see #5185)
+ oldInstances: [],
+ maxZ: 0,
+ events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
+ function(event) { return event + '.dialog-overlay'; }).join(' '),
+ create: function(dialog) {
+ if (this.instances.length === 0) {
+ // prevent use of anchors and inputs
+ // we use a setTimeout in case the overlay is created from an
+ // event that we're going to be cancelling (see #2804)
+ setTimeout(function() {
+ // handle $(el).dialog().dialog('close') (see #4065)
+ if ($.ui.dialog.overlay.instances.length) {
+ $(document).bind($.ui.dialog.overlay.events, function(event) {
+ // stop events if the z-index of the target is < the z-index of the overlay
+ // we cannot return true when we don't want to cancel the event (#3523)
+ if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
+ return false;
+ }
+ });
+ }
+ }, 1);
+
+ // allow closing by pressing the escape key
+ $(document).bind('keydown.dialog-overlay', function(event) {
+ if (dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
+ event.keyCode === $.ui.keyCode.ESCAPE) {
+
+ dialog.close(event);
+ event.preventDefault();
+ }
+ });
+
+ // handle window resize
+ $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
+ }
+
+ var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
+ .appendTo(document.body)
+ .css({
+ width: this.width(),
+ height: this.height()
+ });
+
+ if ($.fn.bgiframe) {
+ $el.bgiframe();
+ }
+
+ this.instances.push($el);
+ return $el;
+ },
+
+ destroy: function($el) {
+ var indexOf = $.inArray($el, this.instances);
+ if (indexOf != -1){
+ this.oldInstances.push(this.instances.splice(indexOf, 1)[0]);
+ }
+
+ if (this.instances.length === 0) {
+ $([document, window]).unbind('.dialog-overlay');
+ }
+
+ $el.remove();
+
+ // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
+ var maxZ = 0;
+ $.each(this.instances, function() {
+ maxZ = Math.max(maxZ, this.css('z-index'));
+ });
+ this.maxZ = maxZ;
+ },
+
+ height: function() {
+ var scrollHeight,
+ offsetHeight;
+ // handle IE 6
+ if ($.browser.msie && $.browser.version < 7) {
+ scrollHeight = Math.max(
+ document.documentElement.scrollHeight,
+ document.body.scrollHeight
+ );
+ offsetHeight = Math.max(
+ document.documentElement.offsetHeight,
+ document.body.offsetHeight
+ );
+
+ if (scrollHeight < offsetHeight) {
+ return $(window).height() + 'px';
+ } else {
+ return scrollHeight + 'px';
+ }
+ // handle "good" browsers
+ } else {
+ return $(document).height() + 'px';
+ }
+ },
+
+ width: function() {
+ var scrollWidth,
+ offsetWidth;
+ // handle IE
+ if ( $.browser.msie ) {
+ scrollWidth = Math.max(
+ document.documentElement.scrollWidth,
+ document.body.scrollWidth
+ );
+ offsetWidth = Math.max(
+ document.documentElement.offsetWidth,
+ document.body.offsetWidth
+ );
+
+ if (scrollWidth < offsetWidth) {
+ return $(window).width() + 'px';
+ } else {
+ return scrollWidth + 'px';
+ }
+ // handle "good" browsers
+ } else {
+ return $(document).width() + 'px';
+ }
+ },
+
+ resize: function() {
+ /* If the dialog is draggable and the user drags it past the
+ * right edge of the window, the document becomes wider so we
+ * need to stretch the overlay. If the user then drags the
+ * dialog back to the left, the document will become narrower,
+ * so we need to shrink the overlay to the appropriate size.
+ * This is handled by shrinking the overlay before setting it
+ * to the full document size.
+ */
+ var $overlays = $([]);
+ $.each($.ui.dialog.overlay.instances, function() {
+ $overlays = $overlays.add(this);
+ });
+
+ $overlays.css({
+ width: 0,
+ height: 0
+ }).css({
+ width: $.ui.dialog.overlay.width(),
+ height: $.ui.dialog.overlay.height()
+ });
+ }
+});
+
+$.extend($.ui.dialog.overlay.prototype, {
+ destroy: function() {
+ $.ui.dialog.overlay.destroy(this.$el);
+ }
+});
+
+}(jQuery));
+/*
+ * jQuery UI Position 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Position
+ */
+(function( $, undefined ) {
+
+$.ui = $.ui || {};
+
+var horizontalPositions = /left|center|right/,
+ verticalPositions = /top|center|bottom/,
+ center = "center",
+ support = {},
+ _position = $.fn.position,
+ _offset = $.fn.offset;
+
+$.fn.position = function( options ) {
+ if ( !options || !options.of ) {
+ return _position.apply( this, arguments );
+ }
+
+ // make a copy, we don't want to modify arguments
+ options = $.extend( {}, options );
+
+ var target = $( options.of ),
+ targetElem = target[0],
+ collision = ( options.collision || "flip" ).split( " " ),
+ offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
+ targetWidth,
+ targetHeight,
+ basePosition;
+
+ if ( targetElem.nodeType === 9 ) {
+ targetWidth = target.width();
+ targetHeight = target.height();
+ basePosition = { top: 0, left: 0 };
+ // TODO: use $.isWindow() in 1.9
+ } else if ( targetElem.setTimeout ) {
+ targetWidth = target.width();
+ targetHeight = target.height();
+ basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
+ } else if ( targetElem.preventDefault ) {
+ // force left top to allow flipping
+ options.at = "left top";
+ targetWidth = targetHeight = 0;
+ basePosition = { top: options.of.pageY, left: options.of.pageX };
+ } else {
+ targetWidth = target.outerWidth();
+ targetHeight = target.outerHeight();
+ basePosition = target.offset();
+ }
+
+ // force my and at to have valid horizontal and veritcal positions
+ // if a value is missing or invalid, it will be converted to center
+ $.each( [ "my", "at" ], function() {
+ var pos = ( options[this] || "" ).split( " " );
+ if ( pos.length === 1) {
+ pos = horizontalPositions.test( pos[0] ) ?
+ pos.concat( [center] ) :
+ verticalPositions.test( pos[0] ) ?
+ [ center ].concat( pos ) :
+ [ center, center ];
+ }
+ pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
+ pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
+ options[ this ] = pos;
+ });
+
+ // normalize collision option
+ if ( collision.length === 1 ) {
+ collision[ 1 ] = collision[ 0 ];
+ }
+
+ // normalize offset option
+ offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
+ if ( offset.length === 1 ) {
+ offset[ 1 ] = offset[ 0 ];
+ }
+ offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
+
+ if ( options.at[0] === "right" ) {
+ basePosition.left += targetWidth;
+ } else if ( options.at[0] === center ) {
+ basePosition.left += targetWidth / 2;
+ }
+
+ if ( options.at[1] === "bottom" ) {
+ basePosition.top += targetHeight;
+ } else if ( options.at[1] === center ) {
+ basePosition.top += targetHeight / 2;
+ }
+
+ basePosition.left += offset[ 0 ];
+ basePosition.top += offset[ 1 ];
+
+ return this.each(function() {
+ var elem = $( this ),
+ elemWidth = elem.outerWidth(),
+ elemHeight = elem.outerHeight(),
+ marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
+ marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
+ collisionWidth = elemWidth + marginLeft +
+ ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ),
+ collisionHeight = elemHeight + marginTop +
+ ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ),
+ position = $.extend( {}, basePosition ),
+ collisionPosition;
+
+ if ( options.my[0] === "right" ) {
+ position.left -= elemWidth;
+ } else if ( options.my[0] === center ) {
+ position.left -= elemWidth / 2;
+ }
+
+ if ( options.my[1] === "bottom" ) {
+ position.top -= elemHeight;
+ } else if ( options.my[1] === center ) {
+ position.top -= elemHeight / 2;
+ }
+
+ // prevent fractions if jQuery version doesn't support them (see #5280)
+ if ( !support.fractions ) {
+ position.left = Math.round( position.left );
+ position.top = Math.round( position.top );
+ }
+
+ collisionPosition = {
+ left: position.left - marginLeft,
+ top: position.top - marginTop
+ };
+
+ $.each( [ "left", "top" ], function( i, dir ) {
+ if ( $.ui.position[ collision[i] ] ) {
+ $.ui.position[ collision[i] ][ dir ]( position, {
+ targetWidth: targetWidth,
+ targetHeight: targetHeight,
+ elemWidth: elemWidth,
+ elemHeight: elemHeight,
+ collisionPosition: collisionPosition,
+ collisionWidth: collisionWidth,
+ collisionHeight: collisionHeight,
+ offset: offset,
+ my: options.my,
+ at: options.at
+ });
+ }
+ });
+
+ if ( $.fn.bgiframe ) {
+ elem.bgiframe();
+ }
+ elem.offset( $.extend( position, { using: options.using } ) );
+ });
+};
+
+$.ui.position = {
+ fit: {
+ left: function( position, data ) {
+ var win = $( window ),
+ over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
+ position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
+ },
+ top: function( position, data ) {
+ var win = $( window ),
+ over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
+ position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
+ }
+ },
+
+ flip: {
+ left: function( position, data ) {
+ if ( data.at[0] === center ) {
+ return;
+ }
+ var win = $( window ),
+ over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
+ myOffset = data.my[ 0 ] === "left" ?
+ -data.elemWidth :
+ data.my[ 0 ] === "right" ?
+ data.elemWidth :
+ 0,
+ atOffset = data.at[ 0 ] === "left" ?
+ data.targetWidth :
+ -data.targetWidth,
+ offset = -2 * data.offset[ 0 ];
+ position.left += data.collisionPosition.left < 0 ?
+ myOffset + atOffset + offset :
+ over > 0 ?
+ myOffset + atOffset + offset :
+ 0;
+ },
+ top: function( position, data ) {
+ if ( data.at[1] === center ) {
+ return;
+ }
+ var win = $( window ),
+ over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
+ myOffset = data.my[ 1 ] === "top" ?
+ -data.elemHeight :
+ data.my[ 1 ] === "bottom" ?
+ data.elemHeight :
+ 0,
+ atOffset = data.at[ 1 ] === "top" ?
+ data.targetHeight :
+ -data.targetHeight,
+ offset = -2 * data.offset[ 1 ];
+ position.top += data.collisionPosition.top < 0 ?
+ myOffset + atOffset + offset :
+ over > 0 ?
+ myOffset + atOffset + offset :
+ 0;
+ }
+ }
+};
+
+// offset setter from jQuery 1.4
+if ( !$.offset.setOffset ) {
+ $.offset.setOffset = function( elem, options ) {
+ // set position first, in-case top/left are set even on static elem
+ if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
+ elem.style.position = "relative";
+ }
+ var curElem = $( elem ),
+ curOffset = curElem.offset(),
+ curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0,
+ curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0,
+ props = {
+ top: (options.top - curOffset.top) + curTop,
+ left: (options.left - curOffset.left) + curLeft
+ };
+
+ if ( 'using' in options ) {
+ options.using.call( elem, props );
+ } else {
+ curElem.css( props );
+ }
+ };
+
+ $.fn.offset = function( options ) {
+ var elem = this[ 0 ];
+ if ( !elem || !elem.ownerDocument ) { return null; }
+ if ( options ) {
+ return this.each(function() {
+ $.offset.setOffset( this, options );
+ });
+ }
+ return _offset.call( this );
+ };
+}
+
+// fraction support test (older versions of jQuery don't support fractions)
+(function () {
+ var body = document.getElementsByTagName( "body" )[ 0 ],
+ div = document.createElement( "div" ),
+ testElement, testElementParent, testElementStyle, offset, offsetTotal;
+
+ //Create a "fake body" for testing based on method used in jQuery.support
+ testElement = document.createElement( body ? "div" : "body" );
+ testElementStyle = {
+ visibility: "hidden",
+ width: 0,
+ height: 0,
+ border: 0,
+ margin: 0,
+ background: "none"
+ };
+ if ( body ) {
+ $.extend( testElementStyle, {
+ position: "absolute",
+ left: "-1000px",
+ top: "-1000px"
+ });
+ }
+ for ( var i in testElementStyle ) {
+ testElement.style[ i ] = testElementStyle[ i ];
+ }
+ testElement.appendChild( div );
+ testElementParent = body || document.documentElement;
+ testElementParent.insertBefore( testElement, testElementParent.firstChild );
+
+ div.style.cssText = "position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;";
+
+ offset = $( div ).offset( function( _, offset ) {
+ return offset;
+ }).offset();
+
+ testElement.innerHTML = "";
+ testElementParent.removeChild( testElement );
+
+ offsetTotal = offset.top + offset.left + ( body ? 2000 : 0 );
+ support.fractions = offsetTotal > 21 && offsetTotal < 22;
+})();
+
+}( jQuery ));
+/*
+ * jQuery UI Progressbar 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Progressbar
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+$.widget( "ui.progressbar", {
+ options: {
+ value: 0,
+ max: 100
+ },
+
+ min: 0,
+
+ _create: function() {
+ this.element
+ .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
+ .attr({
+ role: "progressbar",
+ "aria-valuemin": this.min,
+ "aria-valuemax": this.options.max,
+ "aria-valuenow": this._value()
+ });
+
+ this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
+ .appendTo( this.element );
+
+ this.oldValue = this._value();
+ this._refreshValue();
+ },
+
+ destroy: function() {
+ this.element
+ .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
+ .removeAttr( "role" )
+ .removeAttr( "aria-valuemin" )
+ .removeAttr( "aria-valuemax" )
+ .removeAttr( "aria-valuenow" );
+
+ this.valueDiv.remove();
+
+ $.Widget.prototype.destroy.apply( this, arguments );
+ },
+
+ value: function( newValue ) {
+ if ( newValue === undefined ) {
+ return this._value();
+ }
+
+ this._setOption( "value", newValue );
+ return this;
+ },
+
+ _setOption: function( key, value ) {
+ if ( key === "value" ) {
+ this.options.value = value;
+ this._refreshValue();
+ if ( this._value() === this.options.max ) {
+ this._trigger( "complete" );
+ }
+ }
+
+ $.Widget.prototype._setOption.apply( this, arguments );
+ },
+
+ _value: function() {
+ var val = this.options.value;
+ // normalize invalid value
+ if ( typeof val !== "number" ) {
+ val = 0;
+ }
+ return Math.min( this.options.max, Math.max( this.min, val ) );
+ },
+
+ _percentage: function() {
+ return 100 * this._value() / this.options.max;
+ },
+
+ _refreshValue: function() {
+ var value = this.value();
+ var percentage = this._percentage();
+
+ if ( this.oldValue !== value ) {
+ this.oldValue = value;
+ this._trigger( "change" );
+ }
+
+ this.valueDiv
+ .toggle( value > this.min )
+ .toggleClass( "ui-corner-right", value === this.options.max )
+ .width( percentage.toFixed(0) + "%" );
+ this.element.attr( "aria-valuenow", value );
+ }
+});
+
+$.extend( $.ui.progressbar, {
+ version: "1.8.18"
+});
+
+})( jQuery );
+/*
+ * jQuery UI Slider 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Slider
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+// number of pages in a slider
+// (how many times can you page up/down to go through the whole range)
+var numPages = 5;
+
+$.widget( "ui.slider", $.ui.mouse, {
+
+ widgetEventPrefix: "slide",
+
+ options: {
+ animate: false,
+ distance: 0,
+ max: 100,
+ min: 0,
+ orientation: "horizontal",
+ range: false,
+ step: 1,
+ value: 0,
+ values: null
+ },
+
+ _create: function() {
+ var self = this,
+ o = this.options,
+ existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
+ handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
+ handleCount = ( o.values && o.values.length ) || 1,
+ handles = [];
+
+ this._keySliding = false;
+ this._mouseSliding = false;
+ this._animateOff = true;
+ this._handleIndex = null;
+ this._detectOrientation();
+ this._mouseInit();
+
+ this.element
+ .addClass( "ui-slider" +
+ " ui-slider-" + this.orientation +
+ " ui-widget" +
+ " ui-widget-content" +
+ " ui-corner-all" +
+ ( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) );
+
+ this.range = $([]);
+
+ if ( o.range ) {
+ if ( o.range === true ) {
+ if ( !o.values ) {
+ o.values = [ this._valueMin(), this._valueMin() ];
+ }
+ if ( o.values.length && o.values.length !== 2 ) {
+ o.values = [ o.values[0], o.values[0] ];
+ }
+ }
+
+ this.range = $( "<div></div>" )
+ .appendTo( this.element )
+ .addClass( "ui-slider-range" +
+ // note: this isn't the most fittingly semantic framework class for this element,
+ // but worked best visually with a variety of themes
+ " ui-widget-header" +
+ ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) );
+ }
+
+ for ( var i = existingHandles.length; i < handleCount; i += 1 ) {
+ handles.push( handle );
+ }
+
+ this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( self.element ) );
+
+ this.handle = this.handles.eq( 0 );
+
+ this.handles.add( this.range ).filter( "a" )
+ .click(function( event ) {
+ event.preventDefault();
+ })
+ .hover(function() {
+ if ( !o.disabled ) {
+ $( this ).addClass( "ui-state-hover" );
+ }
+ }, function() {
+ $( this ).removeClass( "ui-state-hover" );
+ })
+ .focus(function() {
+ if ( !o.disabled ) {
+ $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
+ $( this ).addClass( "ui-state-focus" );
+ } else {
+ $( this ).blur();
+ }
+ })
+ .blur(function() {
+ $( this ).removeClass( "ui-state-focus" );
+ });
+
+ this.handles.each(function( i ) {
+ $( this ).data( "index.ui-slider-handle", i );
+ });
+
+ this.handles
+ .keydown(function( event ) {
+ var index = $( this ).data( "index.ui-slider-handle" ),
+ allowed,
+ curVal,
+ newVal,
+ step;
+
+ if ( self.options.disabled ) {
+ return;
+ }
+
+ switch ( event.keyCode ) {
+ case $.ui.keyCode.HOME:
+ case $.ui.keyCode.END:
+ case $.ui.keyCode.PAGE_UP:
+ case $.ui.keyCode.PAGE_DOWN:
+ case $.ui.keyCode.UP:
+ case $.ui.keyCode.RIGHT:
+ case $.ui.keyCode.DOWN:
+ case $.ui.keyCode.LEFT:
+ event.preventDefault();
+ if ( !self._keySliding ) {
+ self._keySliding = true;
+ $( this ).addClass( "ui-state-active" );
+ allowed = self._start( event, index );
+ if ( allowed === false ) {
+ return;
+ }
+ }
+ break;
+ }
+
+ step = self.options.step;
+ if ( self.options.values && self.options.values.length ) {
+ curVal = newVal = self.values( index );
+ } else {
+ curVal = newVal = self.value();
+ }
+
+ switch ( event.keyCode ) {
+ case $.ui.keyCode.HOME:
+ newVal = self._valueMin();
+ break;
+ case $.ui.keyCode.END:
+ newVal = self._valueMax();
+ break;
+ case $.ui.keyCode.PAGE_UP:
+ newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
+ break;
+ case $.ui.keyCode.PAGE_DOWN:
+ newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
+ break;
+ case $.ui.keyCode.UP:
+ case $.ui.keyCode.RIGHT:
+ if ( curVal === self._valueMax() ) {
+ return;
+ }
+ newVal = self._trimAlignValue( curVal + step );
+ break;
+ case $.ui.keyCode.DOWN:
+ case $.ui.keyCode.LEFT:
+ if ( curVal === self._valueMin() ) {
+ return;
+ }
+ newVal = self._trimAlignValue( curVal - step );
+ break;
+ }
+
+ self._slide( event, index, newVal );
+ })
+ .keyup(function( event ) {
+ var index = $( this ).data( "index.ui-slider-handle" );
+
+ if ( self._keySliding ) {
+ self._keySliding = false;
+ self._stop( event, index );
+ self._change( event, index );
+ $( this ).removeClass( "ui-state-active" );
+ }
+
+ });
+
+ this._refreshValue();
+
+ this._animateOff = false;
+ },
+
+ destroy: function() {
+ this.handles.remove();
+ this.range.remove();
+
+ this.element
+ .removeClass( "ui-slider" +
+ " ui-slider-horizontal" +
+ " ui-slider-vertical" +
+ " ui-slider-disabled" +
+ " ui-widget" +
+ " ui-widget-content" +
+ " ui-corner-all" )
+ .removeData( "slider" )
+ .unbind( ".slider" );
+
+ this._mouseDestroy();
+
+ return this;
+ },
+
+ _mouseCapture: function( event ) {
+ var o = this.options,
+ position,
+ normValue,
+ distance,
+ closestHandle,
+ self,
+ index,
+ allowed,
+ offset,
+ mouseOverHandle;
+
+ if ( o.disabled ) {
+ return false;
+ }
+
+ this.elementSize = {
+ width: this.element.outerWidth(),
+ height: this.element.outerHeight()
+ };
+ this.elementOffset = this.element.offset();
+
+ position = { x: event.pageX, y: event.pageY };
+ normValue = this._normValueFromMouse( position );
+ distance = this._valueMax() - this._valueMin() + 1;
+ self = this;
+ this.handles.each(function( i ) {
+ var thisDistance = Math.abs( normValue - self.values(i) );
+ if ( distance > thisDistance ) {
+ distance = thisDistance;
+ closestHandle = $( this );
+ index = i;
+ }
+ });
+
+ // workaround for bug #3736 (if both handles of a range are at 0,
+ // the first is always used as the one with least distance,
+ // and moving it is obviously prevented by preventing negative ranges)
+ if( o.range === true && this.values(1) === o.min ) {
+ index += 1;
+ closestHandle = $( this.handles[index] );
+ }
+
+ allowed = this._start( event, index );
+ if ( allowed === false ) {
+ return false;
+ }
+ this._mouseSliding = true;
+
+ self._handleIndex = index;
+
+ closestHandle
+ .addClass( "ui-state-active" )
+ .focus();
+
+ offset = closestHandle.offset();
+ mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
+ this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
+ left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
+ top: event.pageY - offset.top -
+ ( closestHandle.height() / 2 ) -
+ ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
+ ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
+ ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
+ };
+
+ if ( !this.handles.hasClass( "ui-state-hover" ) ) {
+ this._slide( event, index, normValue );
+ }
+ this._animateOff = true;
+ return true;
+ },
+
+ _mouseStart: function( event ) {
+ return true;
+ },
+
+ _mouseDrag: function( event ) {
+ var position = { x: event.pageX, y: event.pageY },
+ normValue = this._normValueFromMouse( position );
+
+ this._slide( event, this._handleIndex, normValue );
+
+ return false;
+ },
+
+ _mouseStop: function( event ) {
+ this.handles.removeClass( "ui-state-active" );
+ this._mouseSliding = false;
+
+ this._stop( event, this._handleIndex );
+ this._change( event, this._handleIndex );
+
+ this._handleIndex = null;
+ this._clickOffset = null;
+ this._animateOff = false;
+
+ return false;
+ },
+
+ _detectOrientation: function() {
+ this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
+ },
+
+ _normValueFromMouse: function( position ) {
+ var pixelTotal,
+ pixelMouse,
+ percentMouse,
+ valueTotal,
+ valueMouse;
+
+ if ( this.orientation === "horizontal" ) {
+ pixelTotal = this.elementSize.width;
+ pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
+ } else {
+ pixelTotal = this.elementSize.height;
+ pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
+ }
+
+ percentMouse = ( pixelMouse / pixelTotal );
+ if ( percentMouse > 1 ) {
+ percentMouse = 1;
+ }
+ if ( percentMouse < 0 ) {
+ percentMouse = 0;
+ }
+ if ( this.orientation === "vertical" ) {
+ percentMouse = 1 - percentMouse;
+ }
+
+ valueTotal = this._valueMax() - this._valueMin();
+ valueMouse = this._valueMin() + percentMouse * valueTotal;
+
+ return this._trimAlignValue( valueMouse );
+ },
+
+ _start: function( event, index ) {
+ var uiHash = {
+ handle: this.handles[ index ],
+ value: this.value()
+ };
+ if ( this.options.values && this.options.values.length ) {
+ uiHash.value = this.values( index );
+ uiHash.values = this.values();
+ }
+ return this._trigger( "start", event, uiHash );
+ },
+
+ _slide: function( event, index, newVal ) {
+ var otherVal,
+ newValues,
+ allowed;
+
+ if ( this.options.values && this.options.values.length ) {
+ otherVal = this.values( index ? 0 : 1 );
+
+ if ( ( this.options.values.length === 2 && this.options.range === true ) &&
+ ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
+ ) {
+ newVal = otherVal;
+ }
+
+ if ( newVal !== this.values( index ) ) {
+ newValues = this.values();
+ newValues[ index ] = newVal;
+ // A slide can be canceled by returning false from the slide callback
+ allowed = this._trigger( "slide", event, {
+ handle: this.handles[ index ],
+ value: newVal,
+ values: newValues
+ } );
+ otherVal = this.values( index ? 0 : 1 );
+ if ( allowed !== false ) {
+ this.values( index, newVal, true );
+ }
+ }
+ } else {
+ if ( newVal !== this.value() ) {
+ // A slide can be canceled by returning false from the slide callback
+ allowed = this._trigger( "slide", event, {
+ handle: this.handles[ index ],
+ value: newVal
+ } );
+ if ( allowed !== false ) {
+ this.value( newVal );
+ }
+ }
+ }
+ },
+
+ _stop: function( event, index ) {
+ var uiHash = {
+ handle: this.handles[ index ],
+ value: this.value()
+ };
+ if ( this.options.values && this.options.values.length ) {
+ uiHash.value = this.values( index );
+ uiHash.values = this.values();
+ }
+
+ this._trigger( "stop", event, uiHash );
+ },
+
+ _change: function( event, index ) {
+ if ( !this._keySliding && !this._mouseSliding ) {
+ var uiHash = {
+ handle: this.handles[ index ],
+ value: this.value()
+ };
+ if ( this.options.values && this.options.values.length ) {
+ uiHash.value = this.values( index );
+ uiHash.values = this.values();
+ }
+
+ this._trigger( "change", event, uiHash );
+ }
+ },
+
+ value: function( newValue ) {
+ if ( arguments.length ) {
+ this.options.value = this._trimAlignValue( newValue );
+ this._refreshValue();
+ this._change( null, 0 );
+ return;
+ }
+
+ return this._value();
+ },
+
+ values: function( index, newValue ) {
+ var vals,
+ newValues,
+ i;
+
+ if ( arguments.length > 1 ) {
+ this.options.values[ index ] = this._trimAlignValue( newValue );
+ this._refreshValue();
+ this._change( null, index );
+ return;
+ }
+
+ if ( arguments.length ) {
+ if ( $.isArray( arguments[ 0 ] ) ) {
+ vals = this.options.values;
+ newValues = arguments[ 0 ];
+ for ( i = 0; i < vals.length; i += 1 ) {
+ vals[ i ] = this._trimAlignValue( newValues[ i ] );
+ this._change( null, i );
+ }
+ this._refreshValue();
+ } else {
+ if ( this.options.values && this.options.values.length ) {
+ return this._values( index );
+ } else {
+ return this.value();
+ }
+ }
+ } else {
+ return this._values();
+ }
+ },
+
+ _setOption: function( key, value ) {
+ var i,
+ valsLength = 0;
+
+ if ( $.isArray( this.options.values ) ) {
+ valsLength = this.options.values.length;
+ }
+
+ $.Widget.prototype._setOption.apply( this, arguments );
+
+ switch ( key ) {
+ case "disabled":
+ if ( value ) {
+ this.handles.filter( ".ui-state-focus" ).blur();
+ this.handles.removeClass( "ui-state-hover" );
+ this.handles.propAttr( "disabled", true );
+ this.element.addClass( "ui-disabled" );
+ } else {
+ this.handles.propAttr( "disabled", false );
+ this.element.removeClass( "ui-disabled" );
+ }
+ break;
+ case "orientation":
+ this._detectOrientation();
+ this.element
+ .removeClass( "ui-slider-horizontal ui-slider-vertical" )
+ .addClass( "ui-slider-" + this.orientation );
+ this._refreshValue();
+ break;
+ case "value":
+ this._animateOff = true;
+ this._refreshValue();
+ this._change( null, 0 );
+ this._animateOff = false;
+ break;
+ case "values":
+ this._animateOff = true;
+ this._refreshValue();
+ for ( i = 0; i < valsLength; i += 1 ) {
+ this._change( null, i );
+ }
+ this._animateOff = false;
+ break;
+ }
+ },
+
+ //internal value getter
+ // _value() returns value trimmed by min and max, aligned by step
+ _value: function() {
+ var val = this.options.value;
+ val = this._trimAlignValue( val );
+
+ return val;
+ },
+
+ //internal values getter
+ // _values() returns array of values trimmed by min and max, aligned by step
+ // _values( index ) returns single value trimmed by min and max, aligned by step
+ _values: function( index ) {
+ var val,
+ vals,
+ i;
+
+ if ( arguments.length ) {
+ val = this.options.values[ index ];
+ val = this._trimAlignValue( val );
+
+ return val;
+ } else {
+ // .slice() creates a copy of the array
+ // this copy gets trimmed by min and max and then returned
+ vals = this.options.values.slice();
+ for ( i = 0; i < vals.length; i+= 1) {
+ vals[ i ] = this._trimAlignValue( vals[ i ] );
+ }
+
+ return vals;
+ }
+ },
+
+ // returns the step-aligned value that val is closest to, between (inclusive) min and max
+ _trimAlignValue: function( val ) {
+ if ( val <= this._valueMin() ) {
+ return this._valueMin();
+ }
+ if ( val >= this._valueMax() ) {
+ return this._valueMax();
+ }
+ var step = ( this.options.step > 0 ) ? this.options.step : 1,
+ valModStep = (val - this._valueMin()) % step,
+ alignValue = val - valModStep;
+
+ if ( Math.abs(valModStep) * 2 >= step ) {
+ alignValue += ( valModStep > 0 ) ? step : ( -step );
+ }
+
+ // Since JavaScript has problems with large floats, round
+ // the final value to 5 digits after the decimal point (see #4124)
+ return parseFloat( alignValue.toFixed(5) );
+ },
+
+ _valueMin: function() {
+ return this.options.min;
+ },
+
+ _valueMax: function() {
+ return this.options.max;
+ },
+
+ _refreshValue: function() {
+ var oRange = this.options.range,
+ o = this.options,
+ self = this,
+ animate = ( !this._animateOff ) ? o.animate : false,
+ valPercent,
+ _set = {},
+ lastValPercent,
+ value,
+ valueMin,
+ valueMax;
+
+ if ( this.options.values && this.options.values.length ) {
+ this.handles.each(function( i, j ) {
+ valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
+ _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
+ $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
+ if ( self.options.range === true ) {
+ if ( self.orientation === "horizontal" ) {
+ if ( i === 0 ) {
+ self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
+ }
+ if ( i === 1 ) {
+ self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
+ }
+ } else {
+ if ( i === 0 ) {
+ self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
+ }
+ if ( i === 1 ) {
+ self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
+ }
+ }
+ }
+ lastValPercent = valPercent;
+ });
+ } else {
+ value = this.value();
+ valueMin = this._valueMin();
+ valueMax = this._valueMax();
+ valPercent = ( valueMax !== valueMin ) ?
+ ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
+ 0;
+ _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
+ this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
+
+ if ( oRange === "min" && this.orientation === "horizontal" ) {
+ this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
+ }
+ if ( oRange === "max" && this.orientation === "horizontal" ) {
+ this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
+ }
+ if ( oRange === "min" && this.orientation === "vertical" ) {
+ this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
+ }
+ if ( oRange === "max" && this.orientation === "vertical" ) {
+ this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
+ }
+ }
+ }
+
+});
+
+$.extend( $.ui.slider, {
+ version: "1.8.18"
+});
+
+}(jQuery));
+/*
+ * jQuery UI Tabs 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Tabs
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+var tabId = 0,
+ listId = 0;
+
+function getNextTabId() {
+ return ++tabId;
+}
+
+function getNextListId() {
+ return ++listId;
+}
+
+$.widget( "ui.tabs", {
+ options: {
+ add: null,
+ ajaxOptions: null,
+ cache: false,
+ cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
+ collapsible: false,
+ disable: null,
+ disabled: [],
+ enable: null,
+ event: "click",
+ fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
+ idPrefix: "ui-tabs-",
+ load: null,
+ panelTemplate: "<div></div>",
+ remove: null,
+ select: null,
+ show: null,
+ spinner: "<em>Loading&#8230;</em>",
+ tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
+ },
+
+ _create: function() {
+ this._tabify( true );
+ },
+
+ _setOption: function( key, value ) {
+ if ( key == "selected" ) {
+ if (this.options.collapsible && value == this.options.selected ) {
+ return;
+ }
+ this.select( value );
+ } else {
+ this.options[ key ] = value;
+ this._tabify();
+ }
+ },
+
+ _tabId: function( a ) {
+ return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
+ this.options.idPrefix + getNextTabId();
+ },
+
+ _sanitizeSelector: function( hash ) {
+ // we need this because an id may contain a ":"
+ return hash.replace( /:/g, "\\:" );
+ },
+
+ _cookie: function() {
+ var cookie = this.cookie ||
+ ( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
+ return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
+ },
+
+ _ui: function( tab, panel ) {
+ return {
+ tab: tab,
+ panel: panel,
+ index: this.anchors.index( tab )
+ };
+ },
+
+ _cleanup: function() {
+ // restore all former loading tabs labels
+ this.lis.filter( ".ui-state-processing" )
+ .removeClass( "ui-state-processing" )
+ .find( "span:data(label.tabs)" )
+ .each(function() {
+ var el = $( this );
+ el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
+ });
+ },
+
+ _tabify: function( init ) {
+ var self = this,
+ o = this.options,
+ fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
+
+ this.list = this.element.find( "ol,ul" ).eq( 0 );
+ this.lis = $( " > li:has(a[href])", this.list );
+ this.anchors = this.lis.map(function() {
+ return $( "a", this )[ 0 ];
+ });
+ this.panels = $( [] );
+
+ this.anchors.each(function( i, a ) {
+ var href = $( a ).attr( "href" );
+ // For dynamically created HTML that contains a hash as href IE < 8 expands
+ // such href to the full page url with hash and then misinterprets tab as ajax.
+ // Same consideration applies for an added tab with a fragment identifier
+ // since a[href=#fragment-identifier] does unexpectedly not match.
+ // Thus normalize href attribute...
+ var hrefBase = href.split( "#" )[ 0 ],
+ baseEl;
+ if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
+ ( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
+ href = a.hash;
+ a.href = href;
+ }
+
+ // inline tab
+ if ( fragmentId.test( href ) ) {
+ self.panels = self.panels.add( self.element.find( self._sanitizeSelector( href ) ) );
+ // remote tab
+ // prevent loading the page itself if href is just "#"
+ } else if ( href && href !== "#" ) {
+ // required for restore on destroy
+ $.data( a, "href.tabs", href );
+
+ // TODO until #3808 is fixed strip fragment identifier from url
+ // (IE fails to load from such url)
+ $.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
+
+ var id = self._tabId( a );
+ a.href = "#" + id;
+ var $panel = self.element.find( "#" + id );
+ if ( !$panel.length ) {
+ $panel = $( o.panelTemplate )
+ .attr( "id", id )
+ .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
+ .insertAfter( self.panels[ i - 1 ] || self.list );
+ $panel.data( "destroy.tabs", true );
+ }
+ self.panels = self.panels.add( $panel );
+ // invalid tab href
+ } else {
+ o.disabled.push( i );
+ }
+ });
+
+ // initialization from scratch
+ if ( init ) {
+ // attach necessary classes for styling
+ this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
+ this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
+ this.lis.addClass( "ui-state-default ui-corner-top" );
+ this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
+
+ // Selected tab
+ // use "selected" option or try to retrieve:
+ // 1. from fragment identifier in url
+ // 2. from cookie
+ // 3. from selected class attribute on <li>
+ if ( o.selected === undefined ) {
+ if ( location.hash ) {
+ this.anchors.each(function( i, a ) {
+ if ( a.hash == location.hash ) {
+ o.selected = i;
+ return false;
+ }
+ });
+ }
+ if ( typeof o.selected !== "number" && o.cookie ) {
+ o.selected = parseInt( self._cookie(), 10 );
+ }
+ if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
+ o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
+ }
+ o.selected = o.selected || ( this.lis.length ? 0 : -1 );
+ } else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
+ o.selected = -1;
+ }
+
+ // sanity check - default to first tab...
+ o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
+ ? o.selected
+ : 0;
+
+ // Take disabling tabs via class attribute from HTML
+ // into account and update option properly.
+ // A selected tab cannot become disabled.
+ o.disabled = $.unique( o.disabled.concat(
+ $.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
+ return self.lis.index( n );
+ })
+ ) ).sort();
+
+ if ( $.inArray( o.selected, o.disabled ) != -1 ) {
+ o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
+ }
+
+ // highlight selected tab
+ this.panels.addClass( "ui-tabs-hide" );
+ this.lis.removeClass( "ui-tabs-selected ui-state-active" );
+ // check for length avoids error when initializing empty list
+ if ( o.selected >= 0 && this.anchors.length ) {
+ self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
+ this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
+
+ // seems to be expected behavior that the show callback is fired
+ self.element.queue( "tabs", function() {
+ self._trigger( "show", null,
+ self._ui( self.anchors[ o.selected ], self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) )[ 0 ] ) );
+ });
+
+ this.load( o.selected );
+ }
+
+ // clean up to avoid memory leaks in certain versions of IE 6
+ // TODO: namespace this event
+ $( window ).bind( "unload", function() {
+ self.lis.add( self.anchors ).unbind( ".tabs" );
+ self.lis = self.anchors = self.panels = null;
+ });
+ // update selected after add/remove
+ } else {
+ o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
+ }
+
+ // update collapsible
+ // TODO: use .toggleClass()
+ this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
+
+ // set or update cookie after init and add/remove respectively
+ if ( o.cookie ) {
+ this._cookie( o.selected, o.cookie );
+ }
+
+ // disable tabs
+ for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
+ $( li )[ $.inArray( i, o.disabled ) != -1 &&
+ // TODO: use .toggleClass()
+ !$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
+ }
+
+ // reset cache if switching from cached to not cached
+ if ( o.cache === false ) {
+ this.anchors.removeData( "cache.tabs" );
+ }
+
+ // remove all handlers before, tabify may run on existing tabs after add or option change
+ this.lis.add( this.anchors ).unbind( ".tabs" );
+
+ if ( o.event !== "mouseover" ) {
+ var addState = function( state, el ) {
+ if ( el.is( ":not(.ui-state-disabled)" ) ) {
+ el.addClass( "ui-state-" + state );
+ }
+ };
+ var removeState = function( state, el ) {
+ el.removeClass( "ui-state-" + state );
+ };
+ this.lis.bind( "mouseover.tabs" , function() {
+ addState( "hover", $( this ) );
+ });
+ this.lis.bind( "mouseout.tabs", function() {
+ removeState( "hover", $( this ) );
+ });
+ this.anchors.bind( "focus.tabs", function() {
+ addState( "focus", $( this ).closest( "li" ) );
+ });
+ this.anchors.bind( "blur.tabs", function() {
+ removeState( "focus", $( this ).closest( "li" ) );
+ });
+ }
+
+ // set up animations
+ var hideFx, showFx;
+ if ( o.fx ) {
+ if ( $.isArray( o.fx ) ) {
+ hideFx = o.fx[ 0 ];
+ showFx = o.fx[ 1 ];
+ } else {
+ hideFx = showFx = o.fx;
+ }
+ }
+
+ // Reset certain styles left over from animation
+ // and prevent IE's ClearType bug...
+ function resetStyle( $el, fx ) {
+ $el.css( "display", "" );
+ if ( !$.support.opacity && fx.opacity ) {
+ $el[ 0 ].style.removeAttribute( "filter" );
+ }
+ }
+
+ // Show a tab...
+ var showTab = showFx
+ ? function( clicked, $show ) {
+ $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
+ $show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
+ .animate( showFx, showFx.duration || "normal", function() {
+ resetStyle( $show, showFx );
+ self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
+ });
+ }
+ : function( clicked, $show ) {
+ $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
+ $show.removeClass( "ui-tabs-hide" );
+ self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
+ };
+
+ // Hide a tab, $show is optional...
+ var hideTab = hideFx
+ ? function( clicked, $hide ) {
+ $hide.animate( hideFx, hideFx.duration || "normal", function() {
+ self.lis.removeClass( "ui-tabs-selected ui-state-active" );
+ $hide.addClass( "ui-tabs-hide" );
+ resetStyle( $hide, hideFx );
+ self.element.dequeue( "tabs" );
+ });
+ }
+ : function( clicked, $hide, $show ) {
+ self.lis.removeClass( "ui-tabs-selected ui-state-active" );
+ $hide.addClass( "ui-tabs-hide" );
+ self.element.dequeue( "tabs" );
+ };
+
+ // attach tab event handler, unbind to avoid duplicates from former tabifying...
+ this.anchors.bind( o.event + ".tabs", function() {
+ var el = this,
+ $li = $(el).closest( "li" ),
+ $hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
+ $show = self.element.find( self._sanitizeSelector( el.hash ) );
+
+ // If tab is already selected and not collapsible or tab disabled or
+ // or is already loading or click callback returns false stop here.
+ // Check if click handler returns false last so that it is not executed
+ // for a disabled or loading tab!
+ if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
+ $li.hasClass( "ui-state-disabled" ) ||
+ $li.hasClass( "ui-state-processing" ) ||
+ self.panels.filter( ":animated" ).length ||
+ self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
+ this.blur();
+ return false;
+ }
+
+ o.selected = self.anchors.index( this );
+
+ self.abort();
+
+ // if tab may be closed
+ if ( o.collapsible ) {
+ if ( $li.hasClass( "ui-tabs-selected" ) ) {
+ o.selected = -1;
+
+ if ( o.cookie ) {
+ self._cookie( o.selected, o.cookie );
+ }
+
+ self.element.queue( "tabs", function() {
+ hideTab( el, $hide );
+ }).dequeue( "tabs" );
+
+ this.blur();
+ return false;
+ } else if ( !$hide.length ) {
+ if ( o.cookie ) {
+ self._cookie( o.selected, o.cookie );
+ }
+
+ self.element.queue( "tabs", function() {
+ showTab( el, $show );
+ });
+
+ // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
+ self.load( self.anchors.index( this ) );
+
+ this.blur();
+ return false;
+ }
+ }
+
+ if ( o.cookie ) {
+ self._cookie( o.selected, o.cookie );
+ }
+
+ // show new tab
+ if ( $show.length ) {
+ if ( $hide.length ) {
+ self.element.queue( "tabs", function() {
+ hideTab( el, $hide );
+ });
+ }
+ self.element.queue( "tabs", function() {
+ showTab( el, $show );
+ });
+
+ self.load( self.anchors.index( this ) );
+ } else {
+ throw "jQuery UI Tabs: Mismatching fragment identifier.";
+ }
+
+ // Prevent IE from keeping other link focussed when using the back button
+ // and remove dotted border from clicked link. This is controlled via CSS
+ // in modern browsers; blur() removes focus from address bar in Firefox
+ // which can become a usability and annoying problem with tabs('rotate').
+ if ( $.browser.msie ) {
+ this.blur();
+ }
+ });
+
+ // disable click in any case
+ this.anchors.bind( "click.tabs", function(){
+ return false;
+ });
+ },
+
+ _getIndex: function( index ) {
+ // meta-function to give users option to provide a href string instead of a numerical index.
+ // also sanitizes numerical indexes to valid values.
+ if ( typeof index == "string" ) {
+ index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
+ }
+
+ return index;
+ },
+
+ destroy: function() {
+ var o = this.options;
+
+ this.abort();
+
+ this.element
+ .unbind( ".tabs" )
+ .removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
+ .removeData( "tabs" );
+
+ this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
+
+ this.anchors.each(function() {
+ var href = $.data( this, "href.tabs" );
+ if ( href ) {
+ this.href = href;
+ }
+ var $this = $( this ).unbind( ".tabs" );
+ $.each( [ "href", "load", "cache" ], function( i, prefix ) {
+ $this.removeData( prefix + ".tabs" );
+ });
+ });
+
+ this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
+ if ( $.data( this, "destroy.tabs" ) ) {
+ $( this ).remove();
+ } else {
+ $( this ).removeClass([
+ "ui-state-default",
+ "ui-corner-top",
+ "ui-tabs-selected",
+ "ui-state-active",
+ "ui-state-hover",
+ "ui-state-focus",
+ "ui-state-disabled",
+ "ui-tabs-panel",
+ "ui-widget-content",
+ "ui-corner-bottom",
+ "ui-tabs-hide"
+ ].join( " " ) );
+ }
+ });
+
+ if ( o.cookie ) {
+ this._cookie( null, o.cookie );
+ }
+
+ return this;
+ },
+
+ add: function( url, label, index ) {
+ if ( index === undefined ) {
+ index = this.anchors.length;
+ }
+
+ var self = this,
+ o = this.options,
+ $li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
+ id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
+
+ $li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
+
+ // try to find an existing element before creating a new one
+ var $panel = self.element.find( "#" + id );
+ if ( !$panel.length ) {
+ $panel = $( o.panelTemplate )
+ .attr( "id", id )
+ .data( "destroy.tabs", true );
+ }
+ $panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
+
+ if ( index >= this.lis.length ) {
+ $li.appendTo( this.list );
+ $panel.appendTo( this.list[ 0 ].parentNode );
+ } else {
+ $li.insertBefore( this.lis[ index ] );
+ $panel.insertBefore( this.panels[ index ] );
+ }
+
+ o.disabled = $.map( o.disabled, function( n, i ) {
+ return n >= index ? ++n : n;
+ });
+
+ this._tabify();
+
+ if ( this.anchors.length == 1 ) {
+ o.selected = 0;
+ $li.addClass( "ui-tabs-selected ui-state-active" );
+ $panel.removeClass( "ui-tabs-hide" );
+ this.element.queue( "tabs", function() {
+ self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
+ });
+
+ this.load( 0 );
+ }
+
+ this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
+ return this;
+ },
+
+ remove: function( index ) {
+ index = this._getIndex( index );
+ var o = this.options,
+ $li = this.lis.eq( index ).remove(),
+ $panel = this.panels.eq( index ).remove();
+
+ // If selected tab was removed focus tab to the right or
+ // in case the last tab was removed the tab to the left.
+ if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
+ this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
+ }
+
+ o.disabled = $.map(
+ $.grep( o.disabled, function(n, i) {
+ return n != index;
+ }),
+ function( n, i ) {
+ return n >= index ? --n : n;
+ });
+
+ this._tabify();
+
+ this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
+ return this;
+ },
+
+ enable: function( index ) {
+ index = this._getIndex( index );
+ var o = this.options;
+ if ( $.inArray( index, o.disabled ) == -1 ) {
+ return;
+ }
+
+ this.lis.eq( index ).removeClass( "ui-state-disabled" );
+ o.disabled = $.grep( o.disabled, function( n, i ) {
+ return n != index;
+ });
+
+ this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
+ return this;
+ },
+
+ disable: function( index ) {
+ index = this._getIndex( index );
+ var self = this, o = this.options;
+ // cannot disable already selected tab
+ if ( index != o.selected ) {
+ this.lis.eq( index ).addClass( "ui-state-disabled" );
+
+ o.disabled.push( index );
+ o.disabled.sort();
+
+ this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
+ }
+
+ return this;
+ },
+
+ select: function( index ) {
+ index = this._getIndex( index );
+ if ( index == -1 ) {
+ if ( this.options.collapsible && this.options.selected != -1 ) {
+ index = this.options.selected;
+ } else {
+ return this;
+ }
+ }
+ this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
+ return this;
+ },
+
+ load: function( index ) {
+ index = this._getIndex( index );
+ var self = this,
+ o = this.options,
+ a = this.anchors.eq( index )[ 0 ],
+ url = $.data( a, "load.tabs" );
+
+ this.abort();
+
+ // not remote or from cache
+ if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
+ this.element.dequeue( "tabs" );
+ return;
+ }
+
+ // load remote from here on
+ this.lis.eq( index ).addClass( "ui-state-processing" );
+
+ if ( o.spinner ) {
+ var span = $( "span", a );
+ span.data( "label.tabs", span.html() ).html( o.spinner );
+ }
+
+ this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
+ url: url,
+ success: function( r, s ) {
+ self.element.find( self._sanitizeSelector( a.hash ) ).html( r );
+
+ // take care of tab labels
+ self._cleanup();
+
+ if ( o.cache ) {
+ $.data( a, "cache.tabs", true );
+ }
+
+ self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
+ try {
+ o.ajaxOptions.success( r, s );
+ }
+ catch ( e ) {}
+ },
+ error: function( xhr, s, e ) {
+ // take care of tab labels
+ self._cleanup();
+
+ self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
+ try {
+ // Passing index avoid a race condition when this method is
+ // called after the user has selected another tab.
+ // Pass the anchor that initiated this request allows
+ // loadError to manipulate the tab content panel via $(a.hash)
+ o.ajaxOptions.error( xhr, s, index, a );
+ }
+ catch ( e ) {}
+ }
+ } ) );
+
+ // last, so that load event is fired before show...
+ self.element.dequeue( "tabs" );
+
+ return this;
+ },
+
+ abort: function() {
+ // stop possibly running animations
+ this.element.queue( [] );
+ this.panels.stop( false, true );
+
+ // "tabs" queue must not contain more than two elements,
+ // which are the callbacks for the latest clicked tab...
+ this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
+
+ // terminate pending requests from other tabs
+ if ( this.xhr ) {
+ this.xhr.abort();
+ delete this.xhr;
+ }
+
+ // take care of tab labels
+ this._cleanup();
+ return this;
+ },
+
+ url: function( index, url ) {
+ this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
+ return this;
+ },
+
+ length: function() {
+ return this.anchors.length;
+ }
+});
+
+$.extend( $.ui.tabs, {
+ version: "1.8.18"
+});
+
+/*
+ * Tabs Extensions
+ */
+
+/*
+ * Rotate
+ */
+$.extend( $.ui.tabs.prototype, {
+ rotation: null,
+ rotate: function( ms, continuing ) {
+ var self = this,
+ o = this.options;
+
+ var rotate = self._rotate || ( self._rotate = function( e ) {
+ clearTimeout( self.rotation );
+ self.rotation = setTimeout(function() {
+ var t = o.selected;
+ self.select( ++t < self.anchors.length ? t : 0 );
+ }, ms );
+
+ if ( e ) {
+ e.stopPropagation();
+ }
+ });
+
+ var stop = self._unrotate || ( self._unrotate = !continuing
+ ? function(e) {
+ if (e.clientX) { // in case of a true click
+ self.rotate(null);
+ }
+ }
+ : function( e ) {
+ t = o.selected;
+ rotate();
+ });
+
+ // start rotation
+ if ( ms ) {
+ this.element.bind( "tabsshow", rotate );
+ this.anchors.bind( o.event + ".tabs", stop );
+ rotate();
+ // stop rotation
+ } else {
+ clearTimeout( self.rotation );
+ this.element.unbind( "tabsshow", rotate );
+ this.anchors.unbind( o.event + ".tabs", stop );
+ delete this._rotate;
+ delete this._unrotate;
+ }
+
+ return this;
+ }
+});
+
+})( jQuery );
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-ui-1.8.18.custom.min.js b/storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-ui-1.8.18.custom.min.js
new file mode 100644
index 00000000000..f00a62f133f
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-ui-1.8.18.custom.min.js
@@ -0,0 +1,356 @@
+/*!
+ * jQuery UI 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI
+ */(function(a,b){function d(b){return!a(b).parents().andSelf().filter(function(){return a.curCSS(this,"visibility")==="hidden"||a.expr.filters.hidden(this)}).length}function c(b,c){var e=b.nodeName.toLowerCase();if("area"===e){var f=b.parentNode,g=f.name,h;if(!b.href||!g||f.nodeName.toLowerCase()!=="map")return!1;h=a("img[usemap=#"+g+"]")[0];return!!h&&d(h)}return(/input|select|textarea|button|object/.test(e)?!b.disabled:"a"==e?b.href||c:c)&&d(b)}a.ui=a.ui||{};a.ui.version||(a.extend(a.ui,{version:"1.8.18",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}}),a.fn.extend({propAttr:a.fn.prop||a.fn.attr,_focus:a.fn.focus,focus:function(b,c){return typeof b=="number"?this.each(function(){var d=this;setTimeout(function(){a(d).focus(),c&&c.call(d)},b)}):this._focus.apply(this,arguments)},scrollParent:function(){var b;a.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?b=this.parents().filter(function(){return/(relative|absolute|fixed)/.test(a.curCSS(this,"position",1))&&/(auto|scroll)/.test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0):b=this.parents().filter(function(){return/(auto|scroll)/.test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!b.length?a(document):b},zIndex:function(c){if(c!==b)return this.css("zIndex",c);if(this.length){var d=a(this[0]),e,f;while(d.length&&d[0]!==document){e=d.css("position");if(e==="absolute"||e==="relative"||e==="fixed"){f=parseInt(d.css("zIndex"),10);if(!isNaN(f)&&f!==0)return f}d=d.parent()}}return 0},disableSelection:function(){return this.bind((a.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),a.each(["Width","Height"],function(c,d){function h(b,c,d,f){a.each(e,function(){c-=parseFloat(a.curCSS(b,"padding"+this,!0))||0,d&&(c-=parseFloat(a.curCSS(b,"border"+this+"Width",!0))||0),f&&(c-=parseFloat(a.curCSS(b,"margin"+this,!0))||0)});return c}var e=d==="Width"?["Left","Right"]:["Top","Bottom"],f=d.toLowerCase(),g={innerWidth:a.fn.innerWidth,innerHeight:a.fn.innerHeight,outerWidth:a.fn.outerWidth,outerHeight:a.fn.outerHeight};a.fn["inner"+d]=function(c){if(c===b)return g["inner"+d].call(this);return this.each(function(){a(this).css(f,h(this,c)+"px")})},a.fn["outer"+d]=function(b,c){if(typeof b!="number")return g["outer"+d].call(this,b);return this.each(function(){a(this).css(f,h(this,b,!0,c)+"px")})}}),a.extend(a.expr[":"],{data:function(b,c,d){return!!a.data(b,d[3])},focusable:function(b){return c(b,!isNaN(a.attr(b,"tabindex")))},tabbable:function(b){var d=a.attr(b,"tabindex"),e=isNaN(d);return(e||d>=0)&&c(b,!e)}}),a(function(){var b=document.body,c=b.appendChild(c=document.createElement("div"));c.offsetHeight,a.extend(c.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0}),a.support.minHeight=c.offsetHeight===100,a.support.selectstart="onselectstart"in c,b.removeChild(c).style.display="none"}),a.extend(a.ui,{plugin:{add:function(b,c,d){var e=a.ui[b].prototype;for(var f in d)e.plugins[f]=e.plugins[f]||[],e.plugins[f].push([c,d[f]])},call:function(a,b,c){var d=a.plugins[b];if(!!d&&!!a.element[0].parentNode)for(var e=0;e<d.length;e++)a.options[d[e][0]]&&d[e][1].apply(a.element,c)}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(b,c){if(a(b).css("overflow")==="hidden")return!1;var d=c&&c==="left"?"scrollLeft":"scrollTop",e=!1;if(b[d]>0)return!0;b[d]=1,e=b[d]>0,b[d]=0;return e},isOverAxis:function(a,b,c){return a>b&&a<b+c},isOver:function(b,c,d,e,f,g){return a.ui.isOverAxis(b,d,f)&&a.ui.isOverAxis(c,e,g)}}))})(jQuery);/*!
+ * jQuery UI Widget 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Widget
+ */(function(a,b){if(a.cleanData){var c=a.cleanData;a.cleanData=function(b){for(var d=0,e;(e=b[d])!=null;d++)try{a(e).triggerHandler("remove")}catch(f){}c(b)}}else{var d=a.fn.remove;a.fn.remove=function(b,c){return this.each(function(){c||(!b||a.filter(b,[this]).length)&&a("*",this).add([this]).each(function(){try{a(this).triggerHandler("remove")}catch(b){}});return d.call(a(this),b,c)})}}a.widget=function(b,c,d){var e=b.split(".")[0],f;b=b.split(".")[1],f=e+"-"+b,d||(d=c,c=a.Widget),a.expr[":"][f]=function(c){return!!a.data(c,b)},a[e]=a[e]||{},a[e][b]=function(a,b){arguments.length&&this._createWidget(a,b)};var g=new c;g.options=a.extend(!0,{},g.options),a[e][b].prototype=a.extend(!0,g,{namespace:e,widgetName:b,widgetEventPrefix:a[e][b].prototype.widgetEventPrefix||b,widgetBaseClass:f},d),a.widget.bridge(b,a[e][b])},a.widget.bridge=function(c,d){a.fn[c]=function(e){var f=typeof e=="string",g=Array.prototype.slice.call(arguments,1),h=this;e=!f&&g.length?a.extend.apply(null,[!0,e].concat(g)):e;if(f&&e.charAt(0)==="_")return h;f?this.each(function(){var d=a.data(this,c),f=d&&a.isFunction(d[e])?d[e].apply(d,g):d;if(f!==d&&f!==b){h=f;return!1}}):this.each(function(){var b=a.data(this,c);b?b.option(e||{})._init():a.data(this,c,new d(e,this))});return h}},a.Widget=function(a,b){arguments.length&&this._createWidget(a,b)},a.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:!1},_createWidget:function(b,c){a.data(c,this.widgetName,this),this.element=a(c),this.options=a.extend(!0,{},this.options,this._getCreateOptions(),b);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()}),this._create(),this._trigger("create"),this._init()},_getCreateOptions:function(){return a.metadata&&a.metadata.get(this.element[0])[this.widgetName]},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName),this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled "+"ui-state-disabled")},widget:function(){return this.element},option:function(c,d){var e=c;if(arguments.length===0)return a.extend({},this.options);if(typeof c=="string"){if(d===b)return this.options[c];e={},e[c]=d}this._setOptions(e);return this},_setOptions:function(b){var c=this;a.each(b,function(a,b){c._setOption(a,b)});return this},_setOption:function(a,b){this.options[a]=b,a==="disabled"&&this.widget()[b?"addClass":"removeClass"](this.widgetBaseClass+"-disabled"+" "+"ui-state-disabled").attr("aria-disabled",b);return this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_trigger:function(b,c,d){var e,f,g=this.options[b];d=d||{},c=a.Event(c),c.type=(b===this.widgetEventPrefix?b:this.widgetEventPrefix+b).toLowerCase(),c.target=this.element[0],f=c.originalEvent;if(f)for(e in f)e in c||(c[e]=f[e]);this.element.trigger(c,d);return!(a.isFunction(g)&&g.call(this.element[0],c,d)===!1||c.isDefaultPrevented())}}})(jQuery);/*!
+ * jQuery UI Mouse 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Mouse
+ *
+ * Depends:
+ * jquery.ui.widget.js
+ */(function(a,b){var c=!1;a(document).mouseup(function(a){c=!1}),a.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var b=this;this.element.bind("mousedown."+this.widgetName,function(a){return b._mouseDown(a)}).bind("click."+this.widgetName,function(c){if(!0===a.data(c.target,b.widgetName+".preventClickEvent")){a.removeData(c.target,b.widgetName+".preventClickEvent"),c.stopImmediatePropagation();return!1}}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(b){if(!c){this._mouseStarted&&this._mouseUp(b),this._mouseDownEvent=b;var d=this,e=b.which==1,f=typeof this.options.cancel=="string"&&b.target.nodeName?a(b.target).closest(this.options.cancel).length:!1;if(!e||f||!this._mouseCapture(b))return!0;this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){d.mouseDelayMet=!0},this.options.delay));if(this._mouseDistanceMet(b)&&this._mouseDelayMet(b)){this._mouseStarted=this._mouseStart(b)!==!1;if(!this._mouseStarted){b.preventDefault();return!0}}!0===a.data(b.target,this.widgetName+".preventClickEvent")&&a.removeData(b.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(a){return d._mouseMove(a)},this._mouseUpDelegate=function(a){return d._mouseUp(a)},a(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),b.preventDefault(),c=!0;return!0}},_mouseMove:function(b){if(a.browser.msie&&!(document.documentMode>=9)&&!b.button)return this._mouseUp(b);if(this._mouseStarted){this._mouseDrag(b);return b.preventDefault()}this._mouseDistanceMet(b)&&this._mouseDelayMet(b)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,b)!==!1,this._mouseStarted?this._mouseDrag(b):this._mouseUp(b));return!this._mouseStarted},_mouseUp:function(b){a(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,b.target==this._mouseDownEvent.target&&a.data(b.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(b));return!1},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(a){return this.mouseDelayMet},_mouseStart:function(a){},_mouseDrag:function(a){},_mouseStop:function(a){},_mouseCapture:function(a){return!0}})})(jQuery);/*
+ * jQuery UI Position 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Position
+ */(function(a,b){a.ui=a.ui||{};var c=/left|center|right/,d=/top|center|bottom/,e="center",f={},g=a.fn.position,h=a.fn.offset;a.fn.position=function(b){if(!b||!b.of)return g.apply(this,arguments);b=a.extend({},b);var h=a(b.of),i=h[0],j=(b.collision||"flip").split(" "),k=b.offset?b.offset.split(" "):[0,0],l,m,n;i.nodeType===9?(l=h.width(),m=h.height(),n={top:0,left:0}):i.setTimeout?(l=h.width(),m=h.height(),n={top:h.scrollTop(),left:h.scrollLeft()}):i.preventDefault?(b.at="left top",l=m=0,n={top:b.of.pageY,left:b.of.pageX}):(l=h.outerWidth(),m=h.outerHeight(),n=h.offset()),a.each(["my","at"],function(){var a=(b[this]||"").split(" ");a.length===1&&(a=c.test(a[0])?a.concat([e]):d.test(a[0])?[e].concat(a):[e,e]),a[0]=c.test(a[0])?a[0]:e,a[1]=d.test(a[1])?a[1]:e,b[this]=a}),j.length===1&&(j[1]=j[0]),k[0]=parseInt(k[0],10)||0,k.length===1&&(k[1]=k[0]),k[1]=parseInt(k[1],10)||0,b.at[0]==="right"?n.left+=l:b.at[0]===e&&(n.left+=l/2),b.at[1]==="bottom"?n.top+=m:b.at[1]===e&&(n.top+=m/2),n.left+=k[0],n.top+=k[1];return this.each(function(){var c=a(this),d=c.outerWidth(),g=c.outerHeight(),h=parseInt(a.curCSS(this,"marginLeft",!0))||0,i=parseInt(a.curCSS(this,"marginTop",!0))||0,o=d+h+(parseInt(a.curCSS(this,"marginRight",!0))||0),p=g+i+(parseInt(a.curCSS(this,"marginBottom",!0))||0),q=a.extend({},n),r;b.my[0]==="right"?q.left-=d:b.my[0]===e&&(q.left-=d/2),b.my[1]==="bottom"?q.top-=g:b.my[1]===e&&(q.top-=g/2),f.fractions||(q.left=Math.round(q.left),q.top=Math.round(q.top)),r={left:q.left-h,top:q.top-i},a.each(["left","top"],function(c,e){a.ui.position[j[c]]&&a.ui.position[j[c]][e](q,{targetWidth:l,targetHeight:m,elemWidth:d,elemHeight:g,collisionPosition:r,collisionWidth:o,collisionHeight:p,offset:k,my:b.my,at:b.at})}),a.fn.bgiframe&&c.bgiframe(),c.offset(a.extend(q,{using:b.using}))})},a.ui.position={fit:{left:function(b,c){var d=a(window),e=c.collisionPosition.left+c.collisionWidth-d.width()-d.scrollLeft();b.left=e>0?b.left-e:Math.max(b.left-c.collisionPosition.left,b.left)},top:function(b,c){var d=a(window),e=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop();b.top=e>0?b.top-e:Math.max(b.top-c.collisionPosition.top,b.top)}},flip:{left:function(b,c){if(c.at[0]!==e){var d=a(window),f=c.collisionPosition.left+c.collisionWidth-d.width()-d.scrollLeft(),g=c.my[0]==="left"?-c.elemWidth:c.my[0]==="right"?c.elemWidth:0,h=c.at[0]==="left"?c.targetWidth:-c.targetWidth,i=-2*c.offset[0];b.left+=c.collisionPosition.left<0?g+h+i:f>0?g+h+i:0}},top:function(b,c){if(c.at[1]!==e){var d=a(window),f=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop(),g=c.my[1]==="top"?-c.elemHeight:c.my[1]==="bottom"?c.elemHeight:0,h=c.at[1]==="top"?c.targetHeight:-c.targetHeight,i=-2*c.offset[1];b.top+=c.collisionPosition.top<0?g+h+i:f>0?g+h+i:0}}}},a.offset.setOffset||(a.offset.setOffset=function(b,c){/static/.test(a.curCSS(b,"position"))&&(b.style.position="relative");var d=a(b),e=d.offset(),f=parseInt(a.curCSS(b,"top",!0),10)||0,g=parseInt(a.curCSS(b,"left",!0),10)||0,h={top:c.top-e.top+f,left:c.left-e.left+g};"using"in c?c.using.call(b,h):d.css(h)},a.fn.offset=function(b){var c=this[0];if(!c||!c.ownerDocument)return null;if(b)return this.each(function(){a.offset.setOffset(this,b)});return h.call(this)}),function(){var b=document.getElementsByTagName("body")[0],c=document.createElement("div"),d,e,g,h,i;d=document.createElement(b?"div":"body"),g={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},b&&a.extend(g,{position:"absolute",left:"-1000px",top:"-1000px"});for(var j in g)d.style[j]=g[j];d.appendChild(c),e=b||document.documentElement,e.insertBefore(d,e.firstChild),c.style.cssText="position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;",h=a(c).offset(function(a,b){return b}).offset(),d.innerHTML="",e.removeChild(d),i=h.top+h.left+(b?2e3:0),f.fractions=i>21&&i<22}()})(jQuery);/*
+ * jQuery UI Draggable 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Draggables
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
+ */(function(a,b){a.widget("ui.draggable",a.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1},_create:function(){this.options.helper=="original"&&!/^(?:r|a|f)/.test(this.element.css("position"))&&(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},destroy:function(){if(!!this.element.data("draggable")){this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy();return this}},_mouseCapture:function(b){var c=this.options;if(this.helper||c.disabled||a(b.target).is(".ui-resizable-handle"))return!1;this.handle=this._getHandle(b);if(!this.handle)return!1;c.iframeFix&&a(c.iframeFix===!0?"iframe":c.iframeFix).each(function(){a('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(a(this).offset()).appendTo("body")});return!0},_mouseStart:function(b){var c=this.options;this.helper=this._createHelper(b),this._cacheHelperProportions(),a.ui.ddmanager&&(a.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},a.extend(this.offset,{click:{left:b.pageX-this.offset.left,top:b.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(b),this.originalPageX=b.pageX,this.originalPageY=b.pageY,c.cursorAt&&this._adjustOffsetFromHelper(c.cursorAt),c.containment&&this._setContainment();if(this._trigger("start",b)===!1){this._clear();return!1}this._cacheHelperProportions(),a.ui.ddmanager&&!c.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,b),this.helper.addClass("ui-draggable-dragging"),this._mouseDrag(b,!0),a.ui.ddmanager&&a.ui.ddmanager.dragStart(this,b);return!0},_mouseDrag:function(b,c){this.position=this._generatePosition(b),this.positionAbs=this._convertPositionTo("absolute");if(!c){var d=this._uiHash();if(this._trigger("drag",b,d)===!1){this._mouseUp({});return!1}this.position=d.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";a.ui.ddmanager&&a.ui.ddmanager.drag(this,b);return!1},_mouseStop:function(b){var c=!1;a.ui.ddmanager&&!this.options.dropBehaviour&&(c=a.ui.ddmanager.drop(this,b)),this.dropped&&(c=this.dropped,this.dropped=!1);if((!this.element[0]||!this.element[0].parentNode)&&this.options.helper=="original")return!1;if(this.options.revert=="invalid"&&!c||this.options.revert=="valid"&&c||this.options.revert===!0||a.isFunction(this.options.revert)&&this.options.revert.call(this.element,c)){var d=this;a(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){d._trigger("stop",b)!==!1&&d._clear()})}else this._trigger("stop",b)!==!1&&this._clear();return!1},_mouseUp:function(b){this.options.iframeFix===!0&&a("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),a.ui.ddmanager&&a.ui.ddmanager.dragStop(this,b);return a.ui.mouse.prototype._mouseUp.call(this,b)},cancel:function(){this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear();return this},_getHandle:function(b){var c=!this.options.handle||!a(this.options.handle,this.element).length?!0:!1;a(this.options.handle,this.element).find("*").andSelf().each(function(){this==b.target&&(c=!0)});return c},_createHelper:function(b){var c=this.options,d=a.isFunction(c.helper)?a(c.helper.apply(this.element[0],[b])):c.helper=="clone"?this.element.clone().removeAttr("id"):this.element;d.parents("body").length||d.appendTo(c.appendTo=="parent"?this.element[0].parentNode:c.appendTo),d[0]!=this.element[0]&&!/(fixed|absolute)/.test(d.css("position"))&&d.css("position","absolute");return d},_adjustOffsetFromHelper:function(b){typeof b=="string"&&(b=b.split(" ")),a.isArray(b)&&(b={left:+b[0],top:+b[1]||0}),"left"in b&&(this.offset.click.left=b.left+this.margins.left),"right"in b&&(this.offset.click.left=this.helperProportions.width-b.right+this.margins.left),"top"in b&&(this.offset.click.top=b.top+this.margins.top),"bottom"in b&&(this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])&&(b.left+=this.scrollParent.scrollLeft(),b.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)b={top:0,left:0};return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var b=this.options;b.containment=="parent"&&(b.containment=this.helper[0].parentNode);if(b.containment=="document"||b.containment=="window")this.containment=[b.containment=="document"?0:a(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,b.containment=="document"?0:a(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,(b.containment=="document"?0:a(window).scrollLeft())+a(b.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(b.containment=="document"?0:a(window).scrollTop())+(a(b.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(b.containment)&&b.containment.constructor!=Array){var c=a(b.containment),d=c[0];if(!d)return;var e=c.offset(),f=a(d).css("overflow")!="hidden";this.containment=[(parseInt(a(d).css("borderLeftWidth"),10)||0)+(parseInt(a(d).css("paddingLeft"),10)||0),(parseInt(a(d).css("borderTopWidth"),10)||0)+(parseInt(a(d).css("paddingTop"),10)||0),(f?Math.max(d.scrollWidth,d.offsetWidth):d.offsetWidth)-(parseInt(a(d).css("borderLeftWidth"),10)||0)-(parseInt(a(d).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(f?Math.max(d.scrollHeight,d.offsetHeight):d.offsetHeight)-(parseInt(a(d).css("borderTopWidth"),10)||0)-(parseInt(a(d).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=c}else b.containment.constructor==Array&&(this.containment=b.containment)},_convertPositionTo:function(b,c){c||(c=this.position);var d=b=="absolute"?1:-1,e=this.options,f=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=/(html|body)/i.test(f[0].tagName);return{top:c.top+this.offset.relative.top*d+this.offset.parent.top*d-(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():g?0:f.scrollTop())*d),left:c.left+this.offset.relative.left*d+this.offset.parent.left*d-(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:f.scrollLeft())*d)}},_generatePosition:function(b){var c=this.options,d=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(d[0].tagName),f=b.pageX,g=b.pageY;if(this.originalPosition){var h;if(this.containment){if(this.relative_container){var i=this.relative_container.offset();h=[this.containment[0]+i.left,this.containment[1]+i.top,this.containment[2]+i.left,this.containment[3]+i.top]}else h=this.containment;b.pageX-this.offset.click.left<h[0]&&(f=h[0]+this.offset.click.left),b.pageY-this.offset.click.top<h[1]&&(g=h[1]+this.offset.click.top),b.pageX-this.offset.click.left>h[2]&&(f=h[2]+this.offset.click.left),b.pageY-this.offset.click.top>h[3]&&(g=h[3]+this.offset.click.top)}if(c.grid){var j=c.grid[1]?this.originalPageY+Math.round((g-this.originalPageY)/c.grid[1])*c.grid[1]:this.originalPageY;g=h?j-this.offset.click.top<h[1]||j-this.offset.click.top>h[3]?j-this.offset.click.top<h[1]?j+c.grid[1]:j-c.grid[1]:j:j;var k=c.grid[0]?this.originalPageX+Math.round((f-this.originalPageX)/c.grid[0])*c.grid[0]:this.originalPageX;f=h?k-this.offset.click.left<h[0]||k-this.offset.click.left>h[2]?k-this.offset.click.left<h[0]?k+c.grid[0]:k-c.grid[0]:k:k}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:d.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:d.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1},_trigger:function(b,c,d){d=d||this._uiHash(),a.ui.plugin.call(this,b,[c,d]),b=="drag"&&(this.positionAbs=this._convertPositionTo("absolute"));return a.Widget.prototype._trigger.call(this,b,c,d)},plugins:{},_uiHash:function(a){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),a.extend(a.ui.draggable,{version:"1.8.18"}),a.ui.plugin.add("draggable","connectToSortable",{start:function(b,c){var d=a(this).data("draggable"),e=d.options,f=a.extend({},c,{item:d.element});d.sortables=[],a(e.connectToSortable).each(function(){var c=a.data(this,"sortable");c&&!c.options.disabled&&(d.sortables.push({instance:c,shouldRevert:c.options.revert}),c.refreshPositions(),c._trigger("activate",b,f))})},stop:function(b,c){var d=a(this).data("draggable"),e=a.extend({},c,{item:d.element});a.each(d.sortables,function(){this.instance.isOver?(this.instance.isOver=0,d.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=!0),this.instance._mouseStop(b),this.instance.options.helper=this.instance.options._helper,d.options.helper=="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",b,e))})},drag:function(b,c){var d=a(this).data("draggable"),e=this,f=function(b){var c=this.offset.click.top,d=this.offset.click.left,e=this.positionAbs.top,f=this.positionAbs.left,g=b.height,h=b.width,i=b.top,j=b.left;return a.ui.isOver(e+c,f+d,i,j,g,h)};a.each(d.sortables,function(f){this.instance.positionAbs=d.positionAbs,this.instance.helperProportions=d.helperProportions,this.instance.offset.click=d.offset.click,this.instance._intersectsWith(this.instance.containerCache)?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=a(e).clone().removeAttr("id").appendTo(this.instance.element).data("sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return c.helper[0]},b.target=this.instance.currentItem[0],this.instance._mouseCapture(b,!0),this.instance._mouseStart(b,!0,!0),this.instance.offset.click.top=d.offset.click.top,this.instance.offset.click.left=d.offset.click.left,this.instance.offset.parent.left-=d.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=d.offset.parent.top-this.instance.offset.parent.top,d._trigger("toSortable",b),d.dropped=this.instance.element,d.currentItem=d.element,this.instance.fromOutside=d),this.instance.currentItem&&this.instance._mouseDrag(b)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",b,this.instance._uiHash(this.instance)),this.instance._mouseStop(b,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),d._trigger("fromSortable",b),d.dropped=!1)})}}),a.ui.plugin.add("draggable","cursor",{start:function(b,c){var d=a("body"),e=a(this).data("draggable").options;d.css("cursor")&&(e._cursor=d.css("cursor")),d.css("cursor",e.cursor)},stop:function(b,c){var d=a(this).data("draggable").options;d._cursor&&a("body").css("cursor",d._cursor)}}),a.ui.plugin.add("draggable","opacity",{start:function(b,c){var d=a(c.helper),e=a(this).data("draggable").options;d.css("opacity")&&(e._opacity=d.css("opacity")),d.css("opacity",e.opacity)},stop:function(b,c){var d=a(this).data("draggable").options;d._opacity&&a(c.helper).css("opacity",d._opacity)}}),a.ui.plugin.add("draggable","scroll",{start:function(b,c){var d=a(this).data("draggable");d.scrollParent[0]!=document&&d.scrollParent[0].tagName!="HTML"&&(d.overflowOffset=d.scrollParent.offset())},drag:function(b,c){var d=a(this).data("draggable"),e=d.options,f=!1;if(d.scrollParent[0]!=document&&d.scrollParent[0].tagName!="HTML"){if(!e.axis||e.axis!="x")d.overflowOffset.top+d.scrollParent[0].offsetHeight-b.pageY<e.scrollSensitivity?d.scrollParent[0].scrollTop=f=d.scrollParent[0].scrollTop+e.scrollSpeed:b.pageY-d.overflowOffset.top<e.scrollSensitivity&&(d.scrollParent[0].scrollTop=f=d.scrollParent[0].scrollTop-e.scrollSpeed);if(!e.axis||e.axis!="y")d.overflowOffset.left+d.scrollParent[0].offsetWidth-b.pageX<e.scrollSensitivity?d.scrollParent[0].scrollLeft=f=d.scrollParent[0].scrollLeft+e.scrollSpeed:b.pageX-d.overflowOffset.left<e.scrollSensitivity&&(d.scrollParent[0].scrollLeft=f=d.scrollParent[0].scrollLeft-e.scrollSpeed)}else{if(!e.axis||e.axis!="x")b.pageY-a(document).scrollTop()<e.scrollSensitivity?f=a(document).scrollTop(a(document).scrollTop()-e.scrollSpeed):a(window).height()-(b.pageY-a(document).scrollTop())<e.scrollSensitivity&&(f=a(document).scrollTop(a(document).scrollTop()+e.scrollSpeed));if(!e.axis||e.axis!="y")b.pageX-a(document).scrollLeft()<e.scrollSensitivity?f=a(document).scrollLeft(a(document).scrollLeft()-e.scrollSpeed):a(window).width()-(b.pageX-a(document).scrollLeft())<e.scrollSensitivity&&(f=a(document).scrollLeft(a(document).scrollLeft()+e.scrollSpeed))}f!==!1&&a.ui.ddmanager&&!e.dropBehaviour&&a.ui.ddmanager.prepareOffsets(d,b)}}),a.ui.plugin.add("draggable","snap",{start:function(b,c){var d=a(this).data("draggable"),e=d.options;d.snapElements=[],a(e.snap.constructor!=String?e.snap.items||":data(draggable)":e.snap).each(function(){var b=a(this),c=b.offset();this!=d.element[0]&&d.snapElements.push({item:this,width:b.outerWidth(),height:b.outerHeight(),top:c.top,left:c.left})})},drag:function(b,c){var d=a(this).data("draggable"),e=d.options,f=e.snapTolerance,g=c.offset.left,h=g+d.helperProportions.width,i=c.offset.top,j=i+d.helperProportions.height;for(var k=d.snapElements.length-1;k>=0;k--){var l=d.snapElements[k].left,m=l+d.snapElements[k].width,n=d.snapElements[k].top,o=n+d.snapElements[k].height;if(!(l-f<g&&g<m+f&&n-f<i&&i<o+f||l-f<g&&g<m+f&&n-f<j&&j<o+f||l-f<h&&h<m+f&&n-f<i&&i<o+f||l-f<h&&h<m+f&&n-f<j&&j<o+f)){d.snapElements[k].snapping&&d.options.snap.release&&d.options.snap.release.call(d.element,b,a.extend(d._uiHash(),{snapItem:d.snapElements[k].item})),d.snapElements[k].snapping=!1;continue}if(e.snapMode!="inner"){var p=Math.abs(n-j)<=f,q=Math.abs(o-i)<=f,r=Math.abs(l-h)<=f,s=Math.abs(m-g)<=f;p&&(c.position.top=d._convertPositionTo("relative",{top:n-d.helperProportions.height,left:0}).top-d.margins.top),q&&(c.position.top=d._convertPositionTo("relative",{top:o,left:0}).top-d.margins.top),r&&(c.position.left=d._convertPositionTo("relative",{top:0,left:l-d.helperProportions.width}).left-d.margins.left),s&&(c.position.left=d._convertPositionTo("relative",{top:0,left:m}).left-d.margins.left)}var t=p||q||r||s;if(e.snapMode!="outer"){var p=Math.abs(n-i)<=f,q=Math.abs(o-j)<=f,r=Math.abs(l-g)<=f,s=Math.abs(m-h)<=f;p&&(c.position.top=d._convertPositionTo("relative",{top:n,left:0}).top-d.margins.top),q&&(c.position.top=d._convertPositionTo("relative",{top:o-d.helperProportions.height,left:0}).top-d.margins.top),r&&(c.position.left=d._convertPositionTo("relative",{top:0,left:l}).left-d.margins.left),s&&(c.position.left=d._convertPositionTo("relative",{top:0,left:m-d.helperProportions.width}).left-d.margins.left)}!d.snapElements[k].snapping&&(p||q||r||s||t)&&d.options.snap.snap&&d.options.snap.snap.call(d.element,b,a.extend(d._uiHash(),{snapItem:d.snapElements[k].item})),d.snapElements[k].snapping=p||q||r||s||t}}}),a.ui.plugin.add("draggable","stack",{start:function(b,c){var d=a(this).data("draggable").options,e=a.makeArray(a(d.stack)).sort(function(b,c){return(parseInt(a(b).css("zIndex"),10)||0)-(parseInt(a(c).css("zIndex"),10)||0)});if(!!e.length){var f=parseInt(e[0].style.zIndex)||0;a(e).each(function(a){this.style.zIndex=f+a}),this[0].style.zIndex=f+e.length}}}),a.ui.plugin.add("draggable","zIndex",{start:function(b,c){var d=a(c.helper),e=a(this).data("draggable").options;d.css("zIndex")&&(e._zIndex=d.css("zIndex")),d.css("zIndex",e.zIndex)},stop:function(b,c){var d=a(this).data("draggable").options;d._zIndex&&a(c.helper).css("zIndex",d._zIndex)}})})(jQuery);/*
+ * jQuery UI Droppable 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Droppables
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ * jquery.ui.mouse.js
+ * jquery.ui.draggable.js
+ */(function(a,b){a.widget("ui.droppable",{widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect"},_create:function(){var b=this.options,c=b.accept;this.isover=0,this.isout=1,this.accept=a.isFunction(c)?c:function(a){return a.is(c)},this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight},a.ui.ddmanager.droppables[b.scope]=a.ui.ddmanager.droppables[b.scope]||[],a.ui.ddmanager.droppables[b.scope].push(this),b.addClasses&&this.element.addClass("ui-droppable")},destroy:function(){var b=a.ui.ddmanager.droppables[this.options.scope];for(var c=0;c<b.length;c++)b[c]==this&&b.splice(c,1);this.element.removeClass("ui-droppable ui-droppable-disabled").removeData("droppable").unbind(".droppable");return this},_setOption:function(b,c){b=="accept"&&(this.accept=a.isFunction(c)?c:function(a){return a.is(c)}),a.Widget.prototype._setOption.apply(this,arguments)},_activate:function(b){var c=a.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),c&&this._trigger("activate",b,this.ui(c))},_deactivate:function(b){var c=a.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),c&&this._trigger("deactivate",b,this.ui(c))},_over:function(b){var c=a.ui.ddmanager.current;!!c&&(c.currentItem||c.element)[0]!=this.element[0]&&this.accept.call(this.element[0],c.currentItem||c.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",b,this.ui(c)))},_out:function(b){var c=a.ui.ddmanager.current;!!c&&(c.currentItem||c.element)[0]!=this.element[0]&&this.accept.call(this.element[0],c.currentItem||c.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",b,this.ui(c)))},_drop:function(b,c){var d=c||a.ui.ddmanager.current;if(!d||(d.currentItem||d.element)[0]==this.element[0])return!1;var e=!1;this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var b=a.data(this,"droppable");if(b.options.greedy&&!b.options.disabled&&b.options.scope==d.options.scope&&b.accept.call(b.element[0],d.currentItem||d.element)&&a.ui.intersect(d,a.extend(b,{offset:b.element.offset()}),b.options.tolerance)){e=!0;return!1}});if(e)return!1;if(this.accept.call(this.element[0],d.currentItem||d.element)){this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",b,this.ui(d));return this.element}return!1},ui:function(a){return{draggable:a.currentItem||a.element,helper:a.helper,position:a.position,offset:a.positionAbs}}}),a.extend(a.ui.droppable,{version:"1.8.18"}),a.ui.intersect=function(b,c,d){if(!c.offset)return!1;var e=(b.positionAbs||b.position.absolute).left,f=e+b.helperProportions.width,g=(b.positionAbs||b.position.absolute).top,h=g+b.helperProportions.height,i=c.offset.left,j=i+c.proportions.width,k=c.offset.top,l=k+c.proportions.height;switch(d){case"fit":return i<=e&&f<=j&&k<=g&&h<=l;case"intersect":return i<e+b.helperProportions.width/2&&f-b.helperProportions.width/2<j&&k<g+b.helperProportions.height/2&&h-b.helperProportions.height/2<l;case"pointer":var m=(b.positionAbs||b.position.absolute).left+(b.clickOffset||b.offset.click).left,n=(b.positionAbs||b.position.absolute).top+(b.clickOffset||b.offset.click).top,o=a.ui.isOver(n,m,k,i,c.proportions.height,c.proportions.width);return o;case"touch":return(g>=k&&g<=l||h>=k&&h<=l||g<k&&h>l)&&(e>=i&&e<=j||f>=i&&f<=j||e<i&&f>j);default:return!1}},a.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(b,c){var d=a.ui.ddmanager.droppables[b.options.scope]||[],e=c?c.type:null,f=(b.currentItem||b.element).find(":data(droppable)").andSelf();droppablesLoop:for(var g=0;g<d.length;g++){if(d[g].options.disabled||b&&!d[g].accept.call(d[g].element[0],b.currentItem||b.element))continue;for(var h=0;h<f.length;h++)if(f[h]==d[g].element[0]){d[g].proportions.height=0;continue droppablesLoop}d[g].visible=d[g].element.css("display")!="none";if(!d[g].visible)continue;e=="mousedown"&&d[g]._activate.call(d[g],c),d[g].offset=d[g].element.offset(),d[g].proportions={width:d[g].element[0].offsetWidth,height:d[g].element[0].offsetHeight}}},drop:function(b,c){var d=!1;a.each(a.ui.ddmanager.droppables[b.options.scope]||[],function(){!this.options||(!this.options.disabled&&this.visible&&a.ui.intersect(b,this,this.options.tolerance)&&(d=this._drop.call(this,c)||d),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],b.currentItem||b.element)&&(this.isout=1,this.isover=0,this._deactivate.call(this,c)))});return d},dragStart:function(b,c){b.element.parents(":not(body,html)").bind("scroll.droppable",function(){b.options.refreshPositions||a.ui.ddmanager.prepareOffsets(b,c)})},drag:function(b,c){b.options.refreshPositions&&a.ui.ddmanager.prepareOffsets(b,c),a.each(a.ui.ddmanager.droppables[b.options.scope]||[],function(){if(!(this.options.disabled||this.greedyChild||!this.visible)){var d=a.ui.intersect(b,this,this.options.tolerance),e=!d&&this.isover==1?"isout":d&&this.isover==0?"isover":null;if(!e)return;var f;if(this.options.greedy){var g=this.element.parents(":data(droppable):eq(0)");g.length&&(f=a.data(g[0],"droppable"),f.greedyChild=e=="isover"?1:0)}f&&e=="isover"&&(f.isover=0,f.isout=1,f._out.call(f,c)),this[e]=1,this[e=="isout"?"isover":"isout"]=0,this[e=="isover"?"_over":"_out"].call(this,c),f&&e=="isout"&&(f.isout=0,f.isover=1,f._over.call(f,c))}})},dragStop:function(b,c){b.element.parents(":not(body,html)").unbind("scroll.droppable"),b.options.refreshPositions||a.ui.ddmanager.prepareOffsets(b,c)}}})(jQuery);/*
+ * jQuery UI Resizable 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Resizables
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
+ */(function(a,b){a.widget("ui.resizable",a.ui.mouse,{widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1e3},_create:function(){var b=this,c=this.options;this.element.addClass("ui-resizable"),a.extend(this,{_aspectRatio:!!c.aspectRatio,aspectRatio:c.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:c.helper||c.ghost||c.animate?c.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(a('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("resizable",this.element.data("resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=c.handles||(a(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se");if(this.handles.constructor==String){this.handles=="all"&&(this.handles="n,e,s,w,se,sw,ne,nw");var d=this.handles.split(",");this.handles={};for(var e=0;e<d.length;e++){var f=a.trim(d[e]),g="ui-resizable-"+f,h=a('<div class="ui-resizable-handle '+g+'"></div>');/sw|se|ne|nw/.test(f)&&h.css({zIndex:++c.zIndex}),"se"==f&&h.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[f]=".ui-resizable-"+f,this.element.append(h)}}this._renderAxis=function(b){b=b||this.element;for(var c in this.handles){this.handles[c].constructor==String&&(this.handles[c]=a(this.handles[c],this.element).show());if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var d=a(this.handles[c],this.element),e=0;e=/sw|ne|nw|se|n|s/.test(c)?d.outerHeight():d.outerWidth();var f=["padding",/ne|nw|n/.test(c)?"Top":/se|sw|s/.test(c)?"Bottom":/^e$/.test(c)?"Right":"Left"].join("");b.css(f,e),this._proportionallyResize()}if(!a(this.handles[c]).length)continue}},this._renderAxis(this.element),this._handles=a(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){if(!b.resizing){if(this.className)var a=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=a&&a[1]?a[1]:"se"}}),c.autoHide&&(this._handles.hide(),a(this.element).addClass("ui-resizable-autohide").hover(function(){c.disabled||(a(this).removeClass("ui-resizable-autohide"),b._handles.show())},function(){c.disabled||b.resizing||(a(this).addClass("ui-resizable-autohide"),b._handles.hide())})),this._mouseInit()},destroy:function(){this._mouseDestroy();var b=function(b){a(b).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){b(this.element);var c=this.element;c.after(this.originalElement.css({position:c.css("position"),width:c.outerWidth(),height:c.outerHeight(),top:c.css("top"),left:c.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle),b(this.originalElement);return this},_mouseCapture:function(b){var c=!1;for(var d in this.handles)a(this.handles[d])[0]==b.target&&(c=!0);return!this.options.disabled&&c},_mouseStart:function(b){var d=this.options,e=this.element.position(),f=this.element;this.resizing=!0,this.documentScroll={top:a(document).scrollTop(),left:a(document).scrollLeft()},(f.is(".ui-draggable")||/absolute/.test(f.css("position")))&&f.css({position:"absolute",top:e.top,left:e.left}),this._renderProxy();var g=c(this.helper.css("left")),h=c(this.helper.css("top"));d.containment&&(g+=a(d.containment).scrollLeft()||0,h+=a(d.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:g,top:h},this.size=this._helper?{width:f.outerWidth(),height:f.outerHeight()}:{width:f.width(),height:f.height()},this.originalSize=this._helper?{width:f.outerWidth(),height:f.outerHeight()}:{width:f.width(),height:f.height()},this.originalPosition={left:g,top:h},this.sizeDiff={width:f.outerWidth()-f.width(),height:f.outerHeight()-f.height()},this.originalMousePosition={left:b.pageX,top:b.pageY},this.aspectRatio=typeof d.aspectRatio=="number"?d.aspectRatio:this.originalSize.width/this.originalSize.height||1;var i=a(".ui-resizable-"+this.axis).css("cursor");a("body").css("cursor",i=="auto"?this.axis+"-resize":i),f.addClass("ui-resizable-resizing"),this._propagate("start",b);return!0},_mouseDrag:function(b){var c=this.helper,d=this.options,e={},f=this,g=this.originalMousePosition,h=this.axis,i=b.pageX-g.left||0,j=b.pageY-g.top||0,k=this._change[h];if(!k)return!1;var l=k.apply(this,[b,i,j]),m=a.browser.msie&&a.browser.version<7,n=this.sizeDiff;this._updateVirtualBoundaries(b.shiftKey);if(this._aspectRatio||b.shiftKey)l=this._updateRatio(l,b);l=this._respectSize(l,b),this._propagate("resize",b),c.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"}),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),this._updateCache(l),this._trigger("resize",b,this.ui());return!1},_mouseStop:function(b){this.resizing=!1;var c=this.options,d=this;if(this._helper){var e=this._proportionallyResizeElements,f=e.length&&/textarea/i.test(e[0].nodeName),g=f&&a.ui.hasScroll(e[0],"left")?0:d.sizeDiff.height,h=f?0:d.sizeDiff.width,i={width:d.helper.width()-h,height:d.helper.height()-g},j=parseInt(d.element.css("left"),10)+(d.position.left-d.originalPosition.left)||null,k=parseInt(d.element.css("top"),10)+(d.position.top-d.originalPosition.top)||null;c.animate||this.element.css(a.extend(i,{top:k,left:j})),d.helper.height(d.size.height),d.helper.width(d.size.width),this._helper&&!c.animate&&this._proportionallyResize()}a("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",b),this._helper&&this.helper.remove();return!1},_updateVirtualBoundaries:function(a){var b=this.options,c,e,f,g,h;h={minWidth:d(b.minWidth)?b.minWidth:0,maxWidth:d(b.maxWidth)?b.maxWidth:Infinity,minHeight:d(b.minHeight)?b.minHeight:0,maxHeight:d(b.maxHeight)?b.maxHeight:Infinity};if(this._aspectRatio||a)c=h.minHeight*this.aspectRatio,f=h.minWidth/this.aspectRatio,e=h.maxHeight*this.aspectRatio,g=h.maxWidth/this.aspectRatio,c>h.minWidth&&(h.minWidth=c),f>h.minHeight&&(h.minHeight=f),e<h.maxWidth&&(h.maxWidth=e),g<h.maxHeight&&(h.maxHeight=g);this._vBoundaries=h},_updateCache:function(a){var b=this.options;this.offset=this.helper.offset(),d(a.left)&&(this.position.left=a.left),d(a.top)&&(this.position.top=a.top),d(a.height)&&(this.size.height=a.height),d(a.width)&&(this.size.width=a.width)},_updateRatio:function(a,b){var c=this.options,e=this.position,f=this.size,g=this.axis;d(a.height)?a.width=a.height*this.aspectRatio:d(a.width)&&(a.height=a.width/this.aspectRatio),g=="sw"&&(a.left=e.left+(f.width-a.width),a.top=null),g=="nw"&&(a.top=e.top+(f.height-a.height),a.left=e.left+(f.width-a.width));return a},_respectSize:function(a,b){var c=this.helper,e=this._vBoundaries,f=this._aspectRatio||b.shiftKey,g=this.axis,h=d(a.width)&&e.maxWidth&&e.maxWidth<a.width,i=d(a.height)&&e.maxHeight&&e.maxHeight<a.height,j=d(a.width)&&e.minWidth&&e.minWidth>a.width,k=d(a.height)&&e.minHeight&&e.minHeight>a.height;j&&(a.width=e.minWidth),k&&(a.height=e.minHeight),h&&(a.width=e.maxWidth),i&&(a.height=e.maxHeight);var l=this.originalPosition.left+this.originalSize.width,m=this.position.top+this.size.height,n=/sw|nw|w/.test(g),o=/nw|ne|n/.test(g);j&&n&&(a.left=l-e.minWidth),h&&n&&(a.left=l-e.maxWidth),k&&o&&(a.top=m-e.minHeight),i&&o&&(a.top=m-e.maxHeight);var p=!a.width&&!a.height;p&&!a.left&&a.top?a.top=null:p&&!a.top&&a.left&&(a.left=null);return a},_proportionallyResize:function(){var b=this.options;if(!!this._proportionallyResizeElements.length){var c=this.helper||this.element;for(var d=0;d<this._proportionallyResizeElements.length;d++){var e=this._proportionallyResizeElements[d];if(!this.borderDif){var f=[e.css("borderTopWidth"),e.css("borderRightWidth"),e.css("borderBottomWidth"),e.css("borderLeftWidth")],g=[e.css("paddingTop"),e.css("paddingRight"),e.css("paddingBottom"),e.css("paddingLeft")];this.borderDif=a.map(f,function(a,b){var c=parseInt(a,10)||0,d=parseInt(g[b],10)||0;return c+d})}if(a.browser.msie&&(!!a(c).is(":hidden")||!!a(c).parents(":hidden").length))continue;e.css({height:c.height()-this.borderDif[0]-this.borderDif[2]||0,width:c.width()-this.borderDif[1]-this.borderDif[3]||0})}}},_renderProxy:function(){var b=this.element,c=this.options;this.elementOffset=b.offset();if(this._helper){this.helper=this.helper||a('<div style="overflow:hidden;"></div>');var d=a.browser.msie&&a.browser.version<7,e=d?1:0,f=d?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+f,height:this.element.outerHeight()+f,position:"absolute",left:this.elementOffset.left-e+"px",top:this.elementOffset.top-e+"px",zIndex:++c.zIndex}),this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(a,b,c){return{width:this.originalSize.width+b}},w:function(a,b,c){var d=this.options,e=this.originalSize,f=this.originalPosition;return{left:f.left+b,width:e.width-b}},n:function(a,b,c){var d=this.options,e=this.originalSize,f=this.originalPosition;return{top:f.top+c,height:e.height-c}},s:function(a,b,c){return{height:this.originalSize.height+c}},se:function(b,c,d){return a.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,c,d]))},sw:function(b,c,d){return a.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,c,d]))},ne:function(b,c,d){return a.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[b,c,d]))},nw:function(b,c,d){return a.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,c,d]))}},_propagate:function(b,c){a.ui.plugin.call(this,b,[c,this.ui()]),b!="resize"&&this._trigger(b,c,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),a.extend(a.ui.resizable,{version:"1.8.18"}),a.ui.plugin.add("resizable","alsoResize",{start:function(b,c){var d=a(this).data("resizable"),e=d.options,f=function(b){a(b).each(function(){var b=a(this);b.data("resizable-alsoresize",{width:parseInt(b.width(),10),height:parseInt(b.height(),10),left:parseInt(b.css("left"),10),top:parseInt(b.css("top"),10)})})};typeof e.alsoResize=="object"&&!e.alsoResize.parentNode?e.alsoResize.length?(e.alsoResize=e.alsoResize[0],f(e.alsoResize)):a.each(e.alsoResize,function(a){f(a)}):f(e.alsoResize)},resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.originalSize,g=d.originalPosition,h={height:d.size.height-f.height||0,width:d.size.width-f.width||0,top:d.position.top-g.top||0,left:d.position.left-g.left||0},i=function(b,d){a(b).each(function(){var b=a(this),e=a(this).data("resizable-alsoresize"),f={},g=d&&d.length?d:b.parents(c.originalElement[0]).length?["width","height"]:["width","height","top","left"];a.each(g,function(a,b){var c=(e[b]||0)+(h[b]||0);c&&c>=0&&(f[b]=c||null)}),b.css(f)})};typeof e.alsoResize=="object"&&!e.alsoResize.nodeType?a.each(e.alsoResize,function(a,b){i(a,b)}):i(e.alsoResize)},stop:function(b,c){a(this).removeData("resizable-alsoresize")}}),a.ui.plugin.add("resizable","animate",{stop:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d._proportionallyResizeElements,g=f.length&&/textarea/i.test(f[0].nodeName),h=g&&a.ui.hasScroll(f[0],"left")?0:d.sizeDiff.height,i=g?0:d.sizeDiff.width,j={width:d.size.width-i,height:d.size.height-h},k=parseInt(d.element.css("left"),10)+(d.position.left-d.originalPosition.left)||null,l=parseInt(d.element.css("top"),10)+(d.position.top-d.originalPosition.top)||null;d.element.animate(a.extend(j,l&&k?{top:l,left:k}:{}),{duration:e.animateDuration,easing:e.animateEasing,step:function(){var c={width:parseInt(d.element.css("width"),10),height:parseInt(d.element.css("height"),10),top:parseInt(d.element.css("top"),10),left:parseInt(d.element.css("left"),10)};f&&f.length&&a(f[0]).css({width:c.width,height:c.height}),d._updateCache(c),d._propagate("resize",b)}})}}),a.ui.plugin.add("resizable","containment",{start:function(b,d){var e=a(this).data("resizable"),f=e.options,g=e.element,h=f.containment,i=h instanceof a?h.get(0):/parent/.test(h)?g.parent().get(0):h;if(!!i){e.containerElement=a(i);if(/document/.test(h)||h==document)e.containerOffset={left:0,top:0},e.containerPosition={left:0,top:0},e.parentData={element:a(document),left:0,top:0,width:a(document).width(),height:a(document).height()||document.body.parentNode.scrollHeight};else{var j=a(i),k=[];a(["Top","Right","Left","Bottom"]).each(function(a,b){k[a]=c(j.css("padding"+b))}),e.containerOffset=j.offset(),e.containerPosition=j.position(),e.containerSize={height:j.innerHeight()-k[3],width:j.innerWidth()-k[1]};var l=e.containerOffset,m=e.containerSize.height,n=e.containerSize.width,o=a.ui.hasScroll(i,"left")?i.scrollWidth:n,p=a.ui.hasScroll(i)?i.scrollHeight:m;e.parentData={element:i,left:l.left,top:l.top,width:o,height:p}}}},resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.containerSize,g=d.containerOffset,h=d.size,i=d.position,j=d._aspectRatio||b.shiftKey,k={top:0,left:0},l=d.containerElement;l[0]!=document&&/static/.test(l.css("position"))&&(k=g),i.left<(d._helper?g.left:0)&&(d.size.width=d.size.width+(d._helper?d.position.left-g.left:d.position.left-k.left),j&&(d.size.height=d.size.width/e.aspectRatio),d.position.left=e.helper?g.left:0),i.top<(d._helper?g.top:0)&&(d.size.height=d.size.height+(d._helper?d.position.top-g.top:d.position.top),j&&(d.size.width=d.size.height*e.aspectRatio),d.position.top=d._helper?g.top:0),d.offset.left=d.parentData.left+d.position.left,d.offset.top=d.parentData.top+d.position.top;var m=Math.abs((d._helper?d.offset.left-k.left:d.offset.left-k.left)+d.sizeDiff.width),n=Math.abs((d._helper?d.offset.top-k.top:d.offset.top-g.top)+d.sizeDiff.height),o=d.containerElement.get(0)==d.element.parent().get(0),p=/relative|absolute/.test(d.containerElement.css("position"));o&&p&&(m-=d.parentData.left),m+d.size.width>=d.parentData.width&&(d.size.width=d.parentData.width-m,j&&(d.size.height=d.size.width/d.aspectRatio)),n+d.size.height>=d.parentData.height&&(d.size.height=d.parentData.height-n,j&&(d.size.width=d.size.height*d.aspectRatio))},stop:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.position,g=d.containerOffset,h=d.containerPosition,i=d.containerElement,j=a(d.helper),k=j.offset(),l=j.outerWidth()-d.sizeDiff.width,m=j.outerHeight()-d.sizeDiff.height;d._helper&&!e.animate&&/relative/.test(i.css("position"))&&a(this).css({left:k.left-h.left-g.left,width:l,height:m}),d._helper&&!e.animate&&/static/.test(i.css("position"))&&a(this).css({left:k.left-h.left-g.left,width:l,height:m})}}),a.ui.plugin.add("resizable","ghost",{start:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.size;d.ghost=d.originalElement.clone(),d.ghost.css({opacity:.25,display:"block",position:"relative",height:f.height,width:f.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof e.ghost=="string"?e.ghost:""),d.ghost.appendTo(d.helper)},resize:function(b,c){var d=a(this).data("resizable"),e=d.options;d.ghost&&d.ghost.css({position:"relative",height:d.size.height,width:d.size.width})},stop:function(b,c){var d=a(this).data("resizable"),e=d.options;d.ghost&&d.helper&&d.helper.get(0).removeChild(d.ghost.get(0))}}),a.ui.plugin.add("resizable","grid",{resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.size,g=d.originalSize,h=d.originalPosition,i=d.axis,j=e._aspectRatio||b.shiftKey;e.grid=typeof e.grid=="number"?[e.grid,e.grid]:e.grid;var k=Math.round((f.width-g.width)/(e.grid[0]||1))*(e.grid[0]||1),l=Math.round((f.height-g.height)/(e.grid[1]||1))*(e.grid[1]||1);/^(se|s|e)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l):/^(ne)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l,d.position.top=h.top-l):/^(sw)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l,d.position.left=h.left-k):(d.size.width=g.width+k,d.size.height=g.height+l,d.position.top=h.top-l,d.position.left=h.left-k)}});var c=function(a){return parseInt(a,10)||0},d=function(a){return!isNaN(parseInt(a,10))}})(jQuery);/*
+ * jQuery UI Selectable 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Selectables
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
+ */(function(a,b){a.widget("ui.selectable",a.ui.mouse,{options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch"},_create:function(){var b=this;this.element.addClass("ui-selectable"),this.dragged=!1;var c;this.refresh=function(){c=a(b.options.filter,b.element[0]),c.addClass("ui-selectee"),c.each(function(){var b=a(this),c=b.offset();a.data(this,"selectable-item",{element:this,$element:b,left:c.left,top:c.top,right:c.left+b.outerWidth(),bottom:c.top+b.outerHeight(),startselected:!1,selected:b.hasClass("ui-selected"),selecting:b.hasClass("ui-selecting"),unselecting:b.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=c.addClass("ui-selectee"),this._mouseInit(),this.helper=a("<div class='ui-selectable-helper'></div>")},destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable"),this._mouseDestroy();return this},_mouseStart:function(b){var c=this;this.opos=[b.pageX,b.pageY];if(!this.options.disabled){var d=this.options;this.selectees=a(d.filter,this.element[0]),this._trigger("start",b),a(d.appendTo).append(this.helper),this.helper.css({left:b.clientX,top:b.clientY,width:0,height:0}),d.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var d=a.data(this,"selectable-item");d.startselected=!0,!b.metaKey&&!b.ctrlKey&&(d.$element.removeClass("ui-selected"),d.selected=!1,d.$element.addClass("ui-unselecting"),d.unselecting=!0,c._trigger("unselecting",b,{unselecting:d.element}))}),a(b.target).parents().andSelf().each(function(){var d=a.data(this,"selectable-item");if(d){var e=!b.metaKey&&!b.ctrlKey||!d.$element.hasClass("ui-selected");d.$element.removeClass(e?"ui-unselecting":"ui-selected").addClass(e?"ui-selecting":"ui-unselecting"),d.unselecting=!e,d.selecting=e,d.selected=e,e?c._trigger("selecting",b,{selecting:d.element}):c._trigger("unselecting",b,{unselecting:d.element});return!1}})}},_mouseDrag:function(b){var c=this;this.dragged=!0;if(!this.options.disabled){var d=this.options,e=this.opos[0],f=this.opos[1],g=b.pageX,h=b.pageY;if(e>g){var i=g;g=e,e=i}if(f>h){var i=h;h=f,f=i}this.helper.css({left:e,top:f,width:g-e,height:h-f}),this.selectees.each(function(){var i=a.data(this,"selectable-item");if(!!i&&i.element!=c.element[0]){var j=!1;d.tolerance=="touch"?j=!(i.left>g||i.right<e||i.top>h||i.bottom<f):d.tolerance=="fit"&&(j=i.left>e&&i.right<g&&i.top>f&&i.bottom<h),j?(i.selected&&(i.$element.removeClass("ui-selected"),i.selected=!1),i.unselecting&&(i.$element.removeClass("ui-unselecting"),i.unselecting=!1),i.selecting||(i.$element.addClass("ui-selecting"),i.selecting=!0,c._trigger("selecting",b,{selecting:i.element}))):(i.selecting&&((b.metaKey||b.ctrlKey)&&i.startselected?(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.$element.addClass("ui-selected"),i.selected=!0):(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.startselected&&(i.$element.addClass("ui-unselecting"),i.unselecting=!0),c._trigger("unselecting",b,{unselecting:i.element}))),i.selected&&!b.metaKey&&!b.ctrlKey&&!i.startselected&&(i.$element.removeClass("ui-selected"),i.selected=!1,i.$element.addClass("ui-unselecting"),i.unselecting=!0,c._trigger("unselecting",b,{unselecting:i.element})))}});return!1}},_mouseStop:function(b){var c=this;this.dragged=!1;var d=this.options;a(".ui-unselecting",this.element[0]).each(function(){var d=a.data(this,"selectable-item");d.$element.removeClass("ui-unselecting"),d.unselecting=!1,d.startselected=!1,c._trigger("unselected",b,{unselected:d.element})}),a(".ui-selecting",this.element[0]).each(function(){var d=a.data(this,"selectable-item");d.$element.removeClass("ui-selecting").addClass("ui-selected"),d.selecting=!1,d.selected=!0,d.startselected=!0,c._trigger("selected",b,{selected:d.element})}),this._trigger("stop",b),this.helper.remove();return!1}}),a.extend(a.ui.selectable,{version:"1.8.18"})})(jQuery);/*
+ * jQuery UI Sortable 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Sortables
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
+ */(function(a,b){a.widget("ui.sortable",a.ui.mouse,{widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3},_create:function(){var a=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?a.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},destroy:function(){a.Widget.prototype.destroy.call(this),this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var b=this.items.length-1;b>=0;b--)this.items[b].item.removeData(this.widgetName+"-item");return this},_setOption:function(b,c){b==="disabled"?(this.options[b]=c,this.widget()[c?"addClass":"removeClass"]("ui-sortable-disabled")):a.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(b,c){var d=this;if(this.reverting)return!1;if(this.options.disabled||this.options.type=="static")return!1;this._refreshItems(b);var e=null,f=this,g=a(b.target).parents().each(function(){if(a.data(this,d.widgetName+"-item")==f){e=a(this);return!1}});a.data(b.target,d.widgetName+"-item")==f&&(e=a(b.target));if(!e)return!1;if(this.options.handle&&!c){var h=!1;a(this.options.handle,e).find("*").andSelf().each(function(){this==b.target&&(h=!0)});if(!h)return!1}this.currentItem=e,this._removeCurrentsFromItems();return!0},_mouseStart:function(b,c,d){var e=this.options,f=this;this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(b),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),a.extend(this.offset,{click:{left:b.pageX-this.offset.left,top:b.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this._generatePosition(b),this.originalPageX=b.pageX,this.originalPageY=b.pageY,e.cursorAt&&this._adjustOffsetFromHelper(e.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!=this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),e.containment&&this._setContainment(),e.cursor&&(a("body").css("cursor")&&(this._storedCursor=a("body").css("cursor")),a("body").css("cursor",e.cursor)),e.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",e.opacity)),e.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",e.zIndex)),this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",b,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions();if(!d)for(var g=this.containers.length-1;g>=0;g--)this.containers[g]._trigger("activate",b,f._uiHash(this));a.ui.ddmanager&&(a.ui.ddmanager.current=this),a.ui.ddmanager&&!e.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,b),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(b);return!0},_mouseDrag:function(b){this.position=this._generatePosition(b),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs);if(this.options.scroll){var c=this.options,d=!1;this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-b.pageY<c.scrollSensitivity?this.scrollParent[0].scrollTop=d=this.scrollParent[0].scrollTop+c.scrollSpeed:b.pageY-this.overflowOffset.top<c.scrollSensitivity&&(this.scrollParent[0].scrollTop=d=this.scrollParent[0].scrollTop-c.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-b.pageX<c.scrollSensitivity?this.scrollParent[0].scrollLeft=d=this.scrollParent[0].scrollLeft+c.scrollSpeed:b.pageX-this.overflowOffset.left<c.scrollSensitivity&&(this.scrollParent[0].scrollLeft=d=this.scrollParent[0].scrollLeft-c.scrollSpeed)):(b.pageY-a(document).scrollTop()<c.scrollSensitivity?d=a(document).scrollTop(a(document).scrollTop()-c.scrollSpeed):a(window).height()-(b.pageY-a(document).scrollTop())<c.scrollSensitivity&&(d=a(document).scrollTop(a(document).scrollTop()+c.scrollSpeed)),b.pageX-a(document).scrollLeft()<c.scrollSensitivity?d=a(document).scrollLeft(a(document).scrollLeft()-c.scrollSpeed):a(window).width()-(b.pageX-a(document).scrollLeft())<c.scrollSensitivity&&(d=a(document).scrollLeft(a(document).scrollLeft()+c.scrollSpeed))),d!==!1&&a.ui.ddmanager&&!c.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,b)}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";for(var e=this.items.length-1;e>=0;e--){var f=this.items[e],g=f.item[0],h=this._intersectsWithPointer(f);if(!h)continue;if(g!=this.currentItem[0]&&this.placeholder[h==1?"next":"prev"]()[0]!=g&&!a.ui.contains(this.placeholder[0],g)&&(this.options.type=="semi-dynamic"?!a.ui.contains(this.element[0],g):!0)){this.direction=h==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(f))this._rearrange(b,f);else break;this._trigger("change",b,this._uiHash());break}}this._contactContainers(b),a.ui.ddmanager&&a.ui.ddmanager.drag(this,b),this._trigger("sort",b,this._uiHash()),this.lastPositionAbs=this.positionAbs;return!1},_mouseStop:function(b,c){if(!!b){a.ui.ddmanager&&!this.options.dropBehaviour&&a.ui.ddmanager.drop(this,b);if(this.options.revert){var d=this,e=d.placeholder.offset();d.reverting=!0,a(this.helper).animate({left:e.left-this.offset.parent.left-d.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:e.top-this.offset.parent.top-d.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){d._clear(b)})}else this._clear(b,c);return!1}},cancel:function(){var b=this;if(this.dragging){this._mouseUp({target:null}),this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("deactivate",null,b._uiHash(this)),this.containers[c].containerCache.over&&(this.containers[c]._trigger("out",null,b._uiHash(this)),this.containers[c].containerCache.over=0)}this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),a.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?a(this.domPosition.prev).after(this.currentItem):a(this.domPosition.parent).prepend(this.currentItem));return this},serialize:function(b){var c=this._getItemsAsjQuery(b&&b.connected),d=[];b=b||{},a(c).each(function(){var c=(a(b.item||this).attr(b.attribute||"id")||"").match(b.expression||/(.+)[-=_](.+)/);c&&d.push((b.key||c[1]+"[]")+"="+(b.key&&b.expression?c[1]:c[2]))}),!d.length&&b.key&&d.push(b.key+"=");return d.join("&")},toArray:function(b){var c=this._getItemsAsjQuery(b&&b.connected),d=[];b=b||{},c.each(function(){d.push(a(b.item||this).attr(b.attribute||"id")||"")});return d},_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,d=this.positionAbs.top,e=d+this.helperProportions.height,f=a.left,g=f+a.width,h=a.top,i=h+a.height,j=this.offset.click.top,k=this.offset.click.left,l=d+j>h&&d+j<i&&b+k>f&&b+k<g;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers||this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>a[this.floating?"width":"height"]?l:f<b+this.helperProportions.width/2&&c-this.helperProportions.width/2<g&&h<d+this.helperProportions.height/2&&e-this.helperProportions.height/2<i},_intersectsWithPointer:function(b){var c=a.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,b.top,b.height),d=a.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,b.left,b.width),e=c&&d,f=this._getDragVerticalDirection(),g=this._getDragHorizontalDirection();if(!e)return!1;return this.floating?g&&g=="right"||f=="down"?2:1:f&&(f=="down"?2:1)},_intersectsWithSides:function(b){var c=a.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,b.top+b.height/2,b.height),d=a.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,b.left+b.width/2,b.width),e=this._getDragVerticalDirection(),f=this._getDragHorizontalDirection();return this.floating&&f?f=="right"&&d||f=="left"&&!d:e&&(e=="down"&&c||e=="up"&&!c)},_getDragVerticalDirection:function(){var a=this.positionAbs.top-this.lastPositionAbs.top;return a!=0&&(a>0?"down":"up")},_getDragHorizontalDirection:function(){var a=this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a),this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(b){var c=this,d=[],e=[],f=this._connectWith();if(f&&b)for(var g=f.length-1;g>=0;g--){var h=a(f[g]);for(var i=h.length-1;i>=0;i--){var j=a.data(h[i],this.widgetName);j&&j!=this&&!j.options.disabled&&e.push([a.isFunction(j.options.items)?j.options.items.call(j.element):a(j.options.items,j.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),j])}}e.push([a.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):a(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(var g=e.length-1;g>=0;g--)e[g][0].each(function(){d.push(this)});return a(d)},_removeCurrentsFromItems:function(){var a=this.currentItem.find(":data("+this.widgetName+"-item)");for(var b=0;b<this.items.length;b++)for(var c=0;c<a.length;c++)a[c]==this.items[b].item[0]&&this.items.splice(b,1)},_refreshItems:function(b){this.items=[],this.containers=[this];var c=this.items,d=this,e=[[a.isFunction(this.options.items)?this.options.items.call(this.element[0],b,{item:this.currentItem}):a(this.options.items,this.element),this]],f=this._connectWith();if(f&&this.ready)for(var g=f.length-1;g>=0;g--){var h=a(f[g]);for(var i=h.length-1;i>=0;i--){var j=a.data(h[i],this.widgetName);j&&j!=this&&!j.options.disabled&&(e.push([a.isFunction(j.options.items)?j.options.items.call(j.element[0],b,{item:this.currentItem}):a(j.options.items,j.element),j]),this.containers.push(j))}}for(var g=e.length-1;g>=0;g--){var k=e[g][1],l=e[g][0];for(var i=0,m=l.length;i<m;i++){var n=a(l[i]);n.data(this.widgetName+"-item",k),c.push({item:n,instance:k,width:0,height:0,left:0,top:0})}}},refreshPositions:function(b){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());for(var c=this.items.length-1;c>=0;c--){var d=this.items[c];if(d.instance!=this.currentContainer&&this.currentContainer&&d.item[0]!=this.currentItem[0])continue;var e=this.options.toleranceElement?a(this.options.toleranceElement,d.item):d.item;b||(d.width=e.outerWidth(),d.height=e.outerHeight());var f=e.offset();d.left=f.left,d.top=f.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(var c=this.containers.length-1;c>=0;c--){var f=this.containers[c].element.offset();this.containers[c].containerCache.left=f.left,this.containers[c].containerCache.top=f.top,this.containers[c].containerCache.width=this.containers[c].element.outerWidth(),this.containers[c].containerCache.height=this.containers[c].element.outerHeight()}return this},_createPlaceholder:function(b){var c=b||this,d=c.options;if(!d.placeholder||d.placeholder.constructor==String){var e=d.placeholder;d.placeholder={element:function(){var b=a(document.createElement(c.currentItem[0].nodeName)).addClass(e||c.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];e||(b.style.visibility="hidden");return b},update:function(a,b){if(!e||!!d.forcePlaceholderSize)b.height()||b.height(c.currentItem.innerHeight()-parseInt(c.currentItem.css("paddingTop")||0,10)-parseInt(c.currentItem.css("paddingBottom")||0,10)),b.width()||b.width(c.currentItem.innerWidth()-parseInt(c.currentItem.css("paddingLeft")||0,10)-parseInt(c.currentItem.css("paddingRight")||0,10))}}}c.placeholder=a(d.placeholder.element.call(c.element,c.currentItem)),c.currentItem.after(c.placeholder),d.placeholder.update(c,c.placeholder)},_contactContainers:function(b){var c=null,d=null;for(var e=this.containers.length-1;e>=0;e--){if(a.ui.contains(this.currentItem[0],this.containers[e].element[0]))continue;if(this._intersectsWith(this.containers[e].containerCache)){if(c&&a.ui.contains(this.containers[e].element[0],c.element[0]))continue;c=this.containers[e],d=e}else this.containers[e].containerCache.over&&(this.containers[e]._trigger("out",b,this._uiHash(this)),this.containers[e].containerCache.over=0)}if(!!c)if(this.containers.length===1)this.containers[d]._trigger("over",b,this._uiHash(this)),this.containers[d].containerCache.over=1;else if(this.currentContainer!=this.containers[d]){var f=1e4,g=null,h=this.positionAbs[this.containers[d].floating?"left":"top"];for(var i=this.items.length-1;i>=0;i--){if(!a.ui.contains(this.containers[d].element[0],this.items[i].item[0]))continue;var j=this.items[i][this.containers[d].floating?"left":"top"];Math.abs(j-h)<f&&(f=Math.abs(j-h),g=this.items[i])}if(!g&&!this.options.dropOnEmpty)return;this.currentContainer=this.containers[d],g?this._rearrange(b,g,null,!0):this._rearrange(b,null,this.containers[d].element,!0),this._trigger("change",b,this._uiHash()),this.containers[d]._trigger("change",b,this._uiHash(this)),this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[d]._trigger("over",b,this._uiHash(this)),this.containers[d].containerCache.over=1}},_createHelper:function(b){var c=this.options,d=a.isFunction(c.helper)?a(c.helper.apply(this.element[0],[b,this.currentItem])):c.helper=="clone"?this.currentItem.clone():this.currentItem;d.parents("body").length||a(c.appendTo!="parent"?c.appendTo:this.currentItem[0].parentNode)[0].appendChild(d[0]),d[0]==this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(d[0].style.width==""||c.forceHelperSize)&&d.width(this.currentItem.width()),(d[0].style.height==""||c.forceHelperSize)&&d.height(this.currentItem.height());return d},_adjustOffsetFromHelper:function(b){typeof b=="string"&&(b=b.split(" ")),a.isArray(b)&&(b={left:+b[0],top:+b[1]||0}),"left"in b&&(this.offset.click.left=b.left+this.margins.left),"right"in b&&(this.offset.click.left=this.helperProportions.width-b.right+this.margins.left),"top"in b&&(this.offset.click.top=b.top+this.margins.top),"bottom"in b&&(this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])&&(b.left+=this.scrollParent.scrollLeft(),b.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)b={top:0,left:0};return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.currentItem.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var b=this.options;b.containment=="parent"&&(b.containment=this.helper[0].parentNode);if(b.containment=="document"||b.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,a(b.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a(b.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(b.containment)){var c=a(b.containment)[0],d=a(b.containment).offset(),e=a(c).css("overflow")!="hidden";this.containment=[d.left+(parseInt(a(c).css("borderLeftWidth"),10)||0)+(parseInt(a(c).css("paddingLeft"),10)||0)-this.margins.left,d.top+(parseInt(a(c).css("borderTopWidth"),10)||0)+(parseInt(a(c).css("paddingTop"),10)||0)-this.margins.top,d.left+(e?Math.max(c.scrollWidth,c.offsetWidth):c.offsetWidth)-(parseInt(a(c).css("borderLeftWidth"),10)||0)-(parseInt(a(c).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,d.top+(e?Math.max(c.scrollHeight,c.offsetHeight):c.offsetHeight)-(parseInt(a(c).css("borderTopWidth"),10)||0)-(parseInt(a(c).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(b,c){c||(c=this.position);var d=b=="absolute"?1:-1,e=this.options,f=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=/(html|body)/i.test(f[0].tagName);return{top:c.top+this.offset.relative.top*d+this.offset.parent.top*d-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():g?0:f.scrollTop())*d),left:c.left+this.offset.relative.left*d+this.offset.parent.left*d-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:f.scrollLeft())*d)}},_generatePosition:function(b){var c=this.options,d=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(d[0].tagName);this.cssPosition=="relative"&&(this.scrollParent[0]==document||this.scrollParent[0]==this.offsetParent[0])&&(this.offset.relative=this._getRelativeOffset());var f=b.pageX,g=b.pageY;if(this.originalPosition){this.containment&&(b.pageX-this.offset.click.left<this.containment[0]&&(f=this.containment[0]+this.offset.click.left),b.pageY-this.offset.click.top<this.containment[1]&&(g=this.containment[1]+this.offset.click.top),b.pageX-this.offset.click.left>this.containment[2]&&(f=this.containment[2]+this.offset.click.left),b.pageY-this.offset.click.top>this.containment[3]&&(g=this.containment[3]+this.offset.click.top));if(c.grid){var h=this.originalPageY+Math.round((g-this.originalPageY)/c.grid[1])*c.grid[1];g=this.containment?h-this.offset.click.top<this.containment[1]||h-this.offset.click.top>this.containment[3]?h-this.offset.click.top<this.containment[1]?h+c.grid[1]:h-c.grid[1]:h:h;var i=this.originalPageX+Math.round((f-this.originalPageX)/c.grid[0])*c.grid[0];f=this.containment?i-this.offset.click.left<this.containment[0]||i-this.offset.click.left>this.containment[2]?i-this.offset.click.left<this.containment[0]?i+c.grid[0]:i-c.grid[0]:i:i}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(a.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:d.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(a.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:d.scrollLeft())}},_rearrange:function(a,b,c,d){c?c[0].appendChild(this.placeholder[0]):b.item[0].parentNode.insertBefore(this.placeholder[0],this.direction=="down"?b.item[0]:b.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var e=this,f=this.counter;window.setTimeout(function(){f==e.counter&&e.refreshPositions(!d)},0)},_clear:function(b,c){this.reverting=!1;var d=[],e=this;!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var f in this._storedCSS)if(this._storedCSS[f]=="auto"||this._storedCSS[f]=="static")this._storedCSS[f]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();this.fromOutside&&!c&&d.push(function(a){this._trigger("receive",a,this._uiHash(this.fromOutside))}),(this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!=this.currentItem.parent()[0])&&!c&&d.push(function(a){this._trigger("update",a,this._uiHash())});if(!a.ui.contains(this.element[0],this.currentItem[0])){c||d.push(function(a){this._trigger("remove",a,this._uiHash())});for(var f=this.containers.length-1;f>=0;f--)a.ui.contains(this.containers[f].element[0],this.currentItem[0])&&!c&&(d.push(function(a){return function(b){a._trigger("receive",b,this._uiHash(this))}}.call(this,this.containers[f])),d.push(function(a){return function(b){a._trigger("update",b,this._uiHash(this))}}.call(this,this.containers[f])))}for(var f=this.containers.length-1;f>=0;f--)c||d.push(function(a){return function(b){a._trigger("deactivate",b,this._uiHash(this))}}.call(this,this.containers[f])),this.containers[f].containerCache.over&&(d.push(function(a){return function(b){a._trigger("out",b,this._uiHash(this))}}.call(this,this.containers[f])),this.containers[f].containerCache.over=0);this._storedCursor&&a("body").css("cursor",this._storedCursor),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex),this.dragging=!1;if(this.cancelHelperRemoval){if(!c){this._trigger("beforeStop",b,this._uiHash());for(var f=0;f<d.length;f++)d[f].call(this,b);this._trigger("stop",b,this._uiHash())}return!1}c||this._trigger("beforeStop",b,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.helper[0]!=this.currentItem[0]&&this.helper.remove(),this.helper=null;if(!c){for(var f=0;f<d.length;f++)d[f].call(this,b);this._trigger("stop",b,this._uiHash())}this.fromOutside=!1;return!0},_trigger:function(){a.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(b){var c=b||this;return{helper:c.helper,placeholder:c.placeholder||a([]),position:c.position,originalPosition:c.originalPosition,offset:c.positionAbs,item:c.currentItem,sender:b?b.element:null}}}),a.extend(a.ui.sortable,{version:"1.8.18"})})(jQuery);/*
+ * jQuery UI Accordion 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Accordion
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ */(function(a,b){a.widget("ui.accordion",{options:{active:0,animated:"slide",autoHeight:!0,clearStyle:!1,collapsible:!1,event:"click",fillSpace:!1,header:"> li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:!1,navigationFilter:function(){return this.href.toLowerCase()===location.href.toLowerCase()}},_create:function(){var b=this,c=b.options;b.running=0,b.element.addClass("ui-accordion ui-widget ui-helper-reset").children("li").addClass("ui-accordion-li-fix"),b.headers=b.element.find(c.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){c.disabled||a(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){c.disabled||a(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){c.disabled||a(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){c.disabled||a(this).removeClass("ui-state-focus")}),b.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");if(c.navigation){var d=b.element.find("a").filter(c.navigationFilter).eq(0);if(d.length){var e=d.closest(".ui-accordion-header");e.length?b.active=e:b.active=d.closest(".ui-accordion-content").prev()}}b.active=b._findActive(b.active||c.active).addClass("ui-state-default ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top"),b.active.next().addClass("ui-accordion-content-active"),b._createIcons(),b.resize(),b.element.attr("role","tablist"),b.headers.attr("role","tab").bind("keydown.accordion",function(a){return b._keydown(a)}).next().attr("role","tabpanel"),b.headers.not(b.active||"").attr({"aria-expanded":"false","aria-selected":"false",tabIndex:-1}).next().hide(),b.active.length?b.active.attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}):b.headers.eq(0).attr("tabIndex",0),a.browser.safari||b.headers.find("a").attr("tabIndex",-1),c.event&&b.headers.bind(c.event.split(" ").join(".accordion ")+".accordion",function(a){b._clickHandler.call(b,a,this),a.preventDefault()})},_createIcons:function(){var b=this.options;b.icons&&(a("<span></span>").addClass("ui-icon "+b.icons.header).prependTo(this.headers),this.active.children(".ui-icon").toggleClass(b.icons.header).toggleClass(b.icons.headerSelected),this.element.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.children(".ui-icon").remove(),this.element.removeClass("ui-accordion-icons")},destroy:function(){var b=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-selected").removeAttr("tabIndex"),this.headers.find("a").removeAttr("tabIndex"),this._destroyIcons();var c=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled");(b.autoHeight||b.fillHeight)&&c.css("height","");return a.Widget.prototype.destroy.call(this)},_setOption:function(b,c){a.Widget.prototype._setOption.apply(this,arguments),b=="active"&&this.activate(c),b=="icons"&&(this._destroyIcons(),c&&this._createIcons()),b=="disabled"&&this.headers.add(this.headers.next())[c?"addClass":"removeClass"]("ui-accordion-disabled ui-state-disabled")},_keydown:function(b){if(!(this.options.disabled||b.altKey||b.ctrlKey)){var c=a.ui.keyCode,d=this.headers.length,e=this.headers.index(b.target),f=!1;switch(b.keyCode){case c.RIGHT:case c.DOWN:f=this.headers[(e+1)%d];break;case c.LEFT:case c.UP:f=this.headers[(e-1+d)%d];break;case c.SPACE:case c.ENTER:this._clickHandler({target:b.target},b.target),b.preventDefault()}if(f){a(b.target).attr("tabIndex",-1),a(f).attr("tabIndex",0),f.focus();return!1}return!0}},resize:function(){var b=this.options,c;if(b.fillSpace){if(a.browser.msie){var d=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}c=this.element.parent().height(),a.browser.msie&&this.element.parent().css("overflow",d),this.headers.each(function(){c-=a(this).outerHeight(!0)}),this.headers.next().each(function(){a(this).height(Math.max(0,c-a(this).innerHeight()+a(this).height()))}).css("overflow","auto")}else b.autoHeight&&(c=0,this.headers.next().each(function(){c=Math.max(c,a(this).height("").height())}).height(c));return this},activate:function(a){this.options.active=a;var b=this._findActive(a)[0];this._clickHandler({target:b},b);return this},_findActive:function(b){return b?typeof b=="number"?this.headers.filter(":eq("+b+")"):this.headers.not(this.headers.not(b)):b===!1?a([]):this.headers.filter(":eq(0)")},_clickHandler:function(b,c){var d=this.options;if(!d.disabled){if(!b.target){if(!d.collapsible)return;this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header),this.active.next().addClass("ui-accordion-content-active");var e=this.active.next(),f={options:d,newHeader:a([]),oldHeader:d.active,newContent:a([]),oldContent:e},g=this.active=a([]);this._toggle(g,e,f);return}var h=a(b.currentTarget||c),i=h[0]===this.active[0];d.active=d.collapsible&&i?!1:this.headers.index(h);if(this.running||!d.collapsible&&i)return;var j=this.active,g=h.next(),e=this.active.next(),f={options:d,newHeader:i&&d.collapsible?a([]):h,oldHeader:this.active,newContent:i&&d.collapsible?a([]):g,oldContent:e},k=this.headers.index(this.active[0])>this.headers.index(h[0]);this.active=i?a([]):h,this._toggle(g,e,f,i,k),j.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header),i||(h.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").children(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected),h.next().addClass("ui-accordion-content-active"));return}},_toggle:function(b,c,d,e,f){var g=this,h=g.options;g.toShow=b,g.toHide=c,g.data=d;var i=function(){if(!!g)return g._completed.apply(g,arguments)};g._trigger("changestart",null,g.data),g.running=c.size()===0?b.size():c.size();if(h.animated){var j={};h.collapsible&&e?j={toShow:a([]),toHide:c,complete:i,down:f,autoHeight:h.autoHeight||h.fillSpace}:j={toShow:b,toHide:c,complete:i,down:f,autoHeight:h.autoHeight||h.fillSpace},h.proxied||(h.proxied=h.animated),h.proxiedDuration||(h.proxiedDuration=h.duration),h.animated=a.isFunction(h.proxied)?h.proxied(j):h.proxied,h.duration=a.isFunction(h.proxiedDuration)?h.proxiedDuration(j):h.proxiedDuration;var k=a.ui.accordion.animations,l=h.duration,m=h.animated;m&&!k[m]&&!a.easing[m]&&(m="slide"),k[m]||(k[m]=function(a){this.slide(a,{easing:m,duration:l||700})}),k[m](j)}else h.collapsible&&e?b.toggle():(c.hide(),b.show()),i(!0);c.prev().attr({"aria-expanded":"false","aria-selected":"false",tabIndex:-1}).blur(),b.prev().attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}).focus()},_completed:function(a){this.running=a?0:--this.running;this.running||(this.options.clearStyle&&this.toShow.add(this.toHide).css({height:"",overflow:""}),this.toHide.removeClass("ui-accordion-content-active"),this.toHide.length&&(this.toHide.parent()[0].className=this.toHide.parent()[0].className),this._trigger("change",null,this.data))}}),a.extend(a.ui.accordion,{version:"1.8.18",animations:{slide:function(b,c){b=a.extend({easing:"swing",duration:300},b,c);if(!b.toHide.size())b.toShow.animate({height:"show",paddingTop:"show",paddingBottom:"show"},b);else{if(!b.toShow.size()){b.toHide.animate({height:"hide",paddingTop:"hide",paddingBottom:"hide"},b);return}var d=b.toShow.css("overflow"),e=0,f={},g={},h=["height","paddingTop","paddingBottom"],i,j=b.toShow;i=j[0].style.width,j.width(j.parent().width()-parseFloat(j.css("paddingLeft"))-parseFloat(j.css("paddingRight"))-(parseFloat(j.css("borderLeftWidth"))||0)-(parseFloat(j.css("borderRightWidth"))||0)),a.each(h,function(c,d){g[d]="hide";var e=(""+a.css(b.toShow[0],d)).match(/^([\d+-.]+)(.*)$/);f[d]={value:e[1],unit:e[2]||"px"}}),b.toShow.css({height:0,overflow:"hidden"}).show(),b.toHide.filter(":hidden").each(b.complete).end().filter(":visible").animate(g,{step:function(a,c){c.prop=="height"&&(e=c.end-c.start===0?0:(c.now-c.start)/(c.end-c.start)),b.toShow[0].style[c.prop]=e*f[c.prop].value+f[c.prop].unit},duration:b.duration,easing:b.easing,complete:function(){b.autoHeight||b.toShow.css("height",""),b.toShow.css({width:i,overflow:d}),b.complete()}})}},bounceslide:function(a){this.slide(a,{easing:a.down?"easeOutBounce":"swing",duration:a.down?1e3:200})}}})})(jQuery);/*
+ * jQuery UI Autocomplete 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Autocomplete
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ * jquery.ui.position.js
+ */(function(a,b){var c=0;a.widget("ui.autocomplete",{options:{appendTo:"body",autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null},pending:0,_create:function(){var b=this,c=this.element[0].ownerDocument,d;this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(c){if(!b.options.disabled&&!b.element.propAttr("readOnly")){d=!1;var e=a.ui.keyCode;switch(c.keyCode){case e.PAGE_UP:b._move("previousPage",c);break;case e.PAGE_DOWN:b._move("nextPage",c);break;case e.UP:b._move("previous",c),c.preventDefault();break;case e.DOWN:b._move("next",c),c.preventDefault();break;case e.ENTER:case e.NUMPAD_ENTER:b.menu.active&&(d=!0,c.preventDefault());case e.TAB:if(!b.menu.active)return;b.menu.select(c);break;case e.ESCAPE:b.element.val(b.term),b.close(c);break;default:clearTimeout(b.searching),b.searching=setTimeout(function(){b.term!=b.element.val()&&(b.selectedItem=null,b.search(null,c))},b.options.delay)}}}).bind("keypress.autocomplete",function(a){d&&(d=!1,a.preventDefault())}).bind("focus.autocomplete",function(){b.options.disabled||(b.selectedItem=null,b.previous=b.element.val())}).bind("blur.autocomplete",function(a){b.options.disabled||(clearTimeout(b.searching),b.closing=setTimeout(function(){b.close(a),b._change(a)},150))}),this._initSource(),this.response=function(){return b._response.apply(b,arguments)},this.menu=a("<ul></ul>").addClass("ui-autocomplete").appendTo(a(this.options.appendTo||"body",c)[0]).mousedown(function(c){var d=b.menu.element[0];a(c.target).closest(".ui-menu-item").length||setTimeout(function(){a(document).one("mousedown",function(c){c.target!==b.element[0]&&c.target!==d&&!a.ui.contains(d,c.target)&&b.close()})},1),setTimeout(function(){clearTimeout(b.closing)},13)}).menu({focus:function(a,c){var d=c.item.data("item.autocomplete");!1!==b._trigger("focus",a,{item:d})&&/^key/.test(a.originalEvent.type)&&b.element.val(d.value)},selected:function(a,d){var e=d.item.data("item.autocomplete"),f=b.previous;b.element[0]!==c.activeElement&&(b.element.focus(),b.previous=f,setTimeout(function(){b.previous=f,b.selectedItem=e},1)),!1!==b._trigger("select",a,{item:e})&&b.element.val(e.value),b.term=b.element.val(),b.close(a),b.selectedItem=e},blur:function(a,c){b.menu.element.is(":visible")&&b.element.val()!==b.term&&b.element.val(b.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data("menu"),a.fn.bgiframe&&this.menu.element.bgiframe(),b.beforeunloadHandler=function(){b.element.removeAttr("autocomplete")},a(window).bind("beforeunload",b.beforeunloadHandler)},destroy:function(){this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete").removeAttr("role").removeAttr("aria-autocomplete").removeAttr("aria-haspopup"),this.menu.element.remove(),a(window).unbind("beforeunload",this.beforeunloadHandler),a.Widget.prototype.destroy.call(this)},_setOption:function(b,c){a.Widget.prototype._setOption.apply(this,arguments),b==="source"&&this._initSource(),b==="appendTo"&&this.menu.element.appendTo(a(c||"body",this.element[0].ownerDocument)[0]),b==="disabled"&&c&&this.xhr&&this.xhr.abort()},_initSource:function(){var b=this,d,e;a.isArray(this.options.source)?(d=this.options.source,this.source=function(b,c){c(a.ui.autocomplete.filter(d,b.term))}):typeof this.options.source=="string"?(e=this.options.source,this.source=function(d,f){b.xhr&&b.xhr.abort(),b.xhr=a.ajax({url:e,data:d,dataType:"json",context:{autocompleteRequest:++c},success:function(a,b){this.autocompleteRequest===c&&f(a)},error:function(){this.autocompleteRequest===c&&f([])}})}):this.source=this.options.source},search:function(a,b){a=a!=null?a:this.element.val(),this.term=this.element.val();if(a.length<this.options.minLength)return this.close(b);clearTimeout(this.closing);if(this._trigger("search",b)!==!1)return this._search(a)},_search:function(a){this.pending++,this.element.addClass("ui-autocomplete-loading"),this.source({term:a},this.response)},_response:function(a){!this.options.disabled&&a&&a.length?(a=this._normalize(a),this._suggest(a),this._trigger("open")):this.close(),this.pending--,this.pending||this.element.removeClass("ui-autocomplete-loading")},close:function(a){clearTimeout(this.closing),this.menu.element.is(":visible")&&(this.menu.element.hide(),this.menu.deactivate(),this._trigger("close",a))},_change:function(a){this.previous!==this.element.val()&&this._trigger("change",a,{item:this.selectedItem})},_normalize:function(b){if(b.length&&b[0].label&&b[0].value)return b;return a.map(b,function(b){if(typeof b=="string")return{label:b,value:b};return a.extend({label:b.label||b.value,value:b.value||b.label},b)})},_suggest:function(b){var c=this.menu.element.empty().zIndex(this.element.zIndex()+1);this._renderMenu(c,b),this.menu.deactivate(),this.menu.refresh(),c.show(),this._resizeMenu(),c.position(a.extend({of:this.element},this.options.position)),this.options.autoFocus&&this.menu.next(new a.Event("mouseover"))},_resizeMenu:function(){var a=this.menu.element;a.outerWidth(Math.max(a.width("").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(b,c){var d=this;a.each(c,function(a,c){d._renderItem(b,c)})},_renderItem:function(b,c){return a("<li></li>").data("item.autocomplete",c).append(a("<a></a>").text(c.label)).appendTo(b)},_move:function(a,b){if(!this.menu.element.is(":visible"))this.search(null,b);else{if(this.menu.first()&&/^previous/.test(a)||this.menu.last()&&/^next/.test(a)){this.element.val(this.term),this.menu.deactivate();return}this.menu[a](b)}},widget:function(){return this.menu.element}}),a.extend(a.ui.autocomplete,{escapeRegex:function(a){return a.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&")},filter:function(b,c){var d=new RegExp(a.ui.autocomplete.escapeRegex(c),"i");return a.grep(b,function(a){return d.test(a.label||a.value||a)})}})})(jQuery),function(a){a.widget("ui.menu",{_create:function(){var b=this;this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr({role:"listbox","aria-activedescendant":"ui-active-menuitem"}).click(function(c){!a(c.target).closest(".ui-menu-item a").length||(c.preventDefault(),b.select(c))}),this.refresh()},refresh:function(){var b=this,c=this.element.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","menuitem");c.children("a").addClass("ui-corner-all").attr("tabindex",-1).mouseenter(function(c){b.activate(c,a(this).parent())}).mouseleave(function(){b.deactivate()})},activate:function(a,b){this.deactivate();if(this.hasScroll()){var c=b.offset().top-this.element.offset().top,d=this.element.scrollTop(),e=this.element.height();c<0?this.element.scrollTop(d+c):c>=e&&this.element.scrollTop(d+c-e+b.height())}this.active=b.eq(0).children("a").addClass("ui-state-hover").attr("id","ui-active-menuitem").end(),this._trigger("focus",a,{item:b})},deactivate:function(){!this.active||(this.active.children("a").removeClass("ui-state-hover").removeAttr("id"),this._trigger("blur"),this.active=null)},next:function(a){this.move("next",".ui-menu-item:first",a)},previous:function(a){this.move("prev",".ui-menu-item:last",a)},first:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},last:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},move:function(a,b,c){if(!this.active)this.activate(c,this.element.children(b));else{var d=this.active[a+"All"](".ui-menu-item").eq(0);d.length?this.activate(c,d):this.activate(c,this.element.children(b))}},nextPage:function(b){if(this.hasScroll()){if(!this.active||this.last()){this.activate(b,this.element.children(".ui-menu-item:first"));return}var c=this.active.offset().top,d=this.element.height(),e=this.element.children(".ui-menu-item").filter(function(){var b=a(this).offset().top-c-d+a(this).height();return b<10&&b>-10});e.length||(e=this.element.children(".ui-menu-item:last")),this.activate(b,e)}else this.activate(b,this.element.children(".ui-menu-item").filter(!this.active||this.last()?":first":":last"))},previousPage:function(b){if(this.hasScroll()){if(!this.active||this.first()){this.activate(b,this.element.children(".ui-menu-item:last"));return}var c=this.active.offset().top,d=this.element.height();result=this.element.children(".ui-menu-item").filter(function(){var b=a(this).offset().top-c+d-a(this).height();return b<10&&b>-10}),result.length||(result=this.element.children(".ui-menu-item:first")),this.activate(b,result)}else this.activate(b,this.element.children(".ui-menu-item").filter(!this.active||this.first()?":last":":first"))},hasScroll:function(){return this.element.height()<this.element[a.fn.prop?"prop":"attr"]("scrollHeight")},select:function(a){this._trigger("selected",a,{item:this.active})}})}(jQuery);/*
+ * jQuery UI Button 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Button
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ */(function(a,b){var c,d,e,f,g="ui-button ui-widget ui-state-default ui-corner-all",h="ui-state-hover ui-state-active ",i="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",j=function(){var b=a(this).find(":ui-button");setTimeout(function(){b.button("refresh")},1)},k=function(b){var c=b.name,d=b.form,e=a([]);c&&(d?e=a(d).find("[name='"+c+"']"):e=a("[name='"+c+"']",b.ownerDocument).filter(function(){return!this.form}));return e};a.widget("ui.button",{options:{disabled:null,text:!0,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset.button").bind("reset.button",j),typeof this.options.disabled!="boolean"?this.options.disabled=!!this.element.propAttr("disabled"):this.element.propAttr("disabled",this.options.disabled),this._determineButtonType(),this.hasTitle=!!this.buttonElement.attr("title");var b=this,h=this.options,i=this.type==="checkbox"||this.type==="radio",l="ui-state-hover"+(i?"":" ui-state-active"),m="ui-state-focus";h.label===null&&(h.label=this.buttonElement.html()),this.buttonElement.addClass(g).attr("role","button").bind("mouseenter.button",function(){h.disabled||(a(this).addClass("ui-state-hover"),this===c&&a(this).addClass("ui-state-active"))}).bind("mouseleave.button",function(){h.disabled||a(this).removeClass(l)}).bind("click.button",function(a){h.disabled&&(a.preventDefault(),a.stopImmediatePropagation())}),this.element.bind("focus.button",function(){b.buttonElement.addClass(m)}).bind("blur.button",function(){b.buttonElement.removeClass(m)}),i&&(this.element.bind("change.button",function(){f||b.refresh()}),this.buttonElement.bind("mousedown.button",function(a){h.disabled||(f=!1,d=a.pageX,e=a.pageY)}).bind("mouseup.button",function(a){!h.disabled&&(d!==a.pageX||e!==a.pageY)&&(f=!0)})),this.type==="checkbox"?this.buttonElement.bind("click.button",function(){if(h.disabled||f)return!1;a(this).toggleClass("ui-state-active"),b.buttonElement.attr("aria-pressed",b.element[0].checked)}):this.type==="radio"?this.buttonElement.bind("click.button",function(){if(h.disabled||f)return!1;a(this).addClass("ui-state-active"),b.buttonElement.attr("aria-pressed","true");var c=b.element[0];k(c).not(c).map(function(){return a(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed","false")}):(this.buttonElement.bind("mousedown.button",function(){if(h.disabled)return!1;a(this).addClass("ui-state-active"),c=this,a(document).one("mouseup",function(){c=null})}).bind("mouseup.button",function(){if(h.disabled)return!1;a(this).removeClass("ui-state-active")}).bind("keydown.button",function(b){if(h.disabled)return!1;(b.keyCode==a.ui.keyCode.SPACE||b.keyCode==a.ui.keyCode.ENTER)&&a(this).addClass("ui-state-active")}).bind("keyup.button",function(){a(this).removeClass("ui-state-active")}),this.buttonElement.is("a")&&this.buttonElement.keyup(function(b){b.keyCode===a.ui.keyCode.SPACE&&a(this).click()})),this._setOption("disabled",h.disabled),this._resetButton()},_determineButtonType:function(){this.element.is(":checkbox")?this.type="checkbox":this.element.is(":radio")?this.type="radio":this.element.is("input")?this.type="input":this.type="button";if(this.type==="checkbox"||this.type==="radio"){var a=this.element.parents().filter(":last"),b="label[for='"+this.element.attr("id")+"']";this.buttonElement=a.find(b),this.buttonElement.length||(a=a.length?a.siblings():this.element.siblings(),this.buttonElement=a.filter(b),this.buttonElement.length||(this.buttonElement=a.find(b))),this.element.addClass("ui-helper-hidden-accessible");var c=this.element.is(":checked");c&&this.buttonElement.addClass("ui-state-active"),this.buttonElement.attr("aria-pressed",c)}else this.buttonElement=this.element},widget:function(){return this.buttonElement},destroy:function(){this.element.removeClass("ui-helper-hidden-accessible"),this.buttonElement.removeClass(g+" "+h+" "+i).removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()),this.hasTitle||this.buttonElement.removeAttr("title"),a.Widget.prototype.destroy.call(this)},_setOption:function(b,c){a.Widget.prototype._setOption.apply(this,arguments);b==="disabled"?c?this.element.propAttr("disabled",!0):this.element.propAttr("disabled",!1):this._resetButton()},refresh:function(){var b=this.element.is(":disabled");b!==this.options.disabled&&this._setOption("disabled",b),this.type==="radio"?k(this.element[0]).each(function(){a(this).is(":checked")?a(this).button("widget").addClass("ui-state-active").attr("aria-pressed","true"):a(this).button("widget").removeClass("ui-state-active").attr("aria-pressed","false")}):this.type==="checkbox"&&(this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed","true"):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed","false"))},_resetButton:function(){if(this.type==="input")this.options.label&&this.element.val(this.options.label);else{var b=this.buttonElement.removeClass(i),c=a("<span></span>",this.element[0].ownerDocument).addClass("ui-button-text").html(this.options.label).appendTo(b.empty()).text(),d=this.options.icons,e=d.primary&&d.secondary,f=[];d.primary||d.secondary?(this.options.text&&f.push("ui-button-text-icon"+(e?"s":d.primary?"-primary":"-secondary")),d.primary&&b.prepend("<span class='ui-button-icon-primary ui-icon "+d.primary+"'></span>"),d.secondary&&b.append("<span class='ui-button-icon-secondary ui-icon "+d.secondary+"'></span>"),this.options.text||(f.push(e?"ui-button-icons-only":"ui-button-icon-only"),this.hasTitle||b.attr("title",c))):f.push("ui-button-text-only"),b.addClass(f.join(" "))}}}),a.widget("ui.buttonset",{options:{items:":button, :submit, :reset, :checkbox, :radio, a, :data(button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(b,c){b==="disabled"&&this.buttons.button("option",b,c),a.Widget.prototype._setOption.apply(this,arguments)},refresh:function(){var b=this.element.css("direction")==="rtl";this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(b?"ui-corner-right":"ui-corner-left").end().filter(":last").addClass(b?"ui-corner-left":"ui-corner-right").end().end()},destroy:function(){this.element.removeClass("ui-buttonset"),this.buttons.map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy"),a.Widget.prototype.destroy.call(this)}})})(jQuery);/*
+ * jQuery UI Dialog 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Dialog
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ * jquery.ui.button.js
+ * jquery.ui.draggable.js
+ * jquery.ui.mouse.js
+ * jquery.ui.position.js
+ * jquery.ui.resizable.js
+ */(function(a,b){var c="ui-dialog ui-widget ui-widget-content ui-corner-all ",d={buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},e={maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0},f=a.attrFn||{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0,click:!0};a.widget("ui.dialog",{options:{autoOpen:!0,buttons:{},closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:!1,maxWidth:!1,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",collision:"fit",using:function(b){var c=a(this).css(b).offset().top;c<0&&a(this).css("top",b.top-c)}},resizable:!0,show:null,stack:!0,title:"",width:300,zIndex:1e3},_create:function(){this.originalTitle=this.element.attr("title"),typeof this.originalTitle!="string"&&(this.originalTitle=""),this.options.title=this.options.title||this.originalTitle;var b=this,d=b.options,e=d.title||"&#160;",f=a.ui.dialog.getTitleId(b.element),g=(b.uiDialog=a("<div></div>")).appendTo(document.body).hide().addClass(c+d.dialogClass).css({zIndex:d.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(c){d.closeOnEscape&&!c.isDefaultPrevented()&&c.keyCode&&c.keyCode===a.ui.keyCode.ESCAPE&&(b.close(c),c.preventDefault())}).attr({role:"dialog","aria-labelledby":f}).mousedown(function(a){b.moveToTop(!1,a)}),h=b.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(g),i=(b.uiDialogTitlebar=a("<div></div>")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(g),j=a('<a href="#"></a>').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){j.addClass("ui-state-hover")},function(){j.removeClass("ui-state-hover")}).focus(function(){j.addClass("ui-state-focus")}).blur(function(){j.removeClass("ui-state-focus")}).click(function(a){b.close(a);return!1}).appendTo(i),k=(b.uiDialogTitlebarCloseText=a("<span></span>")).addClass("ui-icon ui-icon-closethick").text(d.closeText).appendTo(j),l=a("<span></span>").addClass("ui-dialog-title").attr("id",f).html(e).prependTo(i);a.isFunction(d.beforeclose)&&!a.isFunction(d.beforeClose)&&(d.beforeClose=d.beforeclose),i.find("*").add(i).disableSelection(),d.draggable&&a.fn.draggable&&b._makeDraggable(),d.resizable&&a.fn.resizable&&b._makeResizable(),b._createButtons(d.buttons),b._isOpen=!1,a.fn.bgiframe&&g.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var a=this;a.overlay&&a.overlay.destroy(),a.uiDialog.hide(),a.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"),a.uiDialog.remove(),a.originalTitle&&a.element.attr("title",a.originalTitle);return a},widget:function(){return this.uiDialog},close:function(b){var c=this,d,e;if(!1!==c._trigger("beforeClose",b)){c.overlay&&c.overlay.destroy(),c.uiDialog.unbind("keypress.ui-dialog"),c._isOpen=!1,c.options.hide?c.uiDialog.hide(c.options.hide,function(){c._trigger("close",b)}):(c.uiDialog.hide(),c._trigger("close",b)),a.ui.dialog.overlay.resize(),c.options.modal&&(d=0,a(".ui-dialog").each(function(){this!==c.uiDialog[0]&&(e=a(this).css("z-index"),isNaN(e)||(d=Math.max(d,e)))}),a.ui.dialog.maxZ=d);return c}},isOpen:function(){return this._isOpen},moveToTop:function(b,c){var d=this,e=d.options,f;if(e.modal&&!b||!e.stack&&!e.modal)return d._trigger("focus",c);e.zIndex>a.ui.dialog.maxZ&&(a.ui.dialog.maxZ=e.zIndex),d.overlay&&(a.ui.dialog.maxZ+=1,d.overlay.$el.css("z-index",a.ui.dialog.overlay.maxZ=a.ui.dialog.maxZ)),f={scrollTop:d.element.scrollTop(),scrollLeft:d.element.scrollLeft()},a.ui.dialog.maxZ+=1,d.uiDialog.css("z-index",a.ui.dialog.maxZ),d.element.attr(f),d._trigger("focus",c);return d},open:function(){if(!this._isOpen){var b=this,c=b.options,d=b.uiDialog;b.overlay=c.modal?new a.ui.dialog.overlay(b):null,b._size(),b._position(c.position),d.show(c.show),b.moveToTop(!0),c.modal&&d.bind("keydown.ui-dialog",function(b){if(b.keyCode===a.ui.keyCode.TAB){var c=a(":tabbable",this),d=c.filter(":first"),e=c.filter(":last");if(b.target===e[0]&&!b.shiftKey){d.focus(1);return!1}if(b.target===d[0]&&b.shiftKey){e.focus(1);return!1}}}),a(b.element.find(":tabbable").get().concat(d.find(".ui-dialog-buttonpane :tabbable").get().concat(d.get()))).eq(0).focus(),b._isOpen=!0,b._trigger("open");return b}},_createButtons:function(b){var c=this,d=!1,e=a("<div></div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),g=a("<div></div>").addClass("ui-dialog-buttonset").appendTo(e);c.uiDialog.find(".ui-dialog-buttonpane").remove(),typeof b=="object"&&b!==null&&a.each(b,function(){return!(d=!0)}),d&&(a.each(b,function(b,d){d=a.isFunction(d)?{click:d,text:b}:d;var e=a('<button type="button"></button>').click(function(){d.click.apply(c.element[0],arguments)}).appendTo(g);a.each(d,function(a,b){a!=="click"&&(a in f?e[a](b):e.attr(a,b))}),a.fn.button&&e.button()}),e.appendTo(c.uiDialog))},_makeDraggable:function(){function f(a){return{position:a.position,offset:a.offset}}var b=this,c=b.options,d=a(document),e;b.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(d,g){e=c.height==="auto"?"auto":a(this).height(),a(this).height(a(this).height()).addClass("ui-dialog-dragging"),b._trigger("dragStart",d,f(g))},drag:function(a,c){b._trigger("drag",a,f(c))},stop:function(g,h){c.position=[h.position.left-d.scrollLeft(),h.position.top-d.scrollTop()],a(this).removeClass("ui-dialog-dragging").height(e),b._trigger("dragStop",g,f(h)),a.ui.dialog.overlay.resize()}})},_makeResizable:function(c){function h(a){return{originalPosition:a.originalPosition,originalSize:a.originalSize,position:a.position,size:a.size}}c=c===b?this.options.resizable:c;var d=this,e=d.options,f=d.uiDialog.css("position"),g=typeof c=="string"?c:"n,e,s,w,se,sw,ne,nw";d.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:d.element,maxWidth:e.maxWidth,maxHeight:e.maxHeight,minWidth:e.minWidth,minHeight:d._minHeight(),handles:g,start:function(b,c){a(this).addClass("ui-dialog-resizing"),d._trigger("resizeStart",b,h(c))},resize:function(a,b){d._trigger("resize",a,h(b))},stop:function(b,c){a(this).removeClass("ui-dialog-resizing"),e.height=a(this).height(),e.width=a(this).width(),d._trigger("resizeStop",b,h(c)),a.ui.dialog.overlay.resize()}}).css("position",f).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var a=this.options;return a.height==="auto"?a.minHeight:Math.min(a.minHeight,a.height)},_position:function(b){var c=[],d=[0,0],e;if(b){if(typeof b=="string"||typeof b=="object"&&"0"in b)c=b.split?b.split(" "):[b[0],b[1]],c.length===1&&(c[1]=c[0]),a.each(["left","top"],function(a,b){+c[a]===c[a]&&(d[a]=c[a],c[a]=b)}),b={my:c.join(" "),at:c.join(" "),offset:d.join(" ")};b=a.extend({},a.ui.dialog.prototype.options.position,b)}else b=a.ui.dialog.prototype.options.position;e=this.uiDialog.is(":visible"),e||this.uiDialog.show(),this.uiDialog.css({top:0,left:0}).position(a.extend({of:window},b)),e||this.uiDialog.hide()},_setOptions:function(b){var c=this,f={},g=!1;a.each(b,function(a,b){c._setOption(a,b),a in d&&(g=!0),a in e&&(f[a]=b)}),g&&this._size(),this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",f)},_setOption:function(b,d){var e=this,f=e.uiDialog;switch(b){case"beforeclose":b="beforeClose";break;case"buttons":e._createButtons(d);break;case"closeText":e.uiDialogTitlebarCloseText.text(""+d);break;case"dialogClass":f.removeClass(e.options.dialogClass).addClass(c+d);break;case"disabled":d?f.addClass("ui-dialog-disabled"):f.removeClass("ui-dialog-disabled");break;case"draggable":var g=f.is(":data(draggable)");g&&!d&&f.draggable("destroy"),!g&&d&&e._makeDraggable();break;case"position":e._position(d);break;case"resizable":var h=f.is(":data(resizable)");h&&!d&&f.resizable("destroy"),h&&typeof d=="string"&&f.resizable("option","handles",d),!h&&d!==!1&&e._makeResizable(d);break;case"title":a(".ui-dialog-title",e.uiDialogTitlebar).html(""+(d||"&#160;"))}a.Widget.prototype._setOption.apply(e,arguments)},_size:function(){var b=this.options,c,d,e=this.uiDialog.is(":visible");this.element.show().css({width:"auto",minHeight:0,height:0}),b.minWidth>b.width&&(b.width=b.minWidth),c=this.uiDialog.css({height:"auto",width:b.width}).height(),d=Math.max(0,b.minHeight-c);if(b.height==="auto")if(a.support.minHeight)this.element.css({minHeight:d,height:"auto"});else{this.uiDialog.show();var f=this.element.css("height","auto").height();e||this.uiDialog.hide(),this.element.height(Math.max(f,d))}else this.element.height(Math.max(b.height-c,0));this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}}),a.extend(a.ui.dialog,{version:"1.8.18",uuid:0,maxZ:0,getTitleId:function(a){var b=a.attr("id");b||(this.uuid+=1,b=this.uuid);return"ui-dialog-title-"+b},overlay:function(b){this.$el=a.ui.dialog.overlay.create(b)}}),a.extend(a.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:a.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(a){return a+".dialog-overlay"}).join(" "),create:function(b){this.instances.length===0&&(setTimeout(function(){a.ui.dialog.overlay.instances.length&&a(document).bind(a.ui.dialog.overlay.events,function(b){if(a(b.target).zIndex()<a.ui.dialog.overlay.maxZ)return!1})},1),a(document).bind("keydown.dialog-overlay",function(c){b.options.closeOnEscape&&!c.isDefaultPrevented()&&c.keyCode&&c.keyCode===a.ui.keyCode.ESCAPE&&(b.close(c),c.preventDefault())}),a(window).bind("resize.dialog-overlay",a.ui.dialog.overlay.resize));var c=(this.oldInstances.pop()||a("<div></div>").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),height:this.height()});a.fn.bgiframe&&c.bgiframe(),this.instances.push(c);return c},destroy:function(b){var c=a.inArray(b,this.instances);c!=-1&&this.oldInstances.push(this.instances.splice(c,1)[0]),this.instances.length===0&&a([document,window]).unbind(".dialog-overlay"),b.remove();var d=0;a.each(this.instances,function(){d=Math.max(d,this.css("z-index"))}),this.maxZ=d},height:function(){var b,c;if(a.browser.msie&&a.browser.version<7){b=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),c=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);return b<c?a(window).height()+"px":b+"px"}return a(document).height()+"px"},width:function(){var b,c;if(a.browser.msie){b=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth),c=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth);return b<c?a(window).width()+"px":b+"px"}return a(document).width()+"px"},resize:function(){var b=a([]);a.each(a.ui.dialog.overlay.instances,function(){b=b.add(this)}),b.css({width:0,height:0}).css({width:a.ui.dialog.overlay.width(),height:a.ui.dialog.overlay.height()})}}),a.extend(a.ui.dialog.overlay.prototype,{destroy:function(){a.ui.dialog.overlay.destroy(this.$el)}})})(jQuery);/*
+ * jQuery UI Slider 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Slider
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
+ */(function(a,b){var c=5;a.widget("ui.slider",a.ui.mouse,{widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null},_create:function(){var b=this,d=this.options,e=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),f="<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",g=d.values&&d.values.length||1,h=[];this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"+(d.disabled?" ui-slider-disabled ui-disabled":"")),this.range=a([]),d.range&&(d.range===!0&&(d.values||(d.values=[this._valueMin(),this._valueMin()]),d.values.length&&d.values.length!==2&&(d.values=[d.values[0],d.values[0]])),this.range=a("<div></div>").appendTo(this.element).addClass("ui-slider-range ui-widget-header"+(d.range==="min"||d.range==="max"?" ui-slider-range-"+d.range:"")));for(var i=e.length;i<g;i+=1)h.push(f);this.handles=e.add(a(h.join("")).appendTo(b.element)),this.handle=this.handles.eq(0),this.handles.add(this.range).filter("a").click(function(a){a.preventDefault()}).hover(function(){d.disabled||a(this).addClass("ui-state-hover")},function(){a(this).removeClass("ui-state-hover")}).focus(function(){d.disabled?a(this).blur():(a(".ui-slider .ui-state-focus").removeClass("ui-state-focus"),a(this).addClass("ui-state-focus"))}).blur(function(){a(this).removeClass("ui-state-focus")}),this.handles.each(function(b){a(this).data("index.ui-slider-handle",b)}),this.handles.keydown(function(d){var e=a(this).data("index.ui-slider-handle"),f,g,h,i;if(!b.options.disabled){switch(d.keyCode){case a.ui.keyCode.HOME:case a.ui.keyCode.END:case a.ui.keyCode.PAGE_UP:case a.ui.keyCode.PAGE_DOWN:case a.ui.keyCode.UP:case a.ui.keyCode.RIGHT:case a.ui.keyCode.DOWN:case a.ui.keyCode.LEFT:d.preventDefault();if(!b._keySliding){b._keySliding=!0,a(this).addClass("ui-state-active"),f=b._start(d,e);if(f===!1)return}}i=b.options.step,b.options.values&&b.options.values.length?g=h=b.values(e):g=h=b.value();switch(d.keyCode){case a.ui.keyCode.HOME:h=b._valueMin();break;case a.ui.keyCode.END:h=b._valueMax();break;case a.ui.keyCode.PAGE_UP:h=b._trimAlignValue(g+(b._valueMax()-b._valueMin())/c);break;case a.ui.keyCode.PAGE_DOWN:h=b._trimAlignValue(g-(b._valueMax()-b._valueMin())/c);break;case a.ui.keyCode.UP:case a.ui.keyCode.RIGHT:if(g===b._valueMax())return;h=b._trimAlignValue(g+i);break;case a.ui.keyCode.DOWN:case a.ui.keyCode.LEFT:if(g===b._valueMin())return;h=b._trimAlignValue(g-i)}b._slide(d,e,h)}}).keyup(function(c){var d=a(this).data("index.ui-slider-handle");b._keySliding&&(b._keySliding=!1,b._stop(c,d),b._change(c,d),a(this).removeClass("ui-state-active"))}),this._refreshValue(),this._animateOff=!1},destroy:function(){this.handles.remove(),this.range.remove(),this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider"),this._mouseDestroy();return this},_mouseCapture:function(b){var c=this.options,d,e,f,g,h,i,j,k,l;if(c.disabled)return!1;this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),d={x:b.pageX,y:b.pageY},e=this._normValueFromMouse(d),f=this._valueMax()-this._valueMin()+1,h=this,this.handles.each(function(b){var c=Math.abs(e-h.values(b));f>c&&(f=c,g=a(this),i=b)}),c.range===!0&&this.values(1)===c.min&&(i+=1,g=a(this.handles[i])),j=this._start(b,i);if(j===!1)return!1;this._mouseSliding=!0,h._handleIndex=i,g.addClass("ui-state-active").focus(),k=g.offset(),l=!a(b.target).parents().andSelf().is(".ui-slider-handle"),this._clickOffset=l?{left:0,top:0}:{left:b.pageX-k.left-g.width()/2,top:b.pageY-k.top-g.height()/2-(parseInt(g.css("borderTopWidth"),10)||0)-(parseInt(g.css("borderBottomWidth"),10)||0)+(parseInt(g.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(b,i,e),this._animateOff=!0;return!0},_mouseStart:function(a){return!0},_mouseDrag:function(a){var b={x:a.pageX,y:a.pageY},c=this._normValueFromMouse(b);this._slide(a,this._handleIndex,c);return!1},_mouseStop:function(a){this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(a,this._handleIndex),this._change(a,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1;return!1},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(a){var b,c,d,e,f;this.orientation==="horizontal"?(b=this.elementSize.width,c=a.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(b=this.elementSize.height,c=a.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),d=c/b,d>1&&(d=1),d<0&&(d=0),this.orientation==="vertical"&&(d=1-d),e=this._valueMax()-this._valueMin(),f=this._valueMin()+d*e;return this._trimAlignValue(f)},_start:function(a,b){var c={handle:this.handles[b],value:this.value()};this.options.values&&this.options.values.length&&(c.value=this.values(b),c.values=this.values());return this._trigger("start",a,c)},_slide:function(a,b,c){var d,e,f;this.options.values&&this.options.values.length?(d=this.values(b?0:1),this.options.values.length===2&&this.options.range===!0&&(b===0&&c>d||b===1&&c<d)&&(c=d),c!==this.values(b)&&(e=this.values(),e[b]=c,f=this._trigger("slide",a,{handle:this.handles[b],value:c,values:e}),d=this.values(b?0:1),f!==!1&&this.values(b,c,!0))):c!==this.value()&&(f=this._trigger("slide",a,{handle:this.handles[b],value:c}),f!==!1&&this.value(c))},_stop:function(a,b){var c={handle:this.handles[b],value:this.value()};this.options.values&&this.options.values.length&&(c.value=this.values(b),c.values=this.values()),this._trigger("stop",a,c)},_change:function(a,b){if(!this._keySliding&&!this._mouseSliding){var c={handle:this.handles[b],value:this.value()};this.options.values&&this.options.values.length&&(c.value=this.values(b),c.values=this.values()),this._trigger("change",a,c)}},value:function(a){if(arguments.length)this.options.value=this._trimAlignValue(a),this._refreshValue(),this._change(null,0);else return this._value()},values:function(b,c){var d,e,f;if(arguments.length>1)this.options.values[b]=this._trimAlignValue(c),this._refreshValue(),this._change(null,b);else{if(!arguments.length)return this._values();if(!a.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(b):this.value();d=this.options.values,e=arguments[0];for(f=0;f<d.length;f+=1)d[f]=this._trimAlignValue(e[f]),this._change(null,f);this._refreshValue()}},_setOption:function(b,c){var d,e=0;a.isArray(this.options.values)&&(e=this.options.values.length),a.Widget.prototype._setOption.apply(this,arguments);switch(b){case"disabled":c?(this.handles.filter(".ui-state-focus").blur(),this.handles.removeClass("ui-state-hover"),this.handles.propAttr("disabled",!0),this.element.addClass("ui-disabled")):(this.handles.propAttr("disabled",!1),this.element.removeClass("ui-disabled"));break;case"orientation":this._detectOrientation(),this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation),this._refreshValue();break;case"value":this._animateOff=!0,this._refreshValue(),this._change(null,0),this._animateOff=!1;break;case"values":this._animateOff=!0,this._refreshValue();for(d=0;d<e;d+=1)this._change(null,d);this._animateOff=!1}},_value:function(){var a=this.options.value;a=this._trimAlignValue(a);return a},_values:function(a){var b,c,d;if(arguments.length){b=this.options.values[a],b=this._trimAlignValue(b);return b}c=this.options.values.slice();for(d=0;d<c.length;d+=1)c[d]=this._trimAlignValue(c[d]);return c},_trimAlignValue:function(a){if(a<=this._valueMin())return this._valueMin();if(a>=this._valueMax())return this._valueMax();var b=this.options.step>0?this.options.step:1,c=(a-this._valueMin())%b,d=a-c;Math.abs(c)*2>=b&&(d+=c>0?b:-b);return parseFloat(d.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var b=this.options.range,c=this.options,d=this,e=this._animateOff?!1:c.animate,f,g={},h,i,j,k;this.options.values&&this.options.values.length?this.handles.each(function(b,i){f=(d.values(b)-d._valueMin())/(d._valueMax()-d._valueMin())*100,g[d.orientation==="horizontal"?"left":"bottom"]=f+"%",a(this).stop(1,1)[e?"animate":"css"](g,c.animate),d.options.range===!0&&(d.orientation==="horizontal"?(b===0&&d.range.stop(1,1)[e?"animate":"css"]({left:f+"%"},c.animate),b===1&&d.range[e?"animate":"css"]({width:f-h+"%"},{queue:!1,duration:c.animate})):(b===0&&d.range.stop(1,1)[e?"animate":"css"]({bottom:f+"%"},c.animate),b===1&&d.range[e?"animate":"css"]({height:f-h+"%"},{queue:!1,duration:c.animate}))),h=f}):(i=this.value(),j=this._valueMin(),k=this._valueMax(),f=k!==j?(i-j)/(k-j)*100:0,g[d.orientation==="horizontal"?"left":"bottom"]=f+"%",this.handle.stop(1,1)[e?"animate":"css"](g,c.animate),b==="min"&&this.orientation==="horizontal"&&this.range.stop(1,1)[e?"animate":"css"]({width:f+"%"},c.animate),b==="max"&&this.orientation==="horizontal"&&this.range[e?"animate":"css"]({width:100-f+"%"},{queue:!1,duration:c.animate}),b==="min"&&this.orientation==="vertical"&&this.range.stop(1,1)[e?"animate":"css"]({height:f+"%"},c.animate),b==="max"&&this.orientation==="vertical"&&this.range[e?"animate":"css"]({height:100-f+"%"},{queue:!1,duration:c.animate}))}}),a.extend(a.ui.slider,{version:"1.8.18"})})(jQuery);/*
+ * jQuery UI Tabs 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Tabs
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ */(function(a,b){function f(){return++d}function e(){return++c}var c=0,d=0;a.widget("ui.tabs",{options:{add:null,ajaxOptions:null,cache:!1,cookie:null,collapsible:!1,disable:null,disabled:[],enable:null,event:"click",fx:null,idPrefix:"ui-tabs-",load:null,panelTemplate:"<div></div>",remove:null,select:null,show:null,spinner:"<em>Loading&#8230;</em>",tabTemplate:"<li><a href='#{href}'><span>#{label}</span></a></li>"},_create:function(){this._tabify(!0)},_setOption:function(a,b){if(a=="selected"){if(this.options.collapsible&&b==this.options.selected)return;this.select(b)}else this.options[a]=b,this._tabify()},_tabId:function(a){return a.title&&a.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF-]/g,"")||this.options.idPrefix+e()},_sanitizeSelector:function(a){return a.replace(/:/g,"\\:")},_cookie:function(){var b=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+f());return a.cookie.apply(null,[b].concat(a.makeArray(arguments)))},_ui:function(a,b){return{tab:a,panel:b,index:this.anchors.index(a)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var b=a(this);b.html(b.data("label.tabs")).removeData("label.tabs")})},_tabify:function(c){function m(b,c){b.css("display",""),!a.support.opacity&&c.opacity&&b[0].style.removeAttribute("filter")}var d=this,e=this.options,f=/^#.+/;this.list=this.element.find("ol,ul").eq(0),this.lis=a(" > li:has(a[href])",this.list),this.anchors=this.lis.map(function(){return a("a",this)[0]}),this.panels=a([]),this.anchors.each(function(b,c){var g=a(c).attr("href"),h=g.split("#")[0],i;h&&(h===location.toString().split("#")[0]||(i=a("base")[0])&&h===i.href)&&(g=c.hash,c.href=g);if(f.test(g))d.panels=d.panels.add(d.element.find(d._sanitizeSelector(g)));else if(g&&g!=="#"){a.data(c,"href.tabs",g),a.data(c,"load.tabs",g.replace(/#.*$/,""));var j=d._tabId(c);c.href="#"+j;var k=d.element.find("#"+j);k.length||(k=a(e.panelTemplate).attr("id",j).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(d.panels[b-1]||d.list),k.data("destroy.tabs",!0)),d.panels=d.panels.add(k)}else e.disabled.push(b)}),c?(this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all"),this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all"),this.lis.addClass("ui-state-default ui-corner-top"),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom"),e.selected===b?(location.hash&&this.anchors.each(function(a,b){if(b.hash==location.hash){e.selected=a;return!1}}),typeof e.selected!="number"&&e.cookie&&(e.selected=parseInt(d._cookie(),10)),typeof e.selected!="number"&&this.lis.filter(".ui-tabs-selected").length&&(e.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"))),e.selected=e.selected||(this.lis.length?0:-1)):e.selected===null&&(e.selected=-1),e.selected=e.selected>=0&&this.anchors[e.selected]||e.selected<0?e.selected:0,e.disabled=a.unique(e.disabled.concat(a.map(this.lis.filter(".ui-state-disabled"),function(a,b){return d.lis.index(a)}))).sort(),a.inArray(e.selected,e.disabled)!=-1&&e.disabled.splice(a.inArray(e.selected,e.disabled),1),this.panels.addClass("ui-tabs-hide"),this.lis.removeClass("ui-tabs-selected ui-state-active"),e.selected>=0&&this.anchors.length&&(d.element.find(d._sanitizeSelector(d.anchors[e.selected].hash)).removeClass("ui-tabs-hide"),this.lis.eq(e.selected).addClass("ui-tabs-selected ui-state-active"),d.element.queue("tabs",function(){d._trigger("show",null,d._ui(d.anchors[e.selected],d.element.find(d._sanitizeSelector(d.anchors[e.selected].hash))[0]))}),this.load(e.selected)),a(window).bind("unload",function(){d.lis.add(d.anchors).unbind(".tabs"),d.lis=d.anchors=d.panels=null})):e.selected=this.lis.index(this.lis.filter(".ui-tabs-selected")),this.element[e.collapsible?"addClass":"removeClass"]("ui-tabs-collapsible"),e.cookie&&this._cookie(e.selected,e.cookie);for(var g=0,h;h=this.lis[g];g++)a(h)[a.inArray(g,e.disabled)!=-1&&!a(h).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled");e.cache===!1&&this.anchors.removeData("cache.tabs"),this.lis.add(this.anchors).unbind(".tabs");if(e.event!=="mouseover"){var i=function(a,b){b.is(":not(.ui-state-disabled)")&&b.addClass("ui-state-"+a)},j=function(a,b){b.removeClass("ui-state-"+a)};this.lis.bind("mouseover.tabs",function(){i("hover",a(this))}),this.lis.bind("mouseout.tabs",function(){j("hover",a(this))}),this.anchors.bind("focus.tabs",function(){i("focus",a(this).closest("li"))}),this.anchors.bind("blur.tabs",function(){j("focus",a(this).closest("li"))})}var k,l;e.fx&&(a.isArray(e.fx)?(k=e.fx[0],l=e.fx[1]):k=l=e.fx);var n=l?function(b,c){a(b).closest("li").addClass("ui-tabs-selected ui-state-active"),c.hide().removeClass("ui-tabs-hide").animate(l,l.duration||"normal",function(){m(c,l),d._trigger("show",null,d._ui(b,c[0]))})}:function(b,c){a(b).closest("li").addClass("ui-tabs-selected ui-state-active"),c.removeClass("ui-tabs-hide"),d._trigger("show",null,d._ui(b,c[0]))},o=k?function(a,b){b.animate(k,k.duration||"normal",function(){d.lis.removeClass("ui-tabs-selected ui-state-active"),b.addClass("ui-tabs-hide"),m(b,k),d.element.dequeue("tabs")})}:function(a,b,c){d.lis.removeClass("ui-tabs-selected ui-state-active"),b.addClass("ui-tabs-hide"),d.element.dequeue("tabs")};this.anchors.bind(e.event+".tabs",function(){var b=this,c=a(b).closest("li"),f=d.panels.filter(":not(.ui-tabs-hide)"),g=d.element.find(d._sanitizeSelector(b.hash));if(c.hasClass("ui-tabs-selected")&&!e.collapsible||c.hasClass("ui-state-disabled")||c.hasClass("ui-state-processing")||d.panels.filter(":animated").length||d._trigger("select",null,d._ui(this,g[0]))===!1){this.blur();return!1}e.selected=d.anchors.index(this),d.abort();if(e.collapsible){if(c.hasClass("ui-tabs-selected")){e.selected=-1,e.cookie&&d._cookie(e.selected,e.cookie),d.element.queue("tabs",function(){o(b,f)}).dequeue("tabs"),this.blur();return!1}if(!f.length){e.cookie&&d._cookie(e.selected,e.cookie),d.element.queue("tabs",function(){n(b,g)}),d.load(d.anchors.index(this)),this.blur();return!1}}e.cookie&&d._cookie(e.selected,e.cookie);if(g.length)f.length&&d.element.queue("tabs",function(){o(b,f)}),d.element.queue("tabs",function(){n(b,g)}),d.load(d.anchors.index(this));else throw"jQuery UI Tabs: Mismatching fragment identifier.";a.browser.msie&&this.blur()}),this.anchors.bind("click.tabs",function(){return!1})},_getIndex:function(a){typeof a=="string"&&(a=this.anchors.index(this.anchors.filter("[href$="+a+"]")));return a},destroy:function(){var b=this.options;this.abort(),this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs"),this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all"),this.anchors.each(function(){var b=a.data(this,"href.tabs");b&&(this.href=b);var c=a(this).unbind(".tabs");a.each(["href","load","cache"],function(a,b){c.removeData(b+".tabs")})}),this.lis.unbind(".tabs").add(this.panels).each(function(){a.data(this,"destroy.tabs")?a(this).remove():a(this).removeClass(["ui-state-default","ui-corner-top","ui-tabs-selected","ui-state-active","ui-state-hover","ui-state-focus","ui-state-disabled","ui-tabs-panel","ui-widget-content","ui-corner-bottom","ui-tabs-hide"].join(" "))}),b.cookie&&this._cookie(null,b.cookie);return this},add:function(c,d,e){e===b&&(e=this.anchors.length);var f=this,g=this.options,h=a(g.tabTemplate.replace(/#\{href\}/g,c).replace(/#\{label\}/g,d)),i=c.indexOf("#")?this._tabId(a("a",h)[0]):c.replace("#","");h.addClass("ui-state-default ui-corner-top").data("destroy.tabs",!0);var j=f.element.find("#"+i);j.length||(j=a(g.panelTemplate).attr("id",i).data("destroy.tabs",!0)),j.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide"),e>=this.lis.length?(h.appendTo(this.list),j.appendTo(this.list[0].parentNode)):(h.insertBefore(this.lis[e]),j.insertBefore(this.panels[e])),g.disabled=a.map(g.disabled,function(a,b){return a>=e?++a:a}),this._tabify(),this.anchors.length==1&&(g.selected=0,h.addClass("ui-tabs-selected ui-state-active"),j.removeClass("ui-tabs-hide"),this.element.queue("tabs",function(){f._trigger("show",null,f._ui(f.anchors[0],f.panels[0]))}),this.load(0)),this._trigger("add",null,this._ui(this.anchors[e],this.panels[e]));return this},remove:function(b){b=this._getIndex(b);var c=this.options,d=this.lis.eq(b).remove(),e=this.panels.eq(b).remove();d.hasClass("ui-tabs-selected")&&this.anchors.length>1&&this.select(b+(b+1<this.anchors.length?1:-1)),c.disabled=a.map(a.grep(c.disabled,function(a,c){return a!=b}),function(a,c){return a>=b?--a:a}),this._tabify(),this._trigger("remove",null,this._ui(d.find("a")[0],e[0]));return this},enable:function(b){b=this._getIndex(b);var c=this.options;if(a.inArray(b,c.disabled)!=-1){this.lis.eq(b).removeClass("ui-state-disabled"),c.disabled=a.grep(c.disabled,function(a,c){return a!=b}),this._trigger("enable",null,this._ui(this.anchors[b],this.panels[b]));return this}},disable:function(a){a=this._getIndex(a);var b=this,c=this.options;a!=c.selected&&(this.lis.eq(a).addClass("ui-state-disabled"),c.disabled.push(a),c.disabled.sort(),this._trigger("disable",null,this._ui(this.anchors[a],this.panels[a])));return this},select:function(a){a=this._getIndex(a);if(a==-1)if(this.options.collapsible&&this.options.selected!=-1)a=this.options.selected;else return this;this.anchors.eq(a).trigger(this.options.event+".tabs");return this},load:function(b){b=this._getIndex(b);var c=this,d=this.options,e=this.anchors.eq(b)[0],f=a.data(e,"load.tabs");this.abort();if(!f||this.element.queue("tabs").length!==0&&a.data(e,"cache.tabs"))this.element.dequeue("tabs");else{this.lis.eq(b).addClass("ui-state-processing");if(d.spinner){var g=a("span",e);g.data("label.tabs",g.html()).html(d.spinner)}this.xhr=a.ajax(a.extend({},d.ajaxOptions,{url:f,success:function(f,g){c.element.find(c._sanitizeSelector(e.hash)).html(f),c._cleanup(),d.cache&&a.data(e,"cache.tabs",!0),c._trigger("load",null,c._ui(c.anchors[b],c.panels[b]));try{d.ajaxOptions.success(f,g)}catch(h){}},error:function(a,f,g){c._cleanup(),c._trigger("load",null,c._ui(c.anchors[b],c.panels[b]));try{d.ajaxOptions.error(a,f,b,e)}catch(g){}}})),c.element.dequeue("tabs");return this}},abort:function(){this.element.queue([]),this.panels.stop(!1,!0),this.element.queue("tabs",this.element.queue("tabs").splice(-2,2)),this.xhr&&(this.xhr.abort(),delete this.xhr),this._cleanup();return this},url:function(a,b){this.anchors.eq(a).removeData("cache.tabs").data("load.tabs",b);return this},length:function(){return this.anchors.length}}),a.extend(a.ui.tabs,{version:"1.8.18"}),a.extend(a.ui.tabs.prototype,{rotation:null,rotate:function(a,b){var c=this,d=this.options,e=c._rotate||(c._rotate=function(b){clearTimeout(c.rotation),c.rotation=setTimeout(function(){var a=d.selected;c.select(++a<c.anchors.length?a:0)},a),b&&b.stopPropagation()}),f=c._unrotate||(c._unrotate=b?function(a){t=d.selected,e()}:function(a){a.clientX&&c.rotate(null)});a?(this.element.bind("tabsshow",e),this.anchors.bind(d.event+".tabs",f),e()):(clearTimeout(c.rotation),this.element.unbind("tabsshow",e),this.anchors.unbind(d.event+".tabs",f),delete this._rotate,delete this._unrotate);return this}})})(jQuery);/*
+ * jQuery UI Datepicker 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Datepicker
+ *
+ * Depends:
+ * jquery.ui.core.js
+ */(function($,undefined){function isArray(a){return a&&($.browser.safari&&typeof a=="object"&&a.length||a.constructor&&a.constructor.toString().match(/\Array\(\)/))}function extendRemove(a,b){$.extend(a,b);for(var c in b)if(b[c]==null||b[c]==undefined)a[c]=b[c];return a}function bindHover(a){var b="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return a.bind("mouseout",function(a){var c=$(a.target).closest(b);!c.length||c.removeClass("ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover")}).bind("mouseover",function(c){var d=$(c.target).closest(b);!$.datepicker._isDisabledDatepicker(instActive.inline?a.parent()[0]:instActive.input[0])&&!!d.length&&(d.parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),d.addClass("ui-state-hover"),d.hasClass("ui-datepicker-prev")&&d.addClass("ui-datepicker-prev-hover"),d.hasClass("ui-datepicker-next")&&d.addClass("ui-datepicker-next-hover"))})}function Datepicker(){this.debug=!1,this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},$.extend(this._defaults,this.regional[""]),this.dpDiv=bindHover($('<div id="'+this._mainDivId+'" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))}$.extend($.ui,{datepicker:{version:"1.8.18"}});var PROP_NAME="datepicker",dpuuid=(new Date).getTime(),instActive;$.extend(Datepicker.prototype,{markerClassName:"hasDatepicker",maxRows:4,log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(a){extendRemove(this._defaults,a||{});return this},_attachDatepicker:function(target,settings){var inlineSettings=null;for(var attrName in this._defaults){var attrValue=target.getAttribute("date:"+attrName);if(attrValue){inlineSettings=inlineSettings||{};try{inlineSettings[attrName]=eval(attrValue)}catch(err){inlineSettings[attrName]=attrValue}}}var nodeName=target.nodeName.toLowerCase(),inline=nodeName=="div"||nodeName=="span";target.id||(this.uuid+=1,target.id="dp"+this.uuid);var inst=this._newInst($(target),inline);inst.settings=$.extend({},settings||{},inlineSettings||{}),nodeName=="input"?this._connectDatepicker(target,inst):inline&&this._inlineDatepicker(target,inst)},_newInst:function(a,b){var c=a[0].id.replace(/([^A-Za-z0-9_-])/g,"\\\\$1");return{id:c,input:a,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:b,dpDiv:b?bindHover($('<div class="'+this._inlineClass+' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')):this.dpDiv}},_connectDatepicker:function(a,b){var c=$(a);b.append=$([]),b.trigger=$([]);c.hasClass(this.markerClassName)||(this._attachments(c,b),c.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker",function(a,c,d){b.settings[c]=d}).bind("getData.datepicker",function(a,c){return this._get(b,c)}),this._autoSize(b),$.data(a,PROP_NAME,b),b.settings.disabled&&this._disableDatepicker(a))},_attachments:function(a,b){var c=this._get(b,"appendText"),d=this._get(b,"isRTL");b.append&&b.append.remove(),c&&(b.append=$('<span class="'+this._appendClass+'">'+c+"</span>"),a[d?"before":"after"](b.append)),a.unbind("focus",this._showDatepicker),b.trigger&&b.trigger.remove();var e=this._get(b,"showOn");(e=="focus"||e=="both")&&a.focus(this._showDatepicker);if(e=="button"||e=="both"){var f=this._get(b,"buttonText"),g=this._get(b,"buttonImage");b.trigger=$(this._get(b,"buttonImageOnly")?$("<img/>").addClass(this._triggerClass).attr({src:g,alt:f,title:f}):$('<button type="button"></button>').addClass(this._triggerClass).html(g==""?f:$("<img/>").attr({src:g,alt:f,title:f}))),a[d?"before":"after"](b.trigger),b.trigger.click(function(){$.datepicker._datepickerShowing&&$.datepicker._lastInput==a[0]?$.datepicker._hideDatepicker():$.datepicker._datepickerShowing&&$.datepicker._lastInput!=a[0]?($.datepicker._hideDatepicker(),$.datepicker._showDatepicker(a[0])):$.datepicker._showDatepicker(a[0]);return!1})}},_autoSize:function(a){if(this._get(a,"autoSize")&&!a.inline){var b=new Date(2009,11,20),c=this._get(a,"dateFormat");if(c.match(/[DM]/)){var d=function(a){var b=0,c=0;for(var d=0;d<a.length;d++)a[d].length>b&&(b=a[d].length,c=d);return c};b.setMonth(d(this._get(a,c.match(/MM/)?"monthNames":"monthNamesShort"))),b.setDate(d(this._get(a,c.match(/DD/)?"dayNames":"dayNamesShort"))+20-b.getDay())}a.input.attr("size",this._formatDate(a,b).length)}},_inlineDatepicker:function(a,b){var c=$(a);c.hasClass(this.markerClassName)||(c.addClass(this.markerClassName).append(b.dpDiv).bind("setData.datepicker",function(a,c,d){b.settings[c]=d}).bind("getData.datepicker",function(a,c){return this._get(b,c)}),$.data(a,PROP_NAME,b),this._setDate(b,this._getDefaultDate(b),!0),this._updateDatepicker(b),this._updateAlternate(b),b.settings.disabled&&this._disableDatepicker(a),b.dpDiv.css("display","block"))},_dialogDatepicker:function(a,b,c,d,e){var f=this._dialogInst;if(!f){this.uuid+=1;var g="dp"+this.uuid;this._dialogInput=$('<input type="text" id="'+g+'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>'),this._dialogInput.keydown(this._doKeyDown),$("body").append(this._dialogInput),f=this._dialogInst=this._newInst(this._dialogInput,!1),f.settings={},$.data(this._dialogInput[0],PROP_NAME,f)}extendRemove(f.settings,d||{}),b=b&&b.constructor==Date?this._formatDate(f,b):b,this._dialogInput.val(b),this._pos=e?e.length?e:[e.pageX,e.pageY]:null;if(!this._pos){var h=document.documentElement.clientWidth,i=document.documentElement.clientHeight,j=document.documentElement.scrollLeft||document.body.scrollLeft,k=document.documentElement.scrollTop||document.body.scrollTop;this._pos=[h/2-100+j,i/2-150+k]}this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),f.settings.onSelect=c,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),$.blockUI&&$.blockUI(this.dpDiv),$.data(this._dialogInput[0],PROP_NAME,f);return this},_destroyDatepicker:function(a){var b=$(a),c=$.data(a,PROP_NAME);if(!!b.hasClass(this.markerClassName)){var d=a.nodeName.toLowerCase();$.removeData(a,PROP_NAME),d=="input"?(c.append.remove(),c.trigger.remove(),b.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):(d=="div"||d=="span")&&b.removeClass(this.markerClassName).empty()}},_enableDatepicker:function(a){var b=$(a),c=$.data(a,PROP_NAME);if(!!b.hasClass(this.markerClassName)){var d=a.nodeName.toLowerCase();if(d=="input")a.disabled=!1,c.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""});else if(d=="div"||d=="span"){var e=b.children("."+this._inlineClass);e.children().removeClass("ui-state-disabled"),e.find("select.ui-datepicker-month, select.ui-datepicker-year").removeAttr("disabled")}this._disabledInputs=$.map(this._disabledInputs,function(b){return b==a?null:b})}},_disableDatepicker:function(a){var b=$(a),c=$.data(a,PROP_NAME);if(!!b.hasClass(this.markerClassName)){var d=a.nodeName.toLowerCase();if(d=="input")a.disabled=!0,c.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"});else if(d=="div"||d=="span"){var e=b.children("."+this._inlineClass);e.children().addClass("ui-state-disabled"),e.find("select.ui-datepicker-month, select.ui-datepicker-year").attr("disabled","disabled")}this._disabledInputs=$.map(this._disabledInputs,function(b){return b==a?null:b}),this._disabledInputs[this._disabledInputs.length]=a}},_isDisabledDatepicker:function(a){if(!a)return!1;for(var b=0;b<this._disabledInputs.length;b++)if(this._disabledInputs[b]==a)return!0;return!1},_getInst:function(a){try{return $.data(a,PROP_NAME)}catch(b){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(a,b,c){var d=this._getInst(a);if(arguments.length==2&&typeof b=="string")return b=="defaults"?$.extend({},$.datepicker._defaults):d?b=="all"?$.extend({},d.settings):this._get(d,b):null;var e=b||{};typeof b=="string"&&(e={},e[b]=c);if(d){this._curInst==d&&this._hideDatepicker();var f=this._getDateDatepicker(a,!0),g=this._getMinMaxDate(d,"min"),h=this._getMinMaxDate(d,"max");extendRemove(d.settings,e),g!==null&&e.dateFormat!==undefined&&e.minDate===undefined&&(d.settings.minDate=this._formatDate(d,g)),h!==null&&e.dateFormat!==undefined&&e.maxDate===undefined&&(d.settings.maxDate=this._formatDate(d,h)),this._attachments($(a),d),this._autoSize(d),this._setDate(d,f),this._updateAlternate(d),this._updateDatepicker(d)}},_changeDatepicker:function(a,b,c){this._optionDatepicker(a,b,c)},_refreshDatepicker:function(a){var b=this._getInst(a);b&&this._updateDatepicker(b)},_setDateDatepicker:function(a,b){var c=this._getInst(a);c&&(this._setDate(c,b),this._updateDatepicker(c),this._updateAlternate(c))},_getDateDatepicker:function(a,b){var c=this._getInst(a);c&&!c.inline&&this._setDateFromField(c,b);return c?this._getDate(c):null},_doKeyDown:function(a){var b=$.datepicker._getInst(a.target),c=!0,d=b.dpDiv.is(".ui-datepicker-rtl");b._keyEvent=!0;if($.datepicker._datepickerShowing)switch(a.keyCode){case 9:$.datepicker._hideDatepicker(),c=!1;break;case 13:var e=$("td."+$.datepicker._dayOverClass+":not(."+$.datepicker._currentClass+")",b.dpDiv);e[0]&&$.datepicker._selectDay(a.target,b.selectedMonth,b.selectedYear,e[0]);var f=$.datepicker._get(b,"onSelect");if(f){var g=$.datepicker._formatDate(b);f.apply(b.input?b.input[0]:null,[g,b])}else $.datepicker._hideDatepicker();return!1;case 27:$.datepicker._hideDatepicker();break;case 33:$.datepicker._adjustDate(a.target,a.ctrlKey?-$.datepicker._get(b,"stepBigMonths"):-$.datepicker._get(b,"stepMonths"),"M");break;case 34:$.datepicker._adjustDate(a.target,a.ctrlKey?+$.datepicker._get(b,"stepBigMonths"):+$.datepicker._get(b,"stepMonths"),"M");break;case 35:(a.ctrlKey||a.metaKey)&&$.datepicker._clearDate(a.target),c=a.ctrlKey||a.metaKey;break;case 36:(a.ctrlKey||a.metaKey)&&$.datepicker._gotoToday(a.target),c=a.ctrlKey||a.metaKey;break;case 37:(a.ctrlKey||a.metaKey)&&$.datepicker._adjustDate(a.target,d?1:-1,"D"),c=a.ctrlKey||a.metaKey,a.originalEvent.altKey&&$.datepicker._adjustDate(a.target,a.ctrlKey?-$.datepicker._get(b,"stepBigMonths"):-$.datepicker._get(b,"stepMonths"),"M");break;case 38:(a.ctrlKey||a.metaKey)&&$.datepicker._adjustDate(a.target,-7,"D"),c=a.ctrlKey||a.metaKey;break;case 39:(a.ctrlKey||a.metaKey)&&$.datepicker._adjustDate(a.target,d?-1:1,"D"),c=a.ctrlKey||a.metaKey,a.originalEvent.altKey&&$.datepicker._adjustDate(a.target,a.ctrlKey?+$.datepicker._get(b,"stepBigMonths"):+$.datepicker._get(b,"stepMonths"),"M");break;case 40:(a.ctrlKey||a.metaKey)&&$.datepicker._adjustDate(a.target,7,"D"),c=a.ctrlKey||a.metaKey;break;default:c=!1}else a.keyCode==36&&a.ctrlKey?$.datepicker._showDatepicker(this):c=!1;c&&(a.preventDefault(),a.stopPropagation())},_doKeyPress:function(a){var b=$.datepicker._getInst(a.target);if($.datepicker._get(b,"constrainInput")){var c=$.datepicker._possibleChars($.datepicker._get(b,"dateFormat")),d=String.fromCharCode(a.charCode==undefined?a.keyCode:a.charCode);return a.ctrlKey||a.metaKey||d<" "||!c||c.indexOf(d)>-1}},_doKeyUp:function(a){var b=$.datepicker._getInst(a.target);if(b.input.val()!=b.lastVal)try{var c=$.datepicker.parseDate($.datepicker._get(b,"dateFormat"),b.input?b.input.val():null,$.datepicker._getFormatConfig(b));c&&($.datepicker._setDateFromField(b),$.datepicker._updateAlternate(b),$.datepicker._updateDatepicker(b))}catch(a){$.datepicker.log(a)}return!0},_showDatepicker:function(a){a=a.target||a,a.nodeName.toLowerCase()!="input"&&(a=$("input",a.parentNode)[0]);if(!$.datepicker._isDisabledDatepicker(a)&&$.datepicker._lastInput!=a){var b=$.datepicker._getInst(a);$.datepicker._curInst&&$.datepicker._curInst!=b&&($.datepicker._curInst.dpDiv.stop(!0,!0),b&&$.datepicker._datepickerShowing&&$.datepicker._hideDatepicker($.datepicker._curInst.input[0]));var c=$.datepicker._get(b,"beforeShow"),d=c?c.apply(a,[a,b]):{};if(d===!1)return;extendRemove(b.settings,d),b.lastVal=null,$.datepicker._lastInput=a,$.datepicker._setDateFromField(b),$.datepicker._inDialog&&(a.value=""),$.datepicker._pos||($.datepicker._pos=$.datepicker._findPos(a),$.datepicker._pos[1]+=a.offsetHeight);var e=!1;$(a).parents().each(function(){e|=$(this).css("position")=="fixed";return!e}),e&&$.browser.opera&&($.datepicker._pos[0]-=document.documentElement.scrollLeft,$.datepicker._pos[1]-=document.documentElement.scrollTop);var f={left:$.datepicker._pos[0],top:$.datepicker._pos[1]};$.datepicker._pos=null,b.dpDiv.empty(),b.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),$.datepicker._updateDatepicker(b),f=$.datepicker._checkOffset(b,f,e),b.dpDiv.css({position:$.datepicker._inDialog&&$.blockUI?"static":e?"fixed":"absolute",display:"none",left:f.left+"px",top:f.top+"px"});if(!b.inline){var g=$.datepicker._get(b,"showAnim"),h=$.datepicker._get(b,"duration"),i=function(){var a=b.dpDiv.find("iframe.ui-datepicker-cover");if(!!a.length){var c=$.datepicker._getBorders(b.dpDiv);a.css({left:-c[0],top:-c[1],width:b.dpDiv.outerWidth(),height:b.dpDiv.outerHeight()})}};b.dpDiv.zIndex($(a).zIndex()+1),$.datepicker._datepickerShowing=!0,$.effects&&$.effects[g]?b.dpDiv.show(g,$.datepicker._get(b,"showOptions"),h,i):b.dpDiv[g||"show"](g?h:null,i),(!g||!h)&&i(),b.input.is(":visible")&&!b.input.is(":disabled")&&b.input.focus(),$.datepicker._curInst=b}}},_updateDatepicker:function(a){var b=this;b.maxRows=4;var c=$.datepicker._getBorders(a.dpDiv);instActive=a,a.dpDiv.empty().append(this._generateHTML(a));var d=a.dpDiv.find("iframe.ui-datepicker-cover");!d.length||d.css({left:-c[0],top:-c[1],width:a.dpDiv.outerWidth(),height:a.dpDiv.outerHeight()}),a.dpDiv.find("."+this._dayOverClass+" a").mouseover();var e=this._getNumberOfMonths(a),f=e[1],g=17;a.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),f>1&&a.dpDiv.addClass("ui-datepicker-multi-"+f).css("width",g*f+"em"),a.dpDiv[(e[0]!=1||e[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi"),a.dpDiv[(this._get(a,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),a==$.datepicker._curInst&&$.datepicker._datepickerShowing&&a.input&&a.input.is(":visible")&&!a.input.is(":disabled")&&a.input[0]!=document.activeElement&&a.input.focus();if(a.yearshtml){var h=a.yearshtml;setTimeout(function(){h===a.yearshtml&&a.yearshtml&&a.dpDiv.find("select.ui-datepicker-year:first").replaceWith(a.yearshtml),h=a.yearshtml=null},0)}},_getBorders:function(a){var b=function(a){return{thin:1,medium:2,thick:3}[a]||a};return[parseFloat(b(a.css("border-left-width"))),parseFloat(b(a.css("border-top-width")))]},_checkOffset:function(a,b,c){var d=a.dpDiv.outerWidth(),e=a.dpDiv.outerHeight(),f=a.input?a.input.outerWidth():0,g=a.input?a.input.outerHeight():0,h=document.documentElement.clientWidth+$(document).scrollLeft(),i=document.documentElement.clientHeight+$(document).scrollTop();b.left-=this._get(a,"isRTL")?d-f:0,b.left-=c&&b.left==a.input.offset().left?$(document).scrollLeft():0,b.top-=c&&b.top==a.input.offset().top+g?$(document).scrollTop():0,b.left-=Math.min(b.left,b.left+d>h&&h>d?Math.abs(b.left+d-h):0),b.top-=Math.min(b.top,b.top+e>i&&i>e?Math.abs(e+g):0);return b},_findPos:function(a){var b=this._getInst(a),c=this._get(b,"isRTL");while(a&&(a.type=="hidden"||a.nodeType!=1||$.expr.filters.hidden(a)))a=a[c?"previousSibling":"nextSibling"];var d=$(a).offset();return[d.left,d.top]},_hideDatepicker:function(a){var b=this._curInst;if(!(!b||a&&b!=$.data(a,PROP_NAME))&&this._datepickerShowing){var c=this._get(b,"showAnim"),d=this._get(b,"duration"),e=this,f=function(){$.datepicker._tidyDialog(b),e._curInst=null};$.effects&&$.effects[c]?b.dpDiv.hide(c,$.datepicker._get(b,"showOptions"),d,f):b.dpDiv[c=="slideDown"?"slideUp":c=="fadeIn"?"fadeOut":"hide"](c?d:null,f),c||f(),this._datepickerShowing=!1;var g=this._get(b,"onClose");g&&g.apply(b.input?b.input[0]:null,[b.input?b.input.val():"",b]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),$.blockUI&&($.unblockUI(),$("body").append(this.dpDiv))),this._inDialog=!1}},_tidyDialog:function(a){a.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(a){if(!!$.datepicker._curInst){var b=$(a.target),c=$.datepicker._getInst(b[0]);(b[0].id!=$.datepicker._mainDivId&&b.parents("#"+$.datepicker._mainDivId).length==0&&!b.hasClass($.datepicker.markerClassName)&&!b.closest("."+$.datepicker._triggerClass).length&&$.datepicker._datepickerShowing&&(!$.datepicker._inDialog||!$.blockUI)||b.hasClass($.datepicker.markerClassName)&&$.datepicker._curInst!=c)&&$.datepicker._hideDatepicker()}},_adjustDate:function(a,b,c){var d=$(a),e=this._getInst(d[0]);this._isDisabledDatepicker(d[0])||(this._adjustInstDate(e,b+(c=="M"?this._get(e,"showCurrentAtPos"):0),c),this._updateDatepicker(e))},_gotoToday:function(a){var b=$(a),c=this._getInst(b[0]);if(this._get(c,"gotoCurrent")&&c.currentDay)c.selectedDay=c.currentDay,c.drawMonth=c.selectedMonth=c.currentMonth,c.drawYear=c.selectedYear=c.currentYear;else{var d=new Date;c.selectedDay=d.getDate(),c.drawMonth=c.selectedMonth=d.getMonth(),c.drawYear=c.selectedYear=d.getFullYear()}this._notifyChange(c),this._adjustDate(b)},_selectMonthYear:function(a,b,c){var d=$(a),e=this._getInst(d[0]);e["selected"+(c=="M"?"Month":"Year")]=e["draw"+(c=="M"?"Month":"Year")]=parseInt(b.options[b.selectedIndex].value,10),this._notifyChange(e),this._adjustDate(d)},_selectDay:function(a,b,c,d){var e=$(a);if(!$(d).hasClass(this._unselectableClass)&&!this._isDisabledDatepicker(e[0])){var f=this._getInst(e[0]);f.selectedDay=f.currentDay=$("a",d).html(),f.selectedMonth=f.currentMonth=b,f.selectedYear=f.currentYear=c,this._selectDate(a,this._formatDate(f,f.currentDay,f.currentMonth,f.currentYear))}},_clearDate:function(a){var b=$(a),c=this._getInst(b[0]);this._selectDate(b,"")},_selectDate:function(a,b){var c=$(a),d=this._getInst(c[0]);b=b!=null?b:this._formatDate(d),d.input&&d.input.val(b),this._updateAlternate(d);var e=this._get(d,"onSelect");e?e.apply(d.input?d.input[0]:null,[b,d]):d.input&&d.input.trigger("change"),d.inline?this._updateDatepicker(d):(this._hideDatepicker(),this._lastInput=d.input[0],typeof d.input[0]!="object"&&d.input.focus(),this._lastInput=null)},_updateAlternate:function(a){var b=this._get(a,"altField");if(b){var c=this._get(a,"altFormat")||this._get(a,"dateFormat"),d=this._getDate(a),e=this.formatDate(c,d,this._getFormatConfig(a));$(b).each(function(){$(this).val(e)})}},noWeekends:function(a){var b=a.getDay();return[b>0&&b<6,""]},iso8601Week:function(a){var b=new Date(a.getTime());b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();b.setMonth(0),b.setDate(1);return Math.floor(Math.round((c-b)/864e5)/7)+1},parseDate:function(a,b,c){if(a==null||b==null)throw"Invalid arguments";b=typeof b=="object"?b.toString():b+"";if(b=="")return null;var d=(c?c.shortYearCutoff:null)||this._defaults.shortYearCutoff;d=typeof d!="string"?d:(new Date).getFullYear()%100+parseInt(d,10);var e=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,f=(c?c.dayNames:null)||this._defaults.dayNames,g=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,h=(c?c.monthNames:null)||this._defaults.monthNames,i=-1,j=-1,k=-1,l=-1,m=!1,n=function(b){var c=s+1<a.length&&a.charAt(s+1)==b;c&&s++;return c},o=function(a){var c=n(a),d=a=="@"?14:a=="!"?20:a=="y"&&c?4:a=="o"?3:2,e=new RegExp("^\\d{1,"+d+"}"),f=b.substring(r).match(e);if(!f)throw"Missing number at position "+r;r+=f[0].length;return parseInt(f[0],10)},p=function(a,c,d){var e=$.map(n(a)?d:c,function(a,b){return[[b,a]]}).sort(function(a,b){return-(a[1].length-b[1].length)}),f=-1;$.each(e,function(a,c){var d=c[1];if(b.substr(r,d.length).toLowerCase()==d.toLowerCase()){f=c[0],r+=d.length;return!1}});if(f!=-1)return f+1;throw"Unknown name at position "+r},q=function(){if(b.charAt(r)!=a.charAt(s))throw"Unexpected literal at position "+r;r++},r=0;for(var s=0;s<a.length;s++)if(m)a.charAt(s)=="'"&&!n("'")?m=!1:q();else switch(a.charAt(s)){case"d":k=o("d");break;case"D":p("D",e,f);break;case"o":l=o("o");break;case"m":j=o("m");break;case"M":j=p("M",g,h);break;case"y":i=o("y");break;case"@":var t=new Date(o("@"));i=t.getFullYear(),j=t.getMonth()+1,k=t.getDate();break;case"!":var t=new Date((o("!")-this._ticksTo1970)/1e4);i=t.getFullYear(),j=t.getMonth()+1,k=t.getDate();break;case"'":n("'")?q():m=!0;break;default:q()}if(r<b.length)throw"Extra/unparsed characters found in date: "+b.substring(r);i==-1?i=(new Date).getFullYear():i<100&&(i+=(new Date).getFullYear()-(new Date).getFullYear()%100+(i<=d?0:-100));if(l>-1){j=1,k=l;for(;;){var u=this._getDaysInMonth(i,j-1);if(k<=u)break;j++,k-=u}}var t=this._daylightSavingAdjust(new Date(i,j-1,k));if(t.getFullYear()!=i||t.getMonth()+1!=j||t.getDate()!=k)throw"Invalid date";return t},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1e7,formatDate:function(a,b,c){if(!b)return"";var d=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,e=(c?c.dayNames:null)||this._defaults.dayNames,f=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,g=(c?c.monthNames:null)||this._defaults.monthNames,h=function(b){var c=m+1<a.length&&a.charAt(m+1)==b;c&&m++;return c},i=function(a,b,c){var d=""+b;if(h(a))while(d.length<c)d="0"+d;return d},j=function(a,b,c,d){return h(a)?d[b]:c[b]},k="",l=!1;if(b)for(var m=0;m<a.length;m++)if(l)a.charAt(m)=="'"&&!h("'")?l=!1:k+=a.charAt(m);else switch(a.charAt(m)){case"d":k+=i("d",b.getDate(),2);break;case"D":k+=j("D",b.getDay(),d,e);break;case"o":k+=i("o",Math.round(((new Date(b.getFullYear(),b.getMonth(),b.getDate())).getTime()-(new Date(b.getFullYear(),0,0)).getTime())/864e5),3);break;case"m":k+=i("m",b.getMonth()+1,2);break;case"M":k+=j("M",b.getMonth(),f,g);break;case"y":k+=h("y")?b.getFullYear():(b.getYear()%100<10?"0":"")+b.getYear()%100;break;case"@":k+=b.getTime();break;case"!":k+=b.getTime()*1e4+this._ticksTo1970;break;case"'":h("'")?k+="'":l=!0;break;default:k+=a.charAt(m)}return k},_possibleChars:function(a){var b="",c=!1,d=function(b){var c=e+1<a.length&&a.charAt(e+1)==b;c&&e++;return c};for(var e=0;e<a.length;e++)if(c)a.charAt(e)=="'"&&!d("'")?c=!1:b+=a.charAt(e);else switch(a.charAt(e)){case"d":case"m":case"y":case"@":b+="0123456789";break;case"D":case"M":return null;case"'":d("'")?b+="'":c=!0;break;default:b+=a.charAt(e)}return b},_get:function(a,b){return a.settings[b]!==undefined?a.settings[b]:this._defaults[b]},_setDateFromField:function(a,b){if(a.input.val()!=a.lastVal){var c=this._get(a,"dateFormat"),d=a.lastVal=a.input?a.input.val():null,e,f;e=f=this._getDefaultDate(a);var g=this._getFormatConfig(a);try{e=this.parseDate(c,d,g)||f}catch(h){this.log(h),d=b?"":d}a.selectedDay=e.getDate(),a.drawMonth=a.selectedMonth=e.getMonth(),a.drawYear=a.selectedYear=e.getFullYear(),a.currentDay=d?e.getDate():0,a.currentMonth=d?e.getMonth():0,a.currentYear=d?e.getFullYear():0,this._adjustInstDate(a)}},_getDefaultDate:function(a){return this._restrictMinMax(a,this._determineDate(a,this._get(a,"defaultDate"),new Date))},_determineDate:function(a,b,c){var d=function(a){var b=new Date;b.setDate(b.getDate()+a);return b},e=function(b){try{return $.datepicker.parseDate($.datepicker._get(a,"dateFormat"),b,$.datepicker._getFormatConfig(a))}catch(c){}var d=(b.toLowerCase().match(/^c/)?$.datepicker._getDate(a):null)||new Date,e=d.getFullYear(),f=d.getMonth(),g=d.getDate(),h=/([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,i=h.exec(b);while(i){switch(i[2]||"d"){case"d":case"D":g+=parseInt(i[1],10);break;case"w":case"W":g+=parseInt(i[1],10)*7;break;case"m":case"M":f+=parseInt(i[1],10),g=Math.min(g,$.datepicker._getDaysInMonth(e,f));break;case"y":case"Y":e+=parseInt(i[1],10),g=Math.min(g,$.datepicker._getDaysInMonth(e,f))}i=h.exec(b)}return new Date(e,f,g)},f=b==null||b===""?c:typeof b=="string"?e(b):typeof b=="number"?isNaN(b)?c:d(b):new Date(b.getTime());f=f&&f.toString()=="Invalid Date"?c:f,f&&(f.setHours(0),f.setMinutes(0),f.setSeconds(0),f.setMilliseconds(0));return this._daylightSavingAdjust(f)},_daylightSavingAdjust:function(a){if(!a)return null;a.setHours(a.getHours()>12?a.getHours()+2:0);return a},_setDate:function(a,b,c){var d=!b,e=a.selectedMonth,f=a.selectedYear,g=this._restrictMinMax(a,this._determineDate(a,b,new Date));a.selectedDay=a.currentDay=g.getDate(),a.drawMonth=a.selectedMonth=a.currentMonth=g.getMonth(),a.drawYear=a.selectedYear=a.currentYear=g.getFullYear(),(e!=a.selectedMonth||f!=a.selectedYear)&&!c&&this._notifyChange(a),this._adjustInstDate(a),a.input&&a.input.val(d?"":this._formatDate(a))},_getDate:function(a){var b=!a.currentYear||a.input&&a.input.val()==""?null:this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return b},_generateHTML:function(a){var b=new Date;b=this._daylightSavingAdjust(new Date(b.getFullYear(),b.getMonth(),b.getDate()));var c=this._get(a,"isRTL"),d=this._get(a,"showButtonPanel"),e=this._get(a,"hideIfNoPrevNext"),f=this._get(a,"navigationAsDateFormat"),g=this._getNumberOfMonths(a),h=this._get(a,"showCurrentAtPos"),i=this._get(a,"stepMonths"),j=g[0]!=1||g[1]!=1,k=this._daylightSavingAdjust(a.currentDay?new Date(a.currentYear,a.currentMonth,a.currentDay):new Date(9999,9,9)),l=this._getMinMaxDate(a,"min"),m=this._getMinMaxDate(a,"max"),n=a.drawMonth-h,o=a.drawYear;n<0&&(n+=12,o--);if(m){var p=this._daylightSavingAdjust(new Date(m.getFullYear(),m.getMonth()-g[0]*g[1]+1,m.getDate()));p=l&&p<l?l:p;while(this._daylightSavingAdjust(new Date(o,n,1))>p)n--,n<0&&(n=11,o--)}a.drawMonth=n,a.drawYear=o;var q=this._get(a,"prevText");q=f?this.formatDate(q,this._daylightSavingAdjust(new Date(o,n-i,1)),this._getFormatConfig(a)):q;var r=this._canAdjustMonth(a,-1,o,n)?'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_'+dpuuid+".datepicker._adjustDate('#"+a.id+"', -"+i+", 'M');\""+' title="'+q+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"e":"w")+'">'+q+"</span></a>":e?"":'<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+q+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"e":"w")+'">'+q+"</span></a>",s=this._get(a,"nextText");s=f?this.formatDate(s,this._daylightSavingAdjust(new Date(o,n+i,1)),this._getFormatConfig(a)):s;var t=this._canAdjustMonth(a,1,o,n)?'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_'+dpuuid+".datepicker._adjustDate('#"+a.id+"', +"+i+", 'M');\""+' title="'+s+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"w":"e")+'">'+s+"</span></a>":e?"":'<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+s+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"w":"e")+'">'+s+"</span></a>",u=this._get(a,"currentText"),v=this._get(a,"gotoCurrent")&&a.currentDay?k:b;u=f?this.formatDate(u,v,this._getFormatConfig(a)):u;var w=a.inline?"":'<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_'+dpuuid+'.datepicker._hideDatepicker();">'+this._get(a,"closeText")+"</button>",x=d?'<div class="ui-datepicker-buttonpane ui-widget-content">'+(c?w:"")+(this._isInRange(a,v)?'<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_'+dpuuid+".datepicker._gotoToday('#"+a.id+"');\""+">"+u+"</button>":"")+(c?"":w)+"</div>":"",y=parseInt(this._get(a,"firstDay"),10);y=isNaN(y)?0:y;var z=this._get(a,"showWeek"),A=this._get(a,"dayNames"),B=this._get(a,"dayNamesShort"),C=this._get(a,"dayNamesMin"),D=this._get(a,"monthNames"),E=this._get(a,"monthNamesShort"),F=this._get(a,"beforeShowDay"),G=this._get(a,"showOtherMonths"),H=this._get(a,"selectOtherMonths"),I=this._get(a,"calculateWeek")||this.iso8601Week,J=this._getDefaultDate(a),K="";for(var L=0;L<g[0];L++){var M="";this.maxRows=4;for(var N=0;N<g[1];N++){var O=this._daylightSavingAdjust(new Date(o,n,a.selectedDay)),P=" ui-corner-all",Q="";if(j){Q+='<div class="ui-datepicker-group';if(g[1]>1)switch(N){case 0:Q+=" ui-datepicker-group-first",P=" ui-corner-"+(c?"right":"left");break;case g[1]-1:Q+=" ui-datepicker-group-last",P=" ui-corner-"+(c?"left":"right");break;default:Q+=" ui-datepicker-group-middle",P=""}Q+='">'}Q+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix'+P+'">'+(/all|left/.test(P)&&L==0?c?t:r:"")+(/all|right/.test(P)&&L==0?c?r:t:"")+this._generateMonthYearHeader(a,n,o,l,m,L>0||N>0,D,E)+'</div><table class="ui-datepicker-calendar"><thead>'+"<tr>";var R=z?'<th class="ui-datepicker-week-col">'+this._get(a,"weekHeader")+"</th>":"";for(var S=0;S<7;S++){var T=(S+y)%7;R+="<th"+((S+y+6)%7>=5?' class="ui-datepicker-week-end"':"")+">"+'<span title="'+A[T]+'">'+C[T]+"</span></th>"}Q+=R+"</tr></thead><tbody>";var U=this._getDaysInMonth(o,n);o==a.selectedYear&&n==a.selectedMonth&&(a.selectedDay=Math.min(a.selectedDay,U));var V=(this._getFirstDayOfMonth(o,n)-y+7)%7,W=Math.ceil((V+U)/7),X=j?this.maxRows>W?this.maxRows:W:W;this.maxRows=X;var Y=this._daylightSavingAdjust(new Date(o,n,1-V));for(var Z=0;Z<X;Z++){Q+="<tr>";var _=z?'<td class="ui-datepicker-week-col">'+this._get(a,"calculateWeek")(Y)+"</td>":"";for(var S=0;S<7;S++){var ba=F?F.apply(a.input?a.input[0]:null,[Y]):[!0,""],bb=Y.getMonth()!=n,bc=bb&&!H||!ba[0]||l&&Y<l||m&&Y>m;_+='<td class="'+((S+y+6)%7>=5?" ui-datepicker-week-end":"")+(bb?" ui-datepicker-other-month":"")+(Y.getTime()==O.getTime()&&n==a.selectedMonth&&a._keyEvent||J.getTime()==Y.getTime()&&J.getTime()==O.getTime()?" "+this._dayOverClass:"")+(bc?" "+this._unselectableClass+" ui-state-disabled":"")+(bb&&!G?"":" "+ba[1]+(Y.getTime()==k.getTime()?" "+this._currentClass:"")+(Y.getTime()==b.getTime()?" ui-datepicker-today":""))+'"'+((!bb||G)&&ba[2]?' title="'+ba[2]+'"':"")+(bc?"":' onclick="DP_jQuery_'+dpuuid+".datepicker._selectDay('#"+a.id+"',"+Y.getMonth()+","+Y.getFullYear()+', this);return false;"')+">"+(bb&&!G?"&#xa0;":bc?'<span class="ui-state-default">'+Y.getDate()+"</span>":'<a class="ui-state-default'+(Y.getTime()==b.getTime()?" ui-state-highlight":"")+(Y.getTime()==k.getTime()?" ui-state-active":"")+(bb?" ui-priority-secondary":"")+'" href="#">'+Y.getDate()+"</a>")+"</td>",Y.setDate(Y.getDate()+1),Y=this._daylightSavingAdjust(Y)}Q+=_+"</tr>"}n++,n>11&&(n=0,o++),Q+="</tbody></table>"+(j?"</div>"+(g[0]>0&&N==g[1]-1?'<div class="ui-datepicker-row-break"></div>':""):""),M+=Q}K+=M}K+=x+($.browser.msie&&parseInt($.browser.version,10)<7&&!a.inline?'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>':""),
+a._keyEvent=!1;return K},_generateMonthYearHeader:function(a,b,c,d,e,f,g,h){var i=this._get(a,"changeMonth"),j=this._get(a,"changeYear"),k=this._get(a,"showMonthAfterYear"),l='<div class="ui-datepicker-title">',m="";if(f||!i)m+='<span class="ui-datepicker-month">'+g[b]+"</span>";else{var n=d&&d.getFullYear()==c,o=e&&e.getFullYear()==c;m+='<select class="ui-datepicker-month" onchange="DP_jQuery_'+dpuuid+".datepicker._selectMonthYear('#"+a.id+"', this, 'M');\" "+">";for(var p=0;p<12;p++)(!n||p>=d.getMonth())&&(!o||p<=e.getMonth())&&(m+='<option value="'+p+'"'+(p==b?' selected="selected"':"")+">"+h[p]+"</option>");m+="</select>"}k||(l+=m+(f||!i||!j?"&#xa0;":""));if(!a.yearshtml){a.yearshtml="";if(f||!j)l+='<span class="ui-datepicker-year">'+c+"</span>";else{var q=this._get(a,"yearRange").split(":"),r=(new Date).getFullYear(),s=function(a){var b=a.match(/c[+-].*/)?c+parseInt(a.substring(1),10):a.match(/[+-].*/)?r+parseInt(a,10):parseInt(a,10);return isNaN(b)?r:b},t=s(q[0]),u=Math.max(t,s(q[1]||""));t=d?Math.max(t,d.getFullYear()):t,u=e?Math.min(u,e.getFullYear()):u,a.yearshtml+='<select class="ui-datepicker-year" onchange="DP_jQuery_'+dpuuid+".datepicker._selectMonthYear('#"+a.id+"', this, 'Y');\" "+">";for(;t<=u;t++)a.yearshtml+='<option value="'+t+'"'+(t==c?' selected="selected"':"")+">"+t+"</option>";a.yearshtml+="</select>",l+=a.yearshtml,a.yearshtml=null}}l+=this._get(a,"yearSuffix"),k&&(l+=(f||!i||!j?"&#xa0;":"")+m),l+="</div>";return l},_adjustInstDate:function(a,b,c){var d=a.drawYear+(c=="Y"?b:0),e=a.drawMonth+(c=="M"?b:0),f=Math.min(a.selectedDay,this._getDaysInMonth(d,e))+(c=="D"?b:0),g=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(d,e,f)));a.selectedDay=g.getDate(),a.drawMonth=a.selectedMonth=g.getMonth(),a.drawYear=a.selectedYear=g.getFullYear(),(c=="M"||c=="Y")&&this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min"),d=this._getMinMaxDate(a,"max"),e=c&&b<c?c:b;e=d&&e>d?d:e;return e},_notifyChange:function(a){var b=this._get(a,"onChangeMonthYear");b&&b.apply(a.input?a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){var b=this._get(a,"numberOfMonths");return b==null?[1,1]:typeof b=="number"?[1,b]:b},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-this._daylightSavingAdjust(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,d){var e=this._getNumberOfMonths(a),f=this._daylightSavingAdjust(new Date(c,d+(b<0?b:e[0]*e[1]),1));b<0&&f.setDate(this._getDaysInMonth(f.getFullYear(),f.getMonth()));return this._isInRange(a,f)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min"),d=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!d||b.getTime()<=d.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10);return{shortYearCutoff:b,dayNamesShort:this._get(a,"dayNamesShort"),dayNames:this._get(a,"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,d){b||(a.currentDay=a.selectedDay,a.currentMonth=a.selectedMonth,a.currentYear=a.selectedYear);var e=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(d,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),e,this._getFormatConfig(a))}}),$.fn.datepicker=function(a){if(!this.length)return this;$.datepicker.initialized||($(document).mousedown($.datepicker._checkExternalClick).find("body").append($.datepicker.dpDiv),$.datepicker.initialized=!0);var b=Array.prototype.slice.call(arguments,1);if(typeof a=="string"&&(a=="isDisabled"||a=="getDate"||a=="widget"))return $.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this[0]].concat(b));if(a=="option"&&arguments.length==2&&typeof arguments[1]=="string")return $.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this[0]].concat(b));return this.each(function(){typeof a=="string"?$.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this].concat(b)):$.datepicker._attachDatepicker(this,a)})},$.datepicker=new Datepicker,$.datepicker.initialized=!1,$.datepicker.uuid=(new Date).getTime(),$.datepicker.version="1.8.18",window["DP_jQuery_"+dpuuid]=$})(jQuery);/*
+ * jQuery UI Progressbar 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Progressbar
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ */(function(a,b){a.widget("ui.progressbar",{options:{value:0,max:100},min:0,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.options.max,"aria-valuenow":this._value()}),this.valueDiv=a("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element),this.oldValue=this._value(),this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove(),a.Widget.prototype.destroy.apply(this,arguments)},value:function(a){if(a===b)return this._value();this._setOption("value",a);return this},_setOption:function(b,c){b==="value"&&(this.options.value=c,this._refreshValue(),this._value()===this.options.max&&this._trigger("complete")),a.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;typeof a!="number"&&(a=0);return Math.min(this.options.max,Math.max(this.min,a))},_percentage:function(){return 100*this._value()/this.options.max},_refreshValue:function(){var a=this.value(),b=this._percentage();this.oldValue!==a&&(this.oldValue=a,this._trigger("change")),this.valueDiv.toggle(a>this.min).toggleClass("ui-corner-right",a===this.options.max).width(b.toFixed(0)+"%"),this.element.attr("aria-valuenow",a)}}),a.extend(a.ui.progressbar,{version:"1.8.18"})})(jQuery);/*
+ * jQuery UI Effects 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/
+ */jQuery.effects||function(a,b){function l(b){if(!b||typeof b=="number"||a.fx.speeds[b])return!0;if(typeof b=="string"&&!a.effects[b])return!0;return!1}function k(b,c,d,e){typeof b=="object"&&(e=c,d=null,c=b,b=c.effect),a.isFunction(c)&&(e=c,d=null,c={});if(typeof c=="number"||a.fx.speeds[c])e=d,d=c,c={};a.isFunction(d)&&(e=d,d=null),c=c||{},d=d||c.duration,d=a.fx.off?0:typeof d=="number"?d:d in a.fx.speeds?a.fx.speeds[d]:a.fx.speeds._default,e=e||c.complete;return[b,c,d,e]}function j(a,b){var c={_:0},d;for(d in b)a[d]!=b[d]&&(c[d]=b[d]);return c}function i(b){var c,d;for(c in b)d=b[c],(d==null||a.isFunction(d)||c in g||/scrollbar/.test(c)||!/color/i.test(c)&&isNaN(parseFloat(d)))&&delete b[c];return b}function h(){var a=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle,b={},c,d;if(a&&a.length&&a[0]&&a[a[0]]){var e=a.length;while(e--)c=a[e],typeof a[c]=="string"&&(d=c.replace(/\-(\w)/g,function(a,b){return b.toUpperCase()}),b[d]=a[c])}else for(c in a)typeof a[c]=="string"&&(b[c]=a[c]);return b}function d(b,d){var e;do{e=a.curCSS(b,d);if(e!=""&&e!="transparent"||a.nodeName(b,"body"))break;d="backgroundColor"}while(b=b.parentNode);return c(e)}function c(b){var c;if(b&&b.constructor==Array&&b.length==3)return b;if(c=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(b))return[parseInt(c[1],10),parseInt(c[2],10),parseInt(c[3],10)];if(c=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(b))return[parseFloat(c[1])*2.55,parseFloat(c[2])*2.55,parseFloat(c[3])*2.55];if(c=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(b))return[parseInt(c[1],16),parseInt(c[2],16),parseInt(c[3],16)];if(c=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(b))return[parseInt(c[1]+c[1],16),parseInt(c[2]+c[2],16),parseInt(c[3]+c[3],16)];if(c=/rgba\(0, 0, 0, 0\)/.exec(b))return e.transparent;return e[a.trim(b).toLowerCase()]}a.effects={},a.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","borderColor","color","outlineColor"],function(b,e){a.fx.step[e]=function(a){a.colorInit||(a.start=d(a.elem,e),a.end=c(a.end),a.colorInit=!0),a.elem.style[e]="rgb("+Math.max(Math.min(parseInt(a.pos*(a.end[0]-a.start[0])+a.start[0],10),255),0)+","+Math.max(Math.min(parseInt(a.pos*(a.end[1]-a.start[1])+a.start[1],10),255),0)+","+Math.max(Math.min(parseInt(a.pos*(a.end[2]-a.start[2])+a.start[2],10),255),0)+")"}});var e={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},f=["add","remove","toggle"],g={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};a.effects.animateClass=function(b,c,d,e){a.isFunction(d)&&(e=d,d=null);return this.queue(function(){var g=a(this),k=g.attr("style")||" ",l=i(h.call(this)),m,n=g.attr("class");a.each(f,function(a,c){b[c]&&g[c+"Class"](b[c])}),m=i(h.call(this)),g.attr("class",n),g.animate(j(l,m),{queue:!1,duration:c,easing:d,complete:function(){a.each(f,function(a,c){b[c]&&g[c+"Class"](b[c])}),typeof g.attr("style")=="object"?(g.attr("style").cssText="",g.attr("style").cssText=k):g.attr("style",k),e&&e.apply(this,arguments),a.dequeue(this)}})})},a.fn.extend({_addClass:a.fn.addClass,addClass:function(b,c,d,e){return c?a.effects.animateClass.apply(this,[{add:b},c,d,e]):this._addClass(b)},_removeClass:a.fn.removeClass,removeClass:function(b,c,d,e){return c?a.effects.animateClass.apply(this,[{remove:b},c,d,e]):this._removeClass(b)},_toggleClass:a.fn.toggleClass,toggleClass:function(c,d,e,f,g){return typeof d=="boolean"||d===b?e?a.effects.animateClass.apply(this,[d?{add:c}:{remove:c},e,f,g]):this._toggleClass(c,d):a.effects.animateClass.apply(this,[{toggle:c},d,e,f])},switchClass:function(b,c,d,e,f){return a.effects.animateClass.apply(this,[{add:c,remove:b},d,e,f])}}),a.extend(a.effects,{version:"1.8.18",save:function(a,b){for(var c=0;c<b.length;c++)b[c]!==null&&a.data("ec.storage."+b[c],a[0].style[b[c]])},restore:function(a,b){for(var c=0;c<b.length;c++)b[c]!==null&&a.css(b[c],a.data("ec.storage."+b[c]))},setMode:function(a,b){b=="toggle"&&(b=a.is(":hidden")?"show":"hide");return b},getBaseline:function(a,b){var c,d;switch(a[0]){case"top":c=0;break;case"middle":c=.5;break;case"bottom":c=1;break;default:c=a[0]/b.height}switch(a[1]){case"left":d=0;break;case"center":d=.5;break;case"right":d=1;break;default:d=a[1]/b.width}return{x:d,y:c}},createWrapper:function(b){if(b.parent().is(".ui-effects-wrapper"))return b.parent();var c={width:b.outerWidth(!0),height:b.outerHeight(!0),"float":b.css("float")},d=a("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),e=document.activeElement;b.wrap(d),(b[0]===e||a.contains(b[0],e))&&a(e).focus(),d=b.parent(),b.css("position")=="static"?(d.css({position:"relative"}),b.css({position:"relative"})):(a.extend(c,{position:b.css("position"),zIndex:b.css("z-index")}),a.each(["top","left","bottom","right"],function(a,d){c[d]=b.css(d),isNaN(parseInt(c[d],10))&&(c[d]="auto")}),b.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"}));return d.css(c).show()},removeWrapper:function(b){var c,d=document.activeElement;if(b.parent().is(".ui-effects-wrapper")){c=b.parent().replaceWith(b),(b[0]===d||a.contains(b[0],d))&&a(d).focus();return c}return b},setTransition:function(b,c,d,e){e=e||{},a.each(c,function(a,c){unit=b.cssUnit(c),unit[0]>0&&(e[c]=unit[0]*d+unit[1])});return e}}),a.fn.extend({effect:function(b,c,d,e){var f=k.apply(this,arguments),g={options:f[1],duration:f[2],callback:f[3]},h=g.options.mode,i=a.effects[b];if(a.fx.off||!i)return h?this[h](g.duration,g.callback):this.each(function(){g.callback&&g.callback.call(this)});return i.call(this,g)},_show:a.fn.show,show:function(a){if(l(a))return this._show.apply(this,arguments);var b=k.apply(this,arguments);b[1].mode="show";return this.effect.apply(this,b)},_hide:a.fn.hide,hide:function(a){if(l(a))return this._hide.apply(this,arguments);var b=k.apply(this,arguments);b[1].mode="hide";return this.effect.apply(this,b)},__toggle:a.fn.toggle,toggle:function(b){if(l(b)||typeof b=="boolean"||a.isFunction(b))return this.__toggle.apply(this,arguments);var c=k.apply(this,arguments);c[1].mode="toggle";return this.effect.apply(this,c)},cssUnit:function(b){var c=this.css(b),d=[];a.each(["em","px","%","pt"],function(a,b){c.indexOf(b)>0&&(d=[parseFloat(c),b])});return d}}),a.easing.jswing=a.easing.swing,a.extend(a.easing,{def:"easeOutQuad",swing:function(b,c,d,e,f){return a.easing[a.easing.def](b,c,d,e,f)},easeInQuad:function(a,b,c,d,e){return d*(b/=e)*b+c},easeOutQuad:function(a,b,c,d,e){return-d*(b/=e)*(b-2)+c},easeInOutQuad:function(a,b,c,d,e){if((b/=e/2)<1)return d/2*b*b+c;return-d/2*(--b*(b-2)-1)+c},easeInCubic:function(a,b,c,d,e){return d*(b/=e)*b*b+c},easeOutCubic:function(a,b,c,d,e){return d*((b=b/e-1)*b*b+1)+c},easeInOutCubic:function(a,b,c,d,e){if((b/=e/2)<1)return d/2*b*b*b+c;return d/2*((b-=2)*b*b+2)+c},easeInQuart:function(a,b,c,d,e){return d*(b/=e)*b*b*b+c},easeOutQuart:function(a,b,c,d,e){return-d*((b=b/e-1)*b*b*b-1)+c},easeInOutQuart:function(a,b,c,d,e){if((b/=e/2)<1)return d/2*b*b*b*b+c;return-d/2*((b-=2)*b*b*b-2)+c},easeInQuint:function(a,b,c,d,e){return d*(b/=e)*b*b*b*b+c},easeOutQuint:function(a,b,c,d,e){return d*((b=b/e-1)*b*b*b*b+1)+c},easeInOutQuint:function(a,b,c,d,e){if((b/=e/2)<1)return d/2*b*b*b*b*b+c;return d/2*((b-=2)*b*b*b*b+2)+c},easeInSine:function(a,b,c,d,e){return-d*Math.cos(b/e*(Math.PI/2))+d+c},easeOutSine:function(a,b,c,d,e){return d*Math.sin(b/e*(Math.PI/2))+c},easeInOutSine:function(a,b,c,d,e){return-d/2*(Math.cos(Math.PI*b/e)-1)+c},easeInExpo:function(a,b,c,d,e){return b==0?c:d*Math.pow(2,10*(b/e-1))+c},easeOutExpo:function(a,b,c,d,e){return b==e?c+d:d*(-Math.pow(2,-10*b/e)+1)+c},easeInOutExpo:function(a,b,c,d,e){if(b==0)return c;if(b==e)return c+d;if((b/=e/2)<1)return d/2*Math.pow(2,10*(b-1))+c;return d/2*(-Math.pow(2,-10*--b)+2)+c},easeInCirc:function(a,b,c,d,e){return-d*(Math.sqrt(1-(b/=e)*b)-1)+c},easeOutCirc:function(a,b,c,d,e){return d*Math.sqrt(1-(b=b/e-1)*b)+c},easeInOutCirc:function(a,b,c,d,e){if((b/=e/2)<1)return-d/2*(Math.sqrt(1-b*b)-1)+c;return d/2*(Math.sqrt(1-(b-=2)*b)+1)+c},easeInElastic:function(a,b,c,d,e){var f=1.70158,g=0,h=d;if(b==0)return c;if((b/=e)==1)return c+d;g||(g=e*.3);if(h<Math.abs(d)){h=d;var f=g/4}else var f=g/(2*Math.PI)*Math.asin(d/h);return-(h*Math.pow(2,10*(b-=1))*Math.sin((b*e-f)*2*Math.PI/g))+c},easeOutElastic:function(a,b,c,d,e){var f=1.70158,g=0,h=d;if(b==0)return c;if((b/=e)==1)return c+d;g||(g=e*.3);if(h<Math.abs(d)){h=d;var f=g/4}else var f=g/(2*Math.PI)*Math.asin(d/h);return h*Math.pow(2,-10*b)*Math.sin((b*e-f)*2*Math.PI/g)+d+c},easeInOutElastic:function(a,b,c,d,e){var f=1.70158,g=0,h=d;if(b==0)return c;if((b/=e/2)==2)return c+d;g||(g=e*.3*1.5);if(h<Math.abs(d)){h=d;var f=g/4}else var f=g/(2*Math.PI)*Math.asin(d/h);if(b<1)return-0.5*h*Math.pow(2,10*(b-=1))*Math.sin((b*e-f)*2*Math.PI/g)+c;return h*Math.pow(2,-10*(b-=1))*Math.sin((b*e-f)*2*Math.PI/g)*.5+d+c},easeInBack:function(a,c,d,e,f,g){g==b&&(g=1.70158);return e*(c/=f)*c*((g+1)*c-g)+d},easeOutBack:function(a,c,d,e,f,g){g==b&&(g=1.70158);return e*((c=c/f-1)*c*((g+1)*c+g)+1)+d},easeInOutBack:function(a,c,d,e,f,g){g==b&&(g=1.70158);if((c/=f/2)<1)return e/2*c*c*(((g*=1.525)+1)*c-g)+d;return e/2*((c-=2)*c*(((g*=1.525)+1)*c+g)+2)+d},easeInBounce:function(b,c,d,e,f){return e-a.easing.easeOutBounce(b,f-c,0,e,f)+d},easeOutBounce:function(a,b,c,d,e){return(b/=e)<1/2.75?d*7.5625*b*b+c:b<2/2.75?d*(7.5625*(b-=1.5/2.75)*b+.75)+c:b<2.5/2.75?d*(7.5625*(b-=2.25/2.75)*b+.9375)+c:d*(7.5625*(b-=2.625/2.75)*b+.984375)+c},easeInOutBounce:function(b,c,d,e,f){if(c<f/2)return a.easing.easeInBounce(b,c*2,0,e,f)*.5+d;return a.easing.easeOutBounce(b,c*2-f,0,e,f)*.5+e*.5+d}})}(jQuery);/*
+ * jQuery UI Effects Blind 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Blind
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */(function(a,b){a.effects.blind=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"hide"),f=b.options.direction||"vertical";a.effects.save(c,d),c.show();var g=a.effects.createWrapper(c).css({overflow:"hidden"}),h=f=="vertical"?"height":"width",i=f=="vertical"?g.height():g.width();e=="show"&&g.css(h,0);var j={};j[h]=e=="show"?i:0,g.animate(j,b.duration,b.options.easing,function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()})})}})(jQuery);/*
+ * jQuery UI Effects Bounce 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Bounce
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */(function(a,b){a.effects.bounce=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"effect"),f=b.options.direction||"up",g=b.options.distance||20,h=b.options.times||5,i=b.duration||250;/show|hide/.test(e)&&d.push("opacity"),a.effects.save(c,d),c.show(),a.effects.createWrapper(c);var j=f=="up"||f=="down"?"top":"left",k=f=="up"||f=="left"?"pos":"neg",g=b.options.distance||(j=="top"?c.outerHeight({margin:!0})/3:c.outerWidth({margin:!0})/3);e=="show"&&c.css("opacity",0).css(j,k=="pos"?-g:g),e=="hide"&&(g=g/(h*2)),e!="hide"&&h--;if(e=="show"){var l={opacity:1};l[j]=(k=="pos"?"+=":"-=")+g,c.animate(l,i/2,b.options.easing),g=g/2,h--}for(var m=0;m<h;m++){var n={},p={};n[j]=(k=="pos"?"-=":"+=")+g,p[j]=(k=="pos"?"+=":"-=")+g,c.animate(n,i/2,b.options.easing).animate(p,i/2,b.options.easing),g=e=="hide"?g*2:g/2}if(e=="hide"){var l={opacity:0};l[j]=(k=="pos"?"-=":"+=")+g,c.animate(l,i/2,b.options.easing,function(){c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(this,arguments)})}else{var n={},p={};n[j]=(k=="pos"?"-=":"+=")+g,p[j]=(k=="pos"?"+=":"-=")+g,c.animate(n,i/2,b.options.easing).animate(p,i/2,b.options.easing,function(){a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(this,arguments)})}c.queue("fx",function(){c.dequeue()}),c.dequeue()})}})(jQuery);/*
+ * jQuery UI Effects Clip 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Clip
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */(function(a,b){a.effects.clip=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right","height","width"],e=a.effects.setMode(c,b.options.mode||"hide"),f=b.options.direction||"vertical";a.effects.save(c,d),c.show();var g=a.effects.createWrapper(c).css({overflow:"hidden"}),h=c[0].tagName=="IMG"?g:c,i={size:f=="vertical"?"height":"width",position:f=="vertical"?"top":"left"},j=f=="vertical"?h.height():h.width();e=="show"&&(h.css(i.size,0),h.css(i.position,j/2));var k={};k[i.size]=e=="show"?j:0,k[i.position]=e=="show"?0:j/2,h.animate(k,{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()}})})}})(jQuery);/*
+ * jQuery UI Effects Drop 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Drop
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */(function(a,b){a.effects.drop=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right","opacity"],e=a.effects.setMode(c,b.options.mode||"hide"),f=b.options.direction||"left";a.effects.save(c,d),c.show(),a.effects.createWrapper(c);var g=f=="up"||f=="down"?"top":"left",h=f=="up"||f=="left"?"pos":"neg",i=b.options.distance||(g=="top"?c.outerHeight({margin:!0})/2:c.outerWidth({margin:!0})/2);e=="show"&&c.css("opacity",0).css(g,h=="pos"?-i:i);var j={opacity:e=="show"?1:0};j[g]=(e=="show"?h=="pos"?"+=":"-=":h=="pos"?"-=":"+=")+i,c.animate(j,{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);/*
+ * jQuery UI Effects Explode 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Explode
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */(function(a,b){a.effects.explode=function(b){return this.queue(function(){var c=b.options.pieces?Math.round(Math.sqrt(b.options.pieces)):3,d=b.options.pieces?Math.round(Math.sqrt(b.options.pieces)):3;b.options.mode=b.options.mode=="toggle"?a(this).is(":visible")?"hide":"show":b.options.mode;var e=a(this).show().css("visibility","hidden"),f=e.offset();f.top-=parseInt(e.css("marginTop"),10)||0,f.left-=parseInt(e.css("marginLeft"),10)||0;var g=e.outerWidth(!0),h=e.outerHeight(!0);for(var i=0;i<c;i++)for(var j=0;j<d;j++)e.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-j*(g/d),top:-i*(h/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:g/d,height:h/c,left:f.left+j*(g/d)+(b.options.mode=="show"?(j-Math.floor(d/2))*(g/d):0),top:f.top+i*(h/c)+(b.options.mode=="show"?(i-Math.floor(c/2))*(h/c):0),opacity:b.options.mode=="show"?0:1}).animate({left:f.left+j*(g/d)+(b.options.mode=="show"?0:(j-Math.floor(d/2))*(g/d)),top:f.top+i*(h/c)+(b.options.mode=="show"?0:(i-Math.floor(c/2))*(h/c)),opacity:b.options.mode=="show"?1:0},b.duration||500);setTimeout(function(){b.options.mode=="show"?e.css({visibility:"visible"}):e.css({visibility:"visible"}).hide(),b.callback&&b.callback.apply(e[0]),e.dequeue(),a("div.ui-effects-explode").remove()},b.duration||500)})}})(jQuery);/*
+ * jQuery UI Effects Fade 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Fade
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */(function(a,b){a.effects.fade=function(b){return this.queue(function(){var c=a(this),d=a.effects.setMode(c,b.options.mode||"hide");c.animate({opacity:d},{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);/*
+ * jQuery UI Effects Fold 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Fold
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */(function(a,b){a.effects.fold=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"hide"),f=b.options.size||15,g=!!b.options.horizFirst,h=b.duration?b.duration/2:a.fx.speeds._default/2;a.effects.save(c,d),c.show();var i=a.effects.createWrapper(c).css({overflow:"hidden"}),j=e=="show"!=g,k=j?["width","height"]:["height","width"],l=j?[i.width(),i.height()]:[i.height(),i.width()],m=/([0-9]+)%/.exec(f);m&&(f=parseInt(m[1],10)/100*l[e=="hide"?0:1]),e=="show"&&i.css(g?{height:0,width:f}:{height:f,width:0});var n={},p={};n[k[0]]=e=="show"?l[0]:f,p[k[1]]=e=="show"?l[1]:0,i.animate(n,h,b.options.easing).animate(p,h,b.options.easing,function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()})})}})(jQuery);/*
+ * jQuery UI Effects Highlight 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Highlight
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */(function(a,b){a.effects.highlight=function(b){return this.queue(function(){var c=a(this),d=["backgroundImage","backgroundColor","opacity"],e=a.effects.setMode(c,b.options.mode||"show"),f={backgroundColor:c.css("backgroundColor")};e=="hide"&&(f.opacity=0),a.effects.save(c,d),c.show().css({backgroundImage:"none",backgroundColor:b.options.color||"#ffff99"}).animate(f,{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){e=="hide"&&c.hide(),a.effects.restore(c,d),e=="show"&&!a.support.opacity&&this.style.removeAttribute("filter"),b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);/*
+ * jQuery UI Effects Pulsate 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Pulsate
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */(function(a,b){a.effects.pulsate=function(b){return this.queue(function(){var c=a(this),d=a.effects.setMode(c,b.options.mode||"show");times=(b.options.times||5)*2-1,duration=b.duration?b.duration/2:a.fx.speeds._default/2,isVisible=c.is(":visible"),animateTo=0,isVisible||(c.css("opacity",0).show(),animateTo=1),(d=="hide"&&isVisible||d=="show"&&!isVisible)&&times--;for(var e=0;e<times;e++)c.animate({opacity:animateTo},duration,b.options.easing),animateTo=(animateTo+1)%2;c.animate({opacity:animateTo},duration,b.options.easing,function(){animateTo==0&&c.hide(),b.callback&&b.callback.apply(this,arguments)}),c.queue("fx",function(){c.dequeue()}).dequeue()})}})(jQuery);/*
+ * jQuery UI Effects Scale 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Scale
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */(function(a,b){a.effects.puff=function(b){return this.queue(function(){var c=a(this),d=a.effects.setMode(c,b.options.mode||"hide"),e=parseInt(b.options.percent,10)||150,f=e/100,g={height:c.height(),width:c.width()};a.extend(b.options,{fade:!0,mode:d,percent:d=="hide"?e:100,from:d=="hide"?g:{height:g.height*f,width:g.width*f}}),c.effect("scale",b.options,b.duration,b.callback),c.dequeue()})},a.effects.scale=function(b){return this.queue(function(){var c=a(this),d=a.extend(!0,{},b.options),e=a.effects.setMode(c,b.options.mode||"effect"),f=parseInt(b.options.percent,10)||(parseInt(b.options.percent,10)==0?0:e=="hide"?0:100),g=b.options.direction||"both",h=b.options.origin;e!="effect"&&(d.origin=h||["middle","center"],d.restore=!0);var i={height:c.height(),width:c.width()};c.from=b.options.from||(e=="show"?{height:0,width:0}:i);var j={y:g!="horizontal"?f/100:1,x:g!="vertical"?f/100:1};c.to={height:i.height*j.y,width:i.width*j.x},b.options.fade&&(e=="show"&&(c.from.opacity=0,c.to.opacity=1),e=="hide"&&(c.from.opacity=1,c.to.opacity=0)),d.from=c.from,d.to=c.to,d.mode=e,c.effect("size",d,b.duration,b.callback),c.dequeue()})},a.effects.size=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right","width","height","overflow","opacity"],e=["position","top","bottom","left","right","overflow","opacity"],f=["width","height","overflow"],g=["fontSize"],h=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],i=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],j=a.effects.setMode(c,b.options.mode||"effect"),k=b.options.restore||!1,l=b.options.scale||"both",m=b.options.origin,n={height:c.height(),width:c.width()};c.from=b.options.from||n,c.to=b.options.to||n;if(m){var p=a.effects.getBaseline(m,n);c.from.top=(n.height-c.from.height)*p.y,c.from.left=(n.width-c.from.width)*p.x,c.to.top=(n.height-c.to.height)*p.y,c.to.left=(n.width-c.to.width)*p.x}var q={from:{y:c.from.height/n.height,x:c.from.width/n.width},to:{y:c.to.height/n.height,x:c.to.width/n.width}};if(l=="box"||l=="both")q.from.y!=q.to.y&&(d=d.concat(h),c.from=a.effects.setTransition(c,h,q.from.y,c.from),c.to=a.effects.setTransition(c,h,q.to.y,c.to)),q.from.x!=q.to.x&&(d=d.concat(i),c.from=a.effects.setTransition(c,i,q.from.x,c.from),c.to=a.effects.setTransition(c,i,q.to.x,c.to));(l=="content"||l=="both")&&q.from.y!=q.to.y&&(d=d.concat(g),c.from=a.effects.setTransition(c,g,q.from.y,c.from),c.to=a.effects.setTransition(c,g,q.to.y,c.to)),a.effects.save(c,k?d:e),c.show(),a.effects.createWrapper(c),c.css("overflow","hidden").css(c.from);if(l=="content"||l=="both")h=h.concat(["marginTop","marginBottom"]).concat(g),i=i.concat(["marginLeft","marginRight"]),f=d.concat(h).concat(i),c.find("*[width]").each(function(){child=a(this),k&&a.effects.save(child,f);var c={height:child.height(),width:child.width()};child.from={height:c.height*q.from.y,width:c.width*q.from.x},child.to={height:c.height*q.to.y,width:c.width*q.to.x},q.from.y!=q.to.y&&(child.from=a.effects.setTransition(child,h,q.from.y,child.from),child.to=a.effects.setTransition(child,h,q.to.y,child.to)),q.from.x!=q.to.x&&(child.from=a.effects.setTransition(child,i,q.from.x,child.from),child.to=a.effects.setTransition(child,i,q.to.x,child.to)),child.css(child.from),child.animate(child.to,b.duration,b.options.easing,function(){k&&a.effects.restore(child,f)})});c.animate(c.to,{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){c.to.opacity===0&&c.css("opacity",c.from.opacity),j=="hide"&&c.hide(),a.effects.restore(c,k?d:e),a.effects.removeWrapper(c),b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);/*
+ * jQuery UI Effects Shake 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Shake
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */(function(a,b){a.effects.shake=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"effect"),f=b.options.direction||"left",g=b.options.distance||20,h=b.options.times||3,i=b.duration||b.options.duration||140;a.effects.save(c,d),c.show(),a.effects.createWrapper(c);var j=f=="up"||f=="down"?"top":"left",k=f=="up"||f=="left"?"pos":"neg",l={},m={},n={};l[j]=(k=="pos"?"-=":"+=")+g,m[j]=(k=="pos"?"+=":"-=")+g*2,n[j]=(k=="pos"?"-=":"+=")+g*2,c.animate(l,i,b.options.easing);for(var p=1;p<h;p++)c.animate(m,i,b.options.easing).animate(n,i,b.options.easing);c.animate(m,i,b.options.easing).animate(l,i/2,b.options.easing,function(){a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(this,arguments)}),c.queue("fx",function(){c.dequeue()}),c.dequeue()})}})(jQuery);/*
+ * jQuery UI Effects Slide 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Slide
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */(function(a,b){a.effects.slide=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"show"),f=b.options.direction||"left";a.effects.save(c,d),c.show(),a.effects.createWrapper(c).css({overflow:"hidden"});var g=f=="up"||f=="down"?"top":"left",h=f=="up"||f=="left"?"pos":"neg",i=b.options.distance||(g=="top"?c.outerHeight({margin:!0}):c.outerWidth({margin:!0}));e=="show"&&c.css(g,h=="pos"?isNaN(i)?"-"+i:-i:i);var j={};j[g]=(e=="show"?h=="pos"?"+=":"-=":h=="pos"?"-=":"+=")+i,c.animate(j,{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);/*
+ * jQuery UI Effects Transfer 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Transfer
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */(function(a,b){a.effects.transfer=function(b){return this.queue(function(){var c=a(this),d=a(b.options.to),e=d.offset(),f={top:e.top,left:e.left,height:d.innerHeight(),width:d.innerWidth()},g=c.offset(),h=a('<div class="ui-effects-transfer"></div>').appendTo(document.body).addClass(b.options.className).css({top:g.top,left:g.left,height:c.innerHeight(),width:c.innerWidth(),position:"absolute"}).animate(f,b.duration,b.options.easing,function(){h.remove(),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()})})}})(jQuery); \ No newline at end of file
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/init-db.sh b/storage/mroonga/vendor/groonga/examples/dictionary/init-db.sh
new file mode 100755
index 00000000000..351d90e7b30
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/init-db.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+if [ 1 != $# ]; then
+ echo "usage: $0 db_path"
+ exit 1
+fi
+
+if groonga-suggest-create-dataset $1 dictionary > /dev/null; then
+ echo "db initialized."
+fi
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/jmdict/Makefile.am b/storage/mroonga/vendor/groonga/examples/dictionary/jmdict/Makefile.am
new file mode 100644
index 00000000000..70b4a5bc010
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/jmdict/Makefile.am
@@ -0,0 +1,3 @@
+jmdictdir = $(examples_dictionarydir)/jmdict
+dist_jmdict_SCRIPTS = \
+ jmdict.rb
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/jmdict/jmdict.rb b/storage/mroonga/vendor/groonga/examples/dictionary/jmdict/jmdict.rb
new file mode 100755
index 00000000000..bf8926783cb
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/jmdict/jmdict.rb
@@ -0,0 +1,42 @@
+#!/usr/bin/env ruby
+# -*- coding: utf-8 -*-
+
+require 'rexml/document'
+require 'rexml/parsers/streamparser'
+require 'rexml/parsers/baseparser'
+require 'rexml/streamlistener'
+
+#REXML::Document.new(STDIN)
+
+class MyListener
+ include REXML::StreamListener
+ def tag_start(name, attrs)
+ # p name, attrs
+ case name
+ when 'entry'
+ @n = 0
+ end
+ end
+ def tag_end name
+ # p "tag_end: #{x}"
+ case name
+ when 'sense'
+ @n += 1
+ when 'entry'
+ @n_ents += 1
+ puts "#{@ent}:#{@n}" if (@n > 8)
+ when 'ent_seq'
+ @ent = @text
+ end
+ end
+
+ def text(text)
+ @text = text
+ end
+
+ def xmldecl(version, encoding, standalone)
+ @n_ents = 0
+ end
+end
+
+REXML::Parsers::StreamParser.new(STDIN, MyListener.new).parse
diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/readme.txt b/storage/mroonga/vendor/groonga/examples/dictionary/readme.txt
new file mode 100644
index 00000000000..555706e0061
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/examples/dictionary/readme.txt
@@ -0,0 +1,71 @@
+.. highlightlang:: none
+
+辞書検索ツール
+==============
+
+åå‰
+----
+
+groonga辞書検索ツール
+
+説明
+----
+
+様々ãªå•†ç”¨ãƒ»éžå•†ç”¨ã®è¾žæ›¸ãƒ•ã‚¡ã‚¤ãƒ«ã‚’インãƒãƒ¼ãƒˆã—ã¦groongaã§æ¤œç´¢ã§ãるよã†ã«ã—ã¾ã™ã€‚
+
+対応ã—ã¦ã„る辞書
+++++++++++++++++
+
+ç¾çŠ¶ã§ã¯ä¸‹è¨˜ã®è¾žæ›¸ã«å¯¾å¿œã—ã¦ã„ã¾ã™ã€‚
+
+* EDICT
+
+EDICTã¯ã€Monash大学Jim Breen教授ãŒæä¾›ã—ã¦ã„る和英辞書ã§ã™ã€‚下記ã‹ã‚‰å…¥æ‰‹ã§ãã¾ã™ã€‚
+
+http://ftp.monash.edu.au/pub/nihongo/edict.gz
+
+* GENE95
+
+GENE95ã¯ã€Kurumiã•ã‚“(NiftyID: GGD00145)ãŒä½œæˆã•ã‚ŒãŸè‹±å’Œè¾žæ›¸ã§ã™ã€‚下記ã‹ã‚‰å…¥æ‰‹ã§ãã¾ã™ã€‚
+
+http://www.namazu.org/~tsuchiya/sdic/data/gene95.tar.gz
+
+* 英辞郎
+
+英辞郎ã¯ã€EDPã¨ã„ã†å›£ä½“ã«ã‚ˆã£ã¦ç·¨çº‚ã•ã‚Œã¦ã„る英和・和英辞書ã§ã™ã€‚
+
+http://www.eijiro.jp/
+
+書店やオンラインショップãªã©ã§è³¼å…¥ã§ãã¾ã™ã€‚
+
+データベースã®åˆæœŸåŒ–
+++++++++++++++++++++
+
+本ディレクトリã§ä¸‹è¨˜ã®ã‚ˆã†ã«å®Ÿè¡Œã—ã€è¾žæ›¸ãƒ‡ãƒ¼ã‚¿ã‚’æ ¼ç´ã™ã‚‹ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«ã‚’下記ã®ã‚ˆã†ã«ã—ã¦åˆæœŸåŒ–ã—ã¾ã™ã€‚
+
+ ./init-db.sh データベースパスå
+
+ã“ã®ã‚ˆã†ã«ã—ã¦ä½œæˆã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ã¤ã„ã¦ã€æ§˜ã€…ãªè¾žæ›¸ã®ãƒ‡ãƒ¼ã‚¿ã‚’インãƒãƒ¼ãƒˆã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+
+インãƒãƒ¼ãƒˆã®æ–¹æ³•
+++++++++++++++++
+
+* EDICT
+
+edictディレクトリé…下ã§ä»¥ä¸‹ã®ã‚ˆã†ã«å®Ÿè¡Œã—ã¾ã™ã€‚ edict.gzã¯è‡ªå‹•ã§ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã—ã¾ã™ã€‚
+
+ ./edict-import.sh データベースパスå
+
+* GENE95
+
+gene95ディレクトリé…下ã§ä¸‹è¨˜ã®ã‚ˆã†ã«å®Ÿè¡Œã—ã¾ã™ã€‚ gene95.tar.gzã¯è‡ªå‹•ã§ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã—ã¾ã™ã€‚
+
+ ./gene-import.sh データベースパスå
+
+* 英辞郎
+
+英辞郎ã«ä»˜å±žã®PDICツールを用ã„ã¦CSVファイル形å¼ã«è¾žæ›¸ã‚’エクスãƒãƒ¼ãƒˆã—ã¾ã™ã€‚(ã“ã®ã¨ã「登録項目ã€ã§ã™ã¹ã¦ã®é …目を出力ã™ã‚‹ã‚ˆã†ã«ã—ã¾ã™) eijiroディレクトリé…下ã§ä¸‹è¨˜ã®ã‚ˆã†ã«å®Ÿè¡Œã—ã¾ã™ã€‚
+
+ ./eijiro-import.sh データベースパスå 出力ã—ãŸCSVファイルã®ãƒ‘スå
+
+(英辞郎第四版ã§å‹•ä½œã‚’確èªã—ã¦ã„ã¾ã™)
diff --git a/storage/mroonga/vendor/groonga/groonga-httpd-conf.sh.in b/storage/mroonga/vendor/groonga/groonga-httpd-conf.sh.in
index 22a90d82430..380495bb391 100644
--- a/storage/mroonga/vendor/groonga/groonga-httpd-conf.sh.in
+++ b/storage/mroonga/vendor/groonga/groonga-httpd-conf.sh.in
@@ -6,13 +6,15 @@ sysconfdir="@sysconfdir@"
pkgsysconfdir="@pkgsysconfdir@"
localstatedir="@localstatedir@"
+EXEEXT="@EXEEXT@"
+
SED="@SED@"
export GROONGA_HTTPD_MODULE_PATH="@abs_top_srcdir@/src/httpd/nginx-module"
export GROONGA_HTTPD_IN_TREE_INCLUDE_PATH="@abs_top_srcdir@/include"
export GROONGA_HTTPD_IN_TREE_LINK_PATH="@abs_top_builddir@/lib/.libs"
export GROONGA_HTTPD_PREFIX="${pkgsysconfdir}/httpd"
-export GROONGA_HTTPD_BIN_PATH="${sbindir}/groonga-httpd"
+export GROONGA_HTTPD_BIN_PATH="${sbindir}/groonga-httpd${EXEEXT}"
export GROONGA_HTTPD_CONF_PATH="${pkgsysconfdir}/httpd/groonga-httpd.conf"
export GROONGA_HTTPD_ERROR_LOG_PATH="${localstatedir}/log/groonga/httpd/error.log"
export GROONGA_HTTPD_HTTP_LOG_PATH="${localstatedir}/log/groonga/httpd/access.log"
diff --git a/storage/mroonga/vendor/groonga/include/CMakeLists.txt b/storage/mroonga/vendor/groonga/include/CMakeLists.txt
index 96e22474cbf..7594c6e6c66 100644
--- a/storage/mroonga/vendor/groonga/include/CMakeLists.txt
+++ b/storage/mroonga/vendor/groonga/include/CMakeLists.txt
@@ -13,8 +13,6 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-if(NOT MRN_GROONGA_BUNDLED)
- install(FILES groonga.h DESTINATION "${GRN_INCLUDE_DIR}")
- install(DIRECTORY groonga DESTINATION "${GRN_INCLUDE_DIR}"
- FILES_MATCHING PATTERN "*.h")
-endif()
+install(FILES groonga.h DESTINATION "${GRN_INCLUDE_DIR}")
+install(DIRECTORY groonga DESTINATION "${GRN_INCLUDE_DIR}"
+ FILES_MATCHING PATTERN "*.h")
diff --git a/storage/mroonga/vendor/groonga/include/groonga.h b/storage/mroonga/vendor/groonga/include/groonga.h
index d1cf1e24a56..96384287270 100644
--- a/storage/mroonga/vendor/groonga/include/groonga.h
+++ b/storage/mroonga/vendor/groonga/include/groonga.h
@@ -1,5 +1,5 @@
/*
- Copyright(C) 2009-2014 Brazil
+ Copyright(C) 2014-2015 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -18,2089 +18,12 @@
#ifndef GROONGA_H
#define GROONGA_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdarg.h>
-
-#ifndef GRN_API
-#if defined(_WIN32) || defined(_WIN64)
-#define GRN_API __declspec(dllimport)
-#else
-#define GRN_API
-#endif /* defined(_WIN32) || defined(_WIN64) */
-#endif /* GRN_API */
-
-typedef unsigned int grn_id;
-typedef unsigned char grn_bool;
-
-#define GRN_ID_NIL (0x00)
-#define GRN_ID_MAX (0x3fffffff)
-
-#define GRN_TRUE (1)
-#define GRN_FALSE (0)
-
-typedef enum {
- GRN_SUCCESS = 0,
- GRN_END_OF_DATA = 1,
- GRN_UNKNOWN_ERROR = -1,
- GRN_OPERATION_NOT_PERMITTED = -2,
- GRN_NO_SUCH_FILE_OR_DIRECTORY = -3,
- GRN_NO_SUCH_PROCESS = -4,
- GRN_INTERRUPTED_FUNCTION_CALL = -5,
- GRN_INPUT_OUTPUT_ERROR = -6,
- GRN_NO_SUCH_DEVICE_OR_ADDRESS = -7,
- GRN_ARG_LIST_TOO_LONG = -8,
- GRN_EXEC_FORMAT_ERROR = -9,
- GRN_BAD_FILE_DESCRIPTOR = -10,
- GRN_NO_CHILD_PROCESSES = -11,
- GRN_RESOURCE_TEMPORARILY_UNAVAILABLE = -12,
- GRN_NOT_ENOUGH_SPACE = -13,
- GRN_PERMISSION_DENIED = -14,
- GRN_BAD_ADDRESS = -15,
- GRN_RESOURCE_BUSY = -16,
- GRN_FILE_EXISTS = -17,
- GRN_IMPROPER_LINK = -18,
- GRN_NO_SUCH_DEVICE = -19,
- GRN_NOT_A_DIRECTORY = -20,
- GRN_IS_A_DIRECTORY = -21,
- GRN_INVALID_ARGUMENT = -22,
- GRN_TOO_MANY_OPEN_FILES_IN_SYSTEM = -23,
- GRN_TOO_MANY_OPEN_FILES = -24,
- GRN_INAPPROPRIATE_I_O_CONTROL_OPERATION = -25,
- GRN_FILE_TOO_LARGE = -26,
- GRN_NO_SPACE_LEFT_ON_DEVICE = -27,
- GRN_INVALID_SEEK = -28,
- GRN_READ_ONLY_FILE_SYSTEM = -29,
- GRN_TOO_MANY_LINKS = -30,
- GRN_BROKEN_PIPE = -31,
- GRN_DOMAIN_ERROR = -32,
- GRN_RESULT_TOO_LARGE = -33,
- GRN_RESOURCE_DEADLOCK_AVOIDED = -34,
- GRN_NO_MEMORY_AVAILABLE = -35,
- GRN_FILENAME_TOO_LONG = -36,
- GRN_NO_LOCKS_AVAILABLE = -37,
- GRN_FUNCTION_NOT_IMPLEMENTED = -38,
- GRN_DIRECTORY_NOT_EMPTY = -39,
- GRN_ILLEGAL_BYTE_SEQUENCE = -40,
- GRN_SOCKET_NOT_INITIALIZED = -41,
- GRN_OPERATION_WOULD_BLOCK = -42,
- GRN_ADDRESS_IS_NOT_AVAILABLE = -43,
- GRN_NETWORK_IS_DOWN = -44,
- GRN_NO_BUFFER = -45,
- GRN_SOCKET_IS_ALREADY_CONNECTED = -46,
- GRN_SOCKET_IS_NOT_CONNECTED = -47,
- GRN_SOCKET_IS_ALREADY_SHUTDOWNED = -48,
- GRN_OPERATION_TIMEOUT = -49,
- GRN_CONNECTION_REFUSED = -50,
- GRN_RANGE_ERROR = -51,
- GRN_TOKENIZER_ERROR = -52,
- GRN_FILE_CORRUPT = -53,
- GRN_INVALID_FORMAT = -54,
- GRN_OBJECT_CORRUPT = -55,
- GRN_TOO_MANY_SYMBOLIC_LINKS = -56,
- GRN_NOT_SOCKET = -57,
- GRN_OPERATION_NOT_SUPPORTED = -58,
- GRN_ADDRESS_IS_IN_USE = -59,
- GRN_ZLIB_ERROR = -60,
- GRN_LZO_ERROR = -61,
- GRN_STACK_OVER_FLOW = -62,
- GRN_SYNTAX_ERROR = -63,
- GRN_RETRY_MAX = -64,
- GRN_INCOMPATIBLE_FILE_FORMAT = -65,
- GRN_UPDATE_NOT_ALLOWED = -66,
- GRN_TOO_SMALL_OFFSET = -67,
- GRN_TOO_LARGE_OFFSET = -68,
- GRN_TOO_SMALL_LIMIT = -69,
- GRN_CAS_ERROR = -70,
- GRN_UNSUPPORTED_COMMAND_VERSION = -71,
- GRN_NORMALIZER_ERROR = -72,
- GRN_TOKEN_FILTER_ERROR = -73,
-} grn_rc;
-
-GRN_API grn_rc grn_init(void);
-GRN_API grn_rc grn_fin(void);
-
-typedef enum {
- GRN_ENC_DEFAULT = 0,
- GRN_ENC_NONE,
- GRN_ENC_EUC_JP,
- GRN_ENC_UTF8,
- GRN_ENC_SJIS,
- GRN_ENC_LATIN1,
- GRN_ENC_KOI8R
-} grn_encoding;
-
-typedef enum {
- GRN_COMMAND_VERSION_DEFAULT = 0,
- GRN_COMMAND_VERSION_1,
- GRN_COMMAND_VERSION_2
-} grn_command_version;
-
-#define GRN_COMMAND_VERSION_MIN GRN_COMMAND_VERSION_1
-#define GRN_COMMAND_VERSION_STABLE GRN_COMMAND_VERSION_1
-#define GRN_COMMAND_VERSION_MAX GRN_COMMAND_VERSION_2
-
-typedef enum {
- GRN_LOG_NONE = 0,
- GRN_LOG_EMERG,
- GRN_LOG_ALERT,
- GRN_LOG_CRIT,
- GRN_LOG_ERROR,
- GRN_LOG_WARNING,
- GRN_LOG_NOTICE,
- GRN_LOG_INFO,
- GRN_LOG_DEBUG,
- GRN_LOG_DUMP
-} grn_log_level;
-
-/* query log flags */
-#define GRN_QUERY_LOG_NONE (0x00)
-#define GRN_QUERY_LOG_COMMAND (0x01<<0)
-#define GRN_QUERY_LOG_RESULT_CODE (0x01<<1)
-#define GRN_QUERY_LOG_DESTINATION (0x01<<2)
-#define GRN_QUERY_LOG_CACHE (0x01<<3)
-#define GRN_QUERY_LOG_SIZE (0x01<<4)
-#define GRN_QUERY_LOG_SCORE (0x01<<5)
-#define GRN_QUERY_LOG_ALL\
- (GRN_QUERY_LOG_COMMAND |\
- GRN_QUERY_LOG_RESULT_CODE |\
- GRN_QUERY_LOG_DESTINATION |\
- GRN_QUERY_LOG_CACHE |\
- GRN_QUERY_LOG_SIZE |\
- GRN_QUERY_LOG_SCORE)
-#define GRN_QUERY_LOG_DEFAULT GRN_QUERY_LOG_ALL
-
-typedef enum {
- GRN_CONTENT_NONE = 0,
- GRN_CONTENT_TSV,
- GRN_CONTENT_JSON,
- GRN_CONTENT_XML,
- GRN_CONTENT_MSGPACK
-} grn_content_type;
-
-typedef struct _grn_obj grn_obj;
-typedef struct _grn_ctx grn_ctx;
-
-#define GRN_CTX_MSGSIZE (0x80)
-#define GRN_CTX_FIN (0xff)
-
-typedef union {
- int int_value;
- grn_id id;
- void *ptr;
-} grn_user_data;
-
-typedef grn_obj *grn_proc_func(grn_ctx *ctx, int nargs, grn_obj **args,
- grn_user_data *user_data);
-
-struct _grn_ctx {
- grn_rc rc;
- int flags;
- grn_encoding encoding;
- unsigned char ntrace;
- unsigned char errlvl;
- unsigned char stat;
- unsigned int seqno;
- unsigned int subno;
- unsigned int seqno2;
- unsigned int errline;
- grn_user_data user_data;
- grn_ctx *prev;
- grn_ctx *next;
- const char *errfile;
- const char *errfunc;
- struct _grn_ctx_impl *impl;
- void *trace[16];
- char errbuf[GRN_CTX_MSGSIZE];
-};
-
-#define GRN_CTX_USER_DATA(ctx) (&((ctx)->user_data))
-
-/* Deprecated since 4.0.3. Don't use it. */
-#define GRN_CTX_USE_QL (0x03)
-/* Deprecated since 4.0.3. Don't use it. */
-#define GRN_CTX_BATCH_MODE (0x04)
-#define GRN_CTX_PER_DB (0x08)
-
-GRN_API grn_rc grn_ctx_init(grn_ctx *ctx, int flags);
-GRN_API grn_rc grn_ctx_fin(grn_ctx *ctx);
-GRN_API grn_ctx *grn_ctx_open(int flags);
-GRN_API grn_rc grn_ctx_close(grn_ctx *ctx);
-GRN_API grn_rc grn_ctx_set_finalizer(grn_ctx *ctx, grn_proc_func *func);
-
-GRN_API grn_encoding grn_get_default_encoding(void);
-GRN_API grn_rc grn_set_default_encoding(grn_encoding encoding);
-
-#define GRN_CTX_GET_ENCODING(ctx) ((ctx)->encoding)
-#define GRN_CTX_SET_ENCODING(ctx,enc) \
- ((ctx)->encoding = (enc == GRN_ENC_DEFAULT) ? grn_get_default_encoding() : enc)
-
-GRN_API const char *grn_get_version(void);
-GRN_API const char *grn_get_package(void);
-
-GRN_API grn_command_version grn_get_default_command_version(void);
-GRN_API grn_rc grn_set_default_command_version(grn_command_version version);
-GRN_API grn_command_version grn_ctx_get_command_version(grn_ctx *ctx);
-GRN_API grn_rc grn_ctx_set_command_version(grn_ctx *ctx, grn_command_version version);
-GRN_API long long int grn_ctx_get_match_escalation_threshold(grn_ctx *ctx);
-GRN_API grn_rc grn_ctx_set_match_escalation_threshold(grn_ctx *ctx, long long int threshold);
-GRN_API long long int grn_get_default_match_escalation_threshold(void);
-GRN_API grn_rc grn_set_default_match_escalation_threshold(long long int threshold);
-
-GRN_API int grn_get_lock_timeout(void);
-GRN_API grn_rc grn_set_lock_timeout(int timeout);
-
-/* cache */
-#define GRN_CACHE_DEFAULT_MAX_N_ENTRIES 100
-typedef struct _grn_cache grn_cache;
-
-GRN_API grn_cache *grn_cache_open(grn_ctx *ctx);
-GRN_API grn_rc grn_cache_close(grn_ctx *ctx, grn_cache *cache);
-
-GRN_API grn_rc grn_cache_current_set(grn_ctx *ctx, grn_cache *cache);
-GRN_API grn_cache *grn_cache_current_get(grn_ctx *ctx);
-
-GRN_API grn_rc grn_cache_set_max_n_entries(grn_ctx *ctx,
- grn_cache *cache,
- unsigned int n);
-GRN_API unsigned int grn_cache_get_max_n_entries(grn_ctx *ctx,
- grn_cache *cache);
-
-/* grn_encoding */
-
-GRN_API const char *grn_encoding_to_string(grn_encoding encoding);
-GRN_API grn_encoding grn_encoding_parse(const char *name);
-
-/* obj */
-
-typedef unsigned short int grn_obj_flags;
-
-#define GRN_OBJ_TABLE_TYPE_MASK (0x07)
-#define GRN_OBJ_TABLE_HASH_KEY (0x00)
-#define GRN_OBJ_TABLE_PAT_KEY (0x01)
-#define GRN_OBJ_TABLE_DAT_KEY (0x02)
-#define GRN_OBJ_TABLE_NO_KEY (0x03)
-
-#define GRN_OBJ_KEY_MASK (0x07<<3)
-#define GRN_OBJ_KEY_UINT (0x00<<3)
-#define GRN_OBJ_KEY_INT (0x01<<3)
-#define GRN_OBJ_KEY_FLOAT (0x02<<3)
-#define GRN_OBJ_KEY_GEO_POINT (0x03<<3)
-
-#define GRN_OBJ_KEY_WITH_SIS (0x01<<6)
-#define GRN_OBJ_KEY_NORMALIZE (0x01<<7)
-
-#define GRN_OBJ_COLUMN_TYPE_MASK (0x07)
-#define GRN_OBJ_COLUMN_SCALAR (0x00)
-#define GRN_OBJ_COLUMN_VECTOR (0x01)
-#define GRN_OBJ_COLUMN_INDEX (0x02)
-
-#define GRN_OBJ_COMPRESS_MASK (0x07<<4)
-#define GRN_OBJ_COMPRESS_NONE (0x00<<4)
-#define GRN_OBJ_COMPRESS_ZLIB (0x01<<4)
-#define GRN_OBJ_COMPRESS_LZO (0x02<<4)
-
-#define GRN_OBJ_WITH_SECTION (0x01<<7)
-#define GRN_OBJ_WITH_WEIGHT (0x01<<8)
-#define GRN_OBJ_WITH_POSITION (0x01<<9)
-#define GRN_OBJ_RING_BUFFER (0x01<<10)
-
-#define GRN_OBJ_UNIT_MASK (0x0f<<8)
-#define GRN_OBJ_UNIT_DOCUMENT_NONE (0x00<<8)
-#define GRN_OBJ_UNIT_DOCUMENT_SECTION (0x01<<8)
-#define GRN_OBJ_UNIT_DOCUMENT_POSITION (0x02<<8)
-#define GRN_OBJ_UNIT_SECTION_NONE (0x03<<8)
-#define GRN_OBJ_UNIT_SECTION_POSITION (0x04<<8)
-#define GRN_OBJ_UNIT_POSITION_NONE (0x05<<8)
-#define GRN_OBJ_UNIT_USERDEF_DOCUMENT (0x06<<8)
-#define GRN_OBJ_UNIT_USERDEF_SECTION (0x07<<8)
-#define GRN_OBJ_UNIT_USERDEF_POSITION (0x08<<8)
-
-#define GRN_OBJ_NO_SUBREC (0x00<<13)
-#define GRN_OBJ_WITH_SUBREC (0x01<<13)
-
-#define GRN_OBJ_KEY_VAR_SIZE (0x01<<14)
-
-#define GRN_OBJ_TEMPORARY (0x00<<15)
-#define GRN_OBJ_PERSISTENT (0x01<<15)
-
-/* obj types */
-
-#define GRN_VOID (0x00)
-#define GRN_BULK (0x02)
-#define GRN_PTR (0x03)
-#define GRN_UVECTOR (0x04) /* vector of grn_id */
-#define GRN_PVECTOR (0x05) /* vector of grn_obj* */
-#define GRN_VECTOR (0x06) /* vector of arbitrary data */
-#define GRN_MSG (0x07)
-#define GRN_QUERY (0x08)
-#define GRN_ACCESSOR (0x09)
-#define GRN_SNIP (0x0b)
-#define GRN_PATSNIP (0x0c)
-#define GRN_STRING (0x0d)
-#define GRN_CURSOR_TABLE_HASH_KEY (0x10)
-#define GRN_CURSOR_TABLE_PAT_KEY (0x11)
-#define GRN_CURSOR_TABLE_DAT_KEY (0x12)
-#define GRN_CURSOR_TABLE_NO_KEY (0x13)
-#define GRN_CURSOR_COLUMN_INDEX (0x18)
-#define GRN_CURSOR_COLUMN_GEO_INDEX (0x1a)
-#define GRN_TYPE (0x20)
-#define GRN_PROC (0x21)
-#define GRN_EXPR (0x22)
-#define GRN_TABLE_HASH_KEY (0x30)
-#define GRN_TABLE_PAT_KEY (0x31)
-#define GRN_TABLE_DAT_KEY (0x32)
-#define GRN_TABLE_NO_KEY (0x33)
-#define GRN_DB (0x37)
-#define GRN_COLUMN_FIX_SIZE (0x40)
-#define GRN_COLUMN_VAR_SIZE (0x41)
-#define GRN_COLUMN_INDEX (0x48)
-
-typedef struct _grn_section grn_section;
-typedef struct _grn_obj_header grn_obj_header;
-
-struct _grn_section {
- unsigned int offset;
- unsigned int length;
- unsigned int weight;
- grn_id domain;
-};
-
-struct _grn_obj_header {
- unsigned char type;
- unsigned char impl_flags;
- grn_obj_flags flags;
- grn_id domain;
-};
-
-struct _grn_obj {
- grn_obj_header header;
- union {
- struct {
- char *head;
- char *curr;
- char *tail;
- } b;
- struct {
- grn_obj *body;
- grn_section *sections;
- int n_sections;
- } v;
- } u;
-};
-
-#define GRN_OBJ_REFER (0x01<<0)
-#define GRN_OBJ_OUTPLACE (0x01<<1)
-
-#define GRN_OBJ_INIT(obj,obj_type,obj_flags,obj_domain) do { \
- (obj)->header.type = (obj_type);\
- (obj)->header.impl_flags = (obj_flags);\
- (obj)->header.flags = 0;\
- (obj)->header.domain = (obj_domain);\
- (obj)->u.b.head = NULL;\
- (obj)->u.b.curr = NULL;\
- (obj)->u.b.tail = NULL;\
-} while (0)
-
-#define GRN_OBJ_FIN(ctx,obj) (grn_obj_close((ctx), (obj)))
-
-typedef struct _grn_db_create_optarg grn_db_create_optarg;
-
-struct _grn_db_create_optarg {
- char **builtin_type_names;
- int n_builtin_type_names;
-};
-
-GRN_API grn_obj *grn_db_create(grn_ctx *ctx, const char *path, grn_db_create_optarg *optarg);
-
-#define GRN_DB_OPEN_OR_CREATE(ctx,path,optarg,db) \
- (((db) = grn_db_open((ctx), (path))) || (db = grn_db_create((ctx), (path), (optarg))))
-
-GRN_API grn_obj *grn_db_open(grn_ctx *ctx, const char *path);
-GRN_API void grn_db_touch(grn_ctx *ctx, grn_obj *db);
-
-GRN_API grn_rc grn_ctx_use(grn_ctx *ctx, grn_obj *db);
-GRN_API grn_obj *grn_ctx_db(grn_ctx *ctx);
-GRN_API grn_obj *grn_ctx_get(grn_ctx *ctx, const char *name, int name_size);
-
-typedef enum {
- GRN_DB_VOID = 0,
- GRN_DB_DB,
- GRN_DB_OBJECT,
- GRN_DB_BOOL,
- GRN_DB_INT8,
- GRN_DB_UINT8,
- GRN_DB_INT16,
- GRN_DB_UINT16,
- GRN_DB_INT32,
- GRN_DB_UINT32,
- GRN_DB_INT64,
- GRN_DB_UINT64,
- GRN_DB_FLOAT,
- GRN_DB_TIME,
- GRN_DB_SHORT_TEXT,
- GRN_DB_TEXT,
- GRN_DB_LONG_TEXT,
- GRN_DB_TOKYO_GEO_POINT,
- GRN_DB_WGS84_GEO_POINT
-} grn_builtin_type;
-
-typedef enum {
- GRN_DB_MECAB = 64,
- GRN_DB_DELIMIT,
- GRN_DB_UNIGRAM,
- GRN_DB_BIGRAM,
- GRN_DB_TRIGRAM
-} grn_builtin_tokenizer;
-
-GRN_API grn_obj *grn_ctx_at(grn_ctx *ctx, grn_id id);
-
-GRN_API grn_obj *grn_type_create(grn_ctx *ctx, const char *name, unsigned int name_size,
- grn_obj_flags flags, unsigned int size);
-
-GRN_API grn_rc grn_plugin_register(grn_ctx *ctx, const char *name);
-GRN_API grn_rc grn_plugin_register_by_path(grn_ctx *ctx, const char *path);
-GRN_API const char *grn_plugin_get_system_plugins_dir(void);
-GRN_API const char *grn_plugin_get_suffix(void);
-
-typedef struct {
- const char *name;
- unsigned int name_size;
- grn_obj value;
-} grn_expr_var;
-
-typedef grn_rc (*grn_plugin_func)(grn_ctx *ctx);
-
-typedef enum {
- GRN_PROC_INVALID = 0,
- GRN_PROC_TOKENIZER,
- GRN_PROC_COMMAND,
- GRN_PROC_FUNCTION,
- GRN_PROC_HOOK,
- GRN_PROC_NORMALIZER,
- GRN_PROC_TOKEN_FILTER
-} grn_proc_type;
-
-GRN_API grn_obj *grn_proc_create(grn_ctx *ctx,
- const char *name, int name_size, grn_proc_type type,
- grn_proc_func *init, grn_proc_func *next, grn_proc_func *fin,
- unsigned int nvars, grn_expr_var *vars);
-GRN_API grn_obj *grn_proc_get_info(grn_ctx *ctx, grn_user_data *user_data,
- grn_expr_var **vars, unsigned int *nvars, grn_obj **caller);
-GRN_API grn_proc_type grn_proc_get_type(grn_ctx *ctx, grn_obj *proc);
-
-/*-------------------------------------------------------------
- * API for table
- */
-
-#define GRN_TABLE_MAX_KEY_SIZE (0x1000)
-
-GRN_API grn_obj *grn_table_create(grn_ctx *ctx,
- const char *name, unsigned int name_size,
- const char *path, grn_obj_flags flags,
- grn_obj *key_type, grn_obj *value_type);
-
-#define GRN_TABLE_OPEN_OR_CREATE(ctx,name,name_size,path,flags,key_type,value_type,table) \
- (((table) = grn_ctx_get((ctx), (name), (name_size))) ||\
- ((table) = grn_table_create((ctx), (name), (name_size), (path), (flags), (key_type), (value_type))))
-
-/* TODO: int *added -> grn_bool *added */
-GRN_API grn_id grn_table_add(grn_ctx *ctx, grn_obj *table,
- const void *key, unsigned int key_size, int *added);
-GRN_API grn_id grn_table_get(grn_ctx *ctx, grn_obj *table,
- const void *key, unsigned int key_size);
-GRN_API grn_id grn_table_at(grn_ctx *ctx, grn_obj *table, grn_id id);
-GRN_API grn_id grn_table_lcp_search(grn_ctx *ctx, grn_obj *table,
- const void *key, unsigned int key_size);
-GRN_API int grn_table_get_key(grn_ctx *ctx, grn_obj *table,
- grn_id id, void *keybuf, int buf_size);
-GRN_API grn_rc grn_table_delete(grn_ctx *ctx, grn_obj *table,
- const void *key, unsigned int key_size);
-GRN_API grn_rc grn_table_delete_by_id(grn_ctx *ctx, grn_obj *table, grn_id id);
-GRN_API grn_rc grn_table_update_by_id(grn_ctx *ctx, grn_obj *table, grn_id id,
- const void *dest_key, unsigned int dest_key_size);
-GRN_API grn_rc grn_table_update(grn_ctx *ctx, grn_obj *table,
- const void *src_key, unsigned int src_key_size,
- const void *dest_key, unsigned int dest_key_size);
-GRN_API grn_rc grn_table_truncate(grn_ctx *ctx, grn_obj *table);
-
-typedef grn_obj grn_table_cursor;
-
-#define GRN_CURSOR_ASCENDING (0x00<<0)
-#define GRN_CURSOR_DESCENDING (0x01<<0)
-#define GRN_CURSOR_GE (0x00<<1)
-#define GRN_CURSOR_GT (0x01<<1)
-#define GRN_CURSOR_LE (0x00<<2)
-#define GRN_CURSOR_LT (0x01<<2)
-#define GRN_CURSOR_BY_KEY (0x00<<3)
-#define GRN_CURSOR_BY_ID (0x01<<3)
-#define GRN_CURSOR_PREFIX (0x01<<4)
-#define GRN_CURSOR_SIZE_BY_BIT (0x01<<5)
-#define GRN_CURSOR_RK (0x01<<6)
-
-GRN_API grn_table_cursor *grn_table_cursor_open(grn_ctx *ctx, grn_obj *table,
- const void *min, unsigned int min_size,
- const void *max, unsigned int max_size,
- int offset, int limit, int flags);
-GRN_API grn_rc grn_table_cursor_close(grn_ctx *ctx, grn_table_cursor *tc);
-GRN_API grn_id grn_table_cursor_next(grn_ctx *ctx, grn_table_cursor *tc);
-GRN_API int grn_table_cursor_get_key(grn_ctx *ctx, grn_table_cursor *tc, void **key);
-GRN_API int grn_table_cursor_get_value(grn_ctx *ctx, grn_table_cursor *tc, void **value);
-GRN_API grn_rc grn_table_cursor_set_value(grn_ctx *ctx, grn_table_cursor *tc,
- const void *value, int flags);
-GRN_API grn_rc grn_table_cursor_delete(grn_ctx *ctx, grn_table_cursor *tc);
-GRN_API grn_obj *grn_table_cursor_table(grn_ctx *ctx, grn_table_cursor *tc);
-
-typedef struct {
- grn_id rid;
- grn_id sid;
- unsigned int pos;
- unsigned int tf;
- unsigned int weight;
- unsigned int rest;
-} grn_posting;
-
-GRN_API grn_obj *grn_index_cursor_open(grn_ctx *ctx, grn_table_cursor *tc, grn_obj *index,
- grn_id rid_min, grn_id rid_max, int flags);
-GRN_API grn_posting *grn_index_cursor_next(grn_ctx *ctx, grn_obj *ic, grn_id *tid);
-
-#define GRN_TABLE_EACH(ctx,table,head,tail,id,key,key_size,value,block) do {\
- (ctx)->errlvl = GRN_LOG_NOTICE;\
- (ctx)->rc = GRN_SUCCESS;\
- if ((ctx)->seqno & 1) {\
- (ctx)->subno++;\
- } else {\
- (ctx)->seqno++;\
- }\
- if (table) {\
- switch ((table)->header.type) {\
- case GRN_TABLE_PAT_KEY :\
- GRN_PAT_EACH((ctx), (grn_pat *)(table), (id), (key), (key_size), (value), block);\
- break;\
- case GRN_TABLE_DAT_KEY :\
- GRN_DAT_EACH((ctx), (grn_dat *)(table), (id), (key), (key_size), block);\
- break;\
- case GRN_TABLE_HASH_KEY :\
- GRN_HASH_EACH((ctx), (grn_hash *)(table), (id), (key), (key_size), (value), block);\
- break;\
- case GRN_TABLE_NO_KEY :\
- GRN_ARRAY_EACH((ctx), (grn_array *)(table), (head), (tail), (id), (value), block);\
- break;\
- }\
- }\
- if ((ctx)->subno) {\
- (ctx)->subno--;\
- } else {\
- (ctx)->seqno++;\
- }\
-} while (0)
-
-typedef struct _grn_table_sort_key grn_table_sort_key;
-typedef unsigned char grn_table_sort_flags;
-
-#define GRN_TABLE_SORT_ASC (0x00<<0)
-#define GRN_TABLE_SORT_DESC (0x01<<0)
-
-struct _grn_table_sort_key {
- grn_obj *key;
- grn_table_sort_flags flags;
- int offset;
-};
-
-GRN_API int grn_table_sort(grn_ctx *ctx, grn_obj *table, int offset, int limit,
- grn_obj *result, grn_table_sort_key *keys, int n_keys);
-
-typedef struct _grn_table_group_result grn_table_group_result;
-typedef unsigned int grn_table_group_flags;
-
-#define GRN_TABLE_GROUP_CALC_COUNT (0x01<<3)
-#define GRN_TABLE_GROUP_CALC_MAX (0x01<<4)
-#define GRN_TABLE_GROUP_CALC_MIN (0x01<<5)
-#define GRN_TABLE_GROUP_CALC_SUM (0x01<<6)
-#define GRN_TABLE_GROUP_CALC_AVG (0x01<<7)
-
-typedef enum {
- GRN_OP_PUSH = 0,
- GRN_OP_POP,
- GRN_OP_NOP,
- GRN_OP_CALL,
- GRN_OP_INTERN,
- GRN_OP_GET_REF,
- GRN_OP_GET_VALUE,
- GRN_OP_AND,
- GRN_OP_AND_NOT,
- /* Deprecated. Just for backward compatibility. */
-#define GRN_OP_BUT GRN_OP_AND_NOT
- GRN_OP_OR,
- GRN_OP_ASSIGN,
- GRN_OP_STAR_ASSIGN,
- GRN_OP_SLASH_ASSIGN,
- GRN_OP_MOD_ASSIGN,
- GRN_OP_PLUS_ASSIGN,
- GRN_OP_MINUS_ASSIGN,
- GRN_OP_SHIFTL_ASSIGN,
- GRN_OP_SHIFTR_ASSIGN,
- GRN_OP_SHIFTRR_ASSIGN,
- GRN_OP_AND_ASSIGN,
- GRN_OP_XOR_ASSIGN,
- GRN_OP_OR_ASSIGN,
- GRN_OP_JUMP,
- GRN_OP_CJUMP,
- GRN_OP_COMMA,
- GRN_OP_BITWISE_OR,
- GRN_OP_BITWISE_XOR,
- GRN_OP_BITWISE_AND,
- GRN_OP_BITWISE_NOT,
- GRN_OP_EQUAL,
- GRN_OP_NOT_EQUAL,
- GRN_OP_LESS,
- GRN_OP_GREATER,
- GRN_OP_LESS_EQUAL,
- GRN_OP_GREATER_EQUAL,
- GRN_OP_IN,
- GRN_OP_MATCH,
- GRN_OP_NEAR,
- GRN_OP_NEAR2,
- GRN_OP_SIMILAR,
- GRN_OP_TERM_EXTRACT,
- GRN_OP_SHIFTL,
- GRN_OP_SHIFTR,
- GRN_OP_SHIFTRR,
- GRN_OP_PLUS,
- GRN_OP_MINUS,
- GRN_OP_STAR,
- GRN_OP_SLASH,
- GRN_OP_MOD,
- GRN_OP_DELETE,
- GRN_OP_INCR,
- GRN_OP_DECR,
- GRN_OP_INCR_POST,
- GRN_OP_DECR_POST,
- GRN_OP_NOT,
- GRN_OP_ADJUST,
- GRN_OP_EXACT,
- GRN_OP_LCP,
- GRN_OP_PARTIAL,
- GRN_OP_UNSPLIT,
- GRN_OP_PREFIX,
- GRN_OP_SUFFIX,
- GRN_OP_GEO_DISTANCE1,
- GRN_OP_GEO_DISTANCE2,
- GRN_OP_GEO_DISTANCE3,
- GRN_OP_GEO_DISTANCE4,
- GRN_OP_GEO_WITHINP5,
- GRN_OP_GEO_WITHINP6,
- GRN_OP_GEO_WITHINP8,
- GRN_OP_OBJ_SEARCH,
- GRN_OP_EXPR_GET_VAR,
- GRN_OP_TABLE_CREATE,
- GRN_OP_TABLE_SELECT,
- GRN_OP_TABLE_SORT,
- GRN_OP_TABLE_GROUP,
- GRN_OP_JSON_PUT,
- GRN_OP_GET_MEMBER
-} grn_operator;
-
-struct _grn_table_group_result {
- grn_obj *table;
- unsigned char key_begin;
- unsigned char key_end;
- int limit;
- grn_table_group_flags flags;
- grn_operator op;
-};
-
-GRN_API grn_rc grn_table_group(grn_ctx *ctx, grn_obj *table,
- grn_table_sort_key *keys, int n_keys,
- grn_table_group_result *results, int n_results);
-GRN_API grn_rc grn_table_setoperation(grn_ctx *ctx, grn_obj *table1, grn_obj *table2,
- grn_obj *res, grn_operator op);
-GRN_API grn_rc grn_table_difference(grn_ctx *ctx, grn_obj *table1, grn_obj *table2,
- grn_obj *res1, grn_obj *res2);
-GRN_API int grn_table_columns(grn_ctx *ctx, grn_obj *table,
- const char *name, unsigned int name_size,
- grn_obj *res);
-
-GRN_API grn_obj *grn_obj_column(grn_ctx *ctx, grn_obj *table,
- const char *name, unsigned int name_size);
-
-GRN_API unsigned int grn_table_size(grn_ctx *ctx, grn_obj *table);
-
-/*-------------------------------------------------------------
- * API for column
- */
-
-#define GRN_COLUMN_NAME_ID "_id"
-#define GRN_COLUMN_NAME_ID_LEN (sizeof(GRN_COLUMN_NAME_ID) - 1)
-#define GRN_COLUMN_NAME_KEY "_key"
-#define GRN_COLUMN_NAME_KEY_LEN (sizeof(GRN_COLUMN_NAME_KEY) - 1)
-#define GRN_COLUMN_NAME_VALUE "_value"
-#define GRN_COLUMN_NAME_VALUE_LEN (sizeof(GRN_COLUMN_NAME_VALUE) - 1)
-#define GRN_COLUMN_NAME_SCORE "_score"
-#define GRN_COLUMN_NAME_SCORE_LEN (sizeof(GRN_COLUMN_NAME_SCORE) - 1)
-#define GRN_COLUMN_NAME_NSUBRECS "_nsubrecs"
-#define GRN_COLUMN_NAME_NSUBRECS_LEN (sizeof(GRN_COLUMN_NAME_NSUBRECS) - 1)
-
-GRN_API grn_obj *grn_column_create(grn_ctx *ctx, grn_obj *table,
- const char *name, unsigned int name_size,
- const char *path, grn_obj_flags flags, grn_obj *type);
-
-#define GRN_COLUMN_OPEN_OR_CREATE(ctx,table,name,name_size,path,flags,type,column) \
- (((column) = grn_obj_column((ctx), (table), (name), (name_size))) ||\
- ((column) = grn_column_create((ctx), (table), (name), (name_size), (path), (flags), (type))))
-
-GRN_API grn_rc grn_column_index_update(grn_ctx *ctx, grn_obj *column,
- grn_id id, unsigned int section,
- grn_obj *oldvalue, grn_obj *newvalue);
-GRN_API grn_obj *grn_column_table(grn_ctx *ctx, grn_obj *column);
-
-/*-------------------------------------------------------------
- * API for db, table and/or column
- */
-
-typedef enum {
- GRN_INFO_ENCODING = 0,
- GRN_INFO_SOURCE,
- GRN_INFO_DEFAULT_TOKENIZER,
- GRN_INFO_ELEMENT_SIZE,
- GRN_INFO_CURR_MAX,
- GRN_INFO_MAX_ELEMENT_SIZE,
- GRN_INFO_SEG_SIZE,
- GRN_INFO_CHUNK_SIZE,
- GRN_INFO_MAX_SECTION,
- GRN_INFO_HOOK_LOCAL_DATA,
- GRN_INFO_ELEMENT_A,
- GRN_INFO_ELEMENT_CHUNK,
- GRN_INFO_ELEMENT_CHUNK_SIZE,
- GRN_INFO_ELEMENT_BUFFER_FREE,
- GRN_INFO_ELEMENT_NTERMS,
- GRN_INFO_ELEMENT_NTERMS_VOID,
- GRN_INFO_ELEMENT_SIZE_IN_CHUNK,
- GRN_INFO_ELEMENT_POS_IN_CHUNK,
- GRN_INFO_ELEMENT_SIZE_IN_BUFFER,
- GRN_INFO_ELEMENT_POS_IN_BUFFER,
- GRN_INFO_ELEMENT_ESTIMATE_SIZE,
- GRN_INFO_NGRAM_UNIT_SIZE,
- /*
- GRN_INFO_VERSION,
- GRN_INFO_CONFIGURE_OPTIONS,
- GRN_INFO_CONFIG_PATH,
- */
- GRN_INFO_PARTIAL_MATCH_THRESHOLD,
- GRN_INFO_II_SPLIT_THRESHOLD,
- GRN_INFO_SUPPORT_ZLIB,
- GRN_INFO_SUPPORT_LZO,
- GRN_INFO_NORMALIZER,
- GRN_INFO_TOKEN_FILTERS
-} grn_info_type;
-
-GRN_API grn_obj *grn_obj_get_info(grn_ctx *ctx, grn_obj *obj, grn_info_type type, grn_obj *valuebuf);
-GRN_API grn_rc grn_obj_set_info(grn_ctx *ctx, grn_obj *obj, grn_info_type type, grn_obj *value);
-GRN_API grn_obj *grn_obj_get_element_info(grn_ctx *ctx, grn_obj *obj, grn_id id,
- grn_info_type type, grn_obj *value);
-GRN_API grn_rc grn_obj_set_element_info(grn_ctx *ctx, grn_obj *obj, grn_id id,
- grn_info_type type, grn_obj *value);
-
-GRN_API grn_bool grn_obj_is_builtin(grn_ctx *ctx, grn_obj *obj);
-
-GRN_API grn_obj *grn_obj_get_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value);
-GRN_API int grn_obj_get_values(grn_ctx *ctx, grn_obj *obj, grn_id offset, void **values);
-
-#define GRN_COLUMN_EACH(ctx,column,id,value,block) do {\
- int _n;\
- grn_id id = 1;\
- while ((_n = grn_obj_get_values(ctx, column, id, (void **)&value)) > 0) {\
- for (; _n; _n--, id++, value++) {\
- block\
- }\
- }\
-} while (0)
-
-#define GRN_OBJ_SET_MASK (0x07)
-#define GRN_OBJ_SET (0x01)
-#define GRN_OBJ_INCR (0x02)
-#define GRN_OBJ_DECR (0x03)
-#define GRN_OBJ_APPEND (0x04)
-#define GRN_OBJ_PREPEND (0x05)
-#define GRN_OBJ_GET (0x01<<4)
-#define GRN_OBJ_COMPARE (0x01<<5)
-#define GRN_OBJ_LOCK (0x01<<6)
-#define GRN_OBJ_UNLOCK (0x01<<7)
-
-GRN_API grn_rc grn_obj_set_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value, int flags);
-GRN_API grn_rc grn_obj_remove(grn_ctx *ctx, grn_obj *obj);
-GRN_API grn_rc grn_obj_rename(grn_ctx *ctx, grn_obj *obj,
- const char *name, unsigned int name_size);
-GRN_API grn_rc grn_table_rename(grn_ctx *ctx, grn_obj *table,
- const char *name, unsigned int name_size);
-
-GRN_API grn_rc grn_column_rename(grn_ctx *ctx, grn_obj *column,
- const char *name, unsigned int name_size);
-
-GRN_API grn_rc grn_obj_close(grn_ctx *ctx, grn_obj *obj);
-GRN_API grn_rc grn_obj_reinit(grn_ctx *ctx, grn_obj *obj, grn_id domain, unsigned char flags);
-GRN_API void grn_obj_unlink(grn_ctx *ctx, grn_obj *obj);
-
-GRN_API grn_user_data *grn_obj_user_data(grn_ctx *ctx, grn_obj *obj);
-
-GRN_API grn_rc grn_obj_set_finalizer(grn_ctx *ctx, grn_obj *obj, grn_proc_func *func);
-
-GRN_API const char *grn_obj_path(grn_ctx *ctx, grn_obj *obj);
-GRN_API int grn_obj_name(grn_ctx *ctx, grn_obj *obj, char *namebuf, int buf_size);
-
-GRN_API int grn_column_name(grn_ctx *ctx, grn_obj *obj, char *namebuf, int buf_size);
-
-GRN_API grn_id grn_obj_get_range(grn_ctx *ctx, grn_obj *obj);
-
-#define GRN_OBJ_GET_DOMAIN(obj) \
- ((obj)->header.type == GRN_TABLE_NO_KEY ? GRN_ID_NIL : (obj)->header.domain)
-
-GRN_API int grn_obj_expire(grn_ctx *ctx, grn_obj *obj, int threshold);
-GRN_API int grn_obj_check(grn_ctx *ctx, grn_obj *obj);
-GRN_API grn_rc grn_obj_lock(grn_ctx *ctx, grn_obj *obj, grn_id id, int timeout);
-GRN_API grn_rc grn_obj_unlock(grn_ctx *ctx, grn_obj *obj, grn_id id);
-GRN_API grn_rc grn_obj_clear_lock(grn_ctx *ctx, grn_obj *obj);
-GRN_API unsigned int grn_obj_is_locked(grn_ctx *ctx, grn_obj *obj);
-GRN_API int grn_obj_defrag(grn_ctx *ctx, grn_obj *obj, int threshold);
-
-GRN_API grn_obj *grn_obj_db(grn_ctx *ctx, grn_obj *obj);
-
-GRN_API grn_id grn_obj_id(grn_ctx *ctx, grn_obj *obj);
-
-typedef struct _grn_search_optarg grn_search_optarg;
-
-struct _grn_search_optarg {
- grn_operator mode;
- int similarity_threshold;
- int max_interval;
- int *weight_vector;
- int vector_size;
- grn_obj *proc;
- int max_size;
-};
-
-GRN_API grn_rc grn_obj_search(grn_ctx *ctx, grn_obj *obj, grn_obj *query,
- grn_obj *res, grn_operator op, grn_search_optarg *optarg);
-
-typedef grn_rc grn_selector_func(grn_ctx *ctx, grn_obj *table, grn_obj *index,
- int nargs, grn_obj **args,
- grn_obj *res, grn_operator op);
-
-GRN_API grn_rc grn_proc_set_selector(grn_ctx *ctx, grn_obj *proc,
- grn_selector_func selector);
-
-/*-------------------------------------------------------------
- * grn_vector
-*/
-
-GRN_API unsigned int grn_vector_size(grn_ctx *ctx, grn_obj *vector);
-
-GRN_API grn_rc grn_vector_add_element(grn_ctx *ctx, grn_obj *vector,
- const char *str, unsigned int str_len,
- unsigned int weight, grn_id domain);
-
-GRN_API unsigned int grn_vector_get_element(grn_ctx *ctx, grn_obj *vector,
- unsigned int offset, const char **str,
- unsigned int *weight, grn_id *domain);
-
-/*-------------------------------------------------------------
- * grn_uvector
-*/
-
-GRN_API unsigned int grn_uvector_size(grn_ctx *ctx, grn_obj *uvector);
-
-GRN_API grn_rc grn_uvector_add_element(grn_ctx *ctx, grn_obj *vector,
- grn_id id, unsigned int weight);
-
-GRN_API grn_id grn_uvector_get_element(grn_ctx *ctx, grn_obj *uvector,
- unsigned int offset,
- unsigned int *weight);
-
-/*-------------------------------------------------------------
- * API for hook
- */
-
-GRN_API int grn_proc_call_next(grn_ctx *ctx, grn_obj *exec_info, grn_obj *in, grn_obj *out);
-GRN_API void *grn_proc_get_ctx_local_data(grn_ctx *ctx, grn_obj *exec_info);
-GRN_API void *grn_proc_get_hook_local_data(grn_ctx *ctx, grn_obj *exec_info);
-
-typedef enum {
- GRN_HOOK_SET = 0,
- GRN_HOOK_GET,
- GRN_HOOK_INSERT,
- GRN_HOOK_DELETE,
- GRN_HOOK_SELECT
-} grn_hook_entry;
-
-GRN_API grn_rc grn_obj_add_hook(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry,
- int offset, grn_obj *proc, grn_obj *data);
-GRN_API int grn_obj_get_nhooks(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry);
-GRN_API grn_obj *grn_obj_get_hook(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry,
- int offset, grn_obj *data);
-GRN_API grn_rc grn_obj_delete_hook(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry, int offset);
-
-GRN_API grn_obj *grn_obj_open(grn_ctx *ctx, unsigned char type, grn_obj_flags flags, grn_id domain);
-
-GRN_API int grn_column_index(grn_ctx *ctx, grn_obj *column, grn_operator op,
- grn_obj **indexbuf, int buf_size, int *section);
-
-GRN_API grn_rc grn_obj_delete_by_id(grn_ctx *ctx, grn_obj *db, grn_id id, grn_bool removep);
-GRN_API grn_rc grn_obj_path_by_id(grn_ctx *ctx, grn_obj *db, grn_id id, char *buffer);
-
-/* geo */
-
-typedef struct {
- int latitude;
- int longitude;
-} grn_geo_point;
-
-GRN_API grn_rc grn_geo_select_in_rectangle(grn_ctx *ctx,
- grn_obj *index,
- grn_obj *top_left_point,
- grn_obj *bottom_right_point,
- grn_obj *res,
- grn_operator op);
-GRN_API int grn_geo_estimate_in_rectangle(grn_ctx *ctx,
- grn_obj *index,
- grn_obj *top_left_point,
- grn_obj *bottom_right_point);
-GRN_API grn_obj *grn_geo_cursor_open_in_rectangle(grn_ctx *ctx,
- grn_obj *index,
- grn_obj *top_left_point,
- grn_obj *bottom_right_point,
- int offset,
- int limit);
-GRN_API grn_posting *grn_geo_cursor_next(grn_ctx *ctx, grn_obj *cursor);
-
-
-/* query & snippet */
-
-#ifndef GRN_QUERY_AND
-#define GRN_QUERY_AND '+'
-#endif /* GRN_QUERY_AND */
-#ifndef GRN_QUERY_AND_NOT
-# ifdef GRN_QUERY_BUT
- /* Deprecated. Just for backward compatibility. */
-# define GRN_QUERY_AND_NOT GRN_QUERY_BUT
-# else
-# define GRN_QUERY_AND_NOT '-'
-# endif /* GRN_QUERY_BUT */
-#endif /* GRN_QUERY_AND_NOT */
-#ifndef GRN_QUERY_ADJ_INC
-#define GRN_QUERY_ADJ_INC '>'
-#endif /* GRN_QUERY_ADJ_POS2 */
-#ifndef GRN_QUERY_ADJ_DEC
-#define GRN_QUERY_ADJ_DEC '<'
-#endif /* GRN_QUERY_ADJ_POS1 */
-#ifndef GRN_QUERY_ADJ_NEG
-#define GRN_QUERY_ADJ_NEG '~'
-#endif /* GRN_QUERY_ADJ_NEG */
-#ifndef GRN_QUERY_PREFIX
-#define GRN_QUERY_PREFIX '*'
-#endif /* GRN_QUERY_PREFIX */
-#ifndef GRN_QUERY_PARENL
-#define GRN_QUERY_PARENL '('
-#endif /* GRN_QUERY_PARENL */
-#ifndef GRN_QUERY_PARENR
-#define GRN_QUERY_PARENR ')'
-#endif /* GRN_QUERY_PARENR */
-#ifndef GRN_QUERY_QUOTEL
-#define GRN_QUERY_QUOTEL '"'
-#endif /* GRN_QUERY_QUOTEL */
-#ifndef GRN_QUERY_QUOTER
-#define GRN_QUERY_QUOTER '"'
-#endif /* GRN_QUERY_QUOTER */
-#ifndef GRN_QUERY_ESCAPE
-#define GRN_QUERY_ESCAPE '\\'
-#endif /* GRN_QUERY_ESCAPE */
-#ifndef GRN_QUERY_COLUMN
-#define GRN_QUERY_COLUMN ':'
-#endif /* GRN_QUERY_COLUMN */
-
-typedef struct _grn_snip_mapping grn_snip_mapping;
-
-struct _grn_snip_mapping {
- void *dummy;
-};
-
-#define GRN_SNIP_NORMALIZE (0x01<<0)
-#define GRN_SNIP_COPY_TAG (0x01<<1)
-#define GRN_SNIP_SKIP_LEADING_SPACES (0x01<<2)
-
-#define GRN_SNIP_MAPPING_HTML_ESCAPE ((grn_snip_mapping *)-1)
-
-GRN_API grn_obj *grn_snip_open(grn_ctx *ctx, int flags, unsigned int width,
- unsigned int max_results,
- const char *defaultopentag, unsigned int defaultopentag_len,
- const char *defaultclosetag, unsigned int defaultclosetag_len,
- grn_snip_mapping *mapping);
-GRN_API grn_rc grn_snip_add_cond(grn_ctx *ctx, grn_obj *snip,
- const char *keyword, unsigned int keyword_len,
- const char *opentag, unsigned int opentag_len,
- const char *closetag, unsigned int closetag_len);
-GRN_API grn_rc grn_snip_set_normalizer(grn_ctx *ctx, grn_obj *snip,
- grn_obj *normalizer);
-GRN_API grn_obj *grn_snip_get_normalizer(grn_ctx *ctx, grn_obj *snip);
-GRN_API grn_rc grn_snip_exec(grn_ctx *ctx, grn_obj *snip,
- const char *string, unsigned int string_len,
- unsigned int *nresults, unsigned int *max_tagged_len);
-GRN_API grn_rc grn_snip_get_result(grn_ctx *ctx, grn_obj *snip, const unsigned int index,
- char *result, unsigned int *result_len);
-
-/* log */
-
-#define GRN_LOG_TIME (0x01<<0)
-#define GRN_LOG_TITLE (0x01<<1)
-#define GRN_LOG_MESSAGE (0x01<<2)
-#define GRN_LOG_LOCATION (0x01<<3)
-
-/* Deprecated since 2.1.2. Use grn_logger instead. */
-typedef struct _grn_logger_info grn_logger_info;
-
-/* Deprecated since 2.1.2. Use grn_logger instead. */
-struct _grn_logger_info {
- grn_log_level max_level;
- int flags;
- void (*func)(int, const char *, const char *, const char *, const char *, void *);
- void *func_arg;
-};
-
-/* Deprecated since 2.1.2. Use grn_logger_set() instead. */
-GRN_API grn_rc grn_logger_info_set(grn_ctx *ctx, const grn_logger_info *info);
-
-typedef struct _grn_logger grn_logger;
-
-struct _grn_logger {
- grn_log_level max_level;
- int flags;
- void *user_data;
- void (*log)(grn_ctx *ctx, grn_log_level level,
- const char *timestamp, const char *title, const char *message,
- const char *location, void *user_data);
- void (*reopen)(grn_ctx *ctx, void *user_data);
- void (*fin)(grn_ctx *ctx, void *user_data);
-};
-
-GRN_API grn_rc grn_logger_set(grn_ctx *ctx, const grn_logger *logger);
-
-GRN_API void grn_logger_set_max_level(grn_ctx *ctx, grn_log_level max_level);
-GRN_API grn_log_level grn_logger_get_max_level(grn_ctx *ctx);
-
-#ifdef __GNUC__
-#define GRN_ATTRIBUTE_PRINTF(fmt_pos) \
- __attribute__ ((format(printf, fmt_pos, fmt_pos + 1)))
-#else
-#define GRN_ATTRIBUTE_PRINTF(fmt_pos)
-#endif /* __GNUC__ */
-
-GRN_API void grn_logger_put(grn_ctx *ctx, grn_log_level level,
- const char *file, int line, const char *func, const char *fmt, ...) GRN_ATTRIBUTE_PRINTF(6);
-GRN_API void grn_logger_reopen(grn_ctx *ctx);
-
-GRN_API grn_bool grn_logger_pass(grn_ctx *ctx, grn_log_level level);
-
-#ifndef GRN_LOG_DEFAULT_LEVEL
-#define GRN_LOG_DEFAULT_LEVEL GRN_LOG_NOTICE
-#endif /* GRN_LOG_DEFAULT_LEVEL */
-
-GRN_API void grn_default_logger_set_max_level(grn_log_level level);
-GRN_API grn_log_level grn_default_logger_get_max_level(void);
-GRN_API void grn_default_logger_set_path(const char *path);
-GRN_API const char *grn_default_logger_get_path(void);
-
-#define GRN_LOG(ctx,level,...) do {\
- if (grn_logger_pass(ctx, level)) {\
- grn_logger_put(ctx, (level), __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__); \
- }\
-} while (0)
-
-typedef struct _grn_query_logger grn_query_logger;
-
-struct _grn_query_logger {
- unsigned int flags;
- void *user_data;
- void (*log)(grn_ctx *ctx, unsigned int flag,
- const char *timestamp, const char *info, const char *message,
- void *user_data);
- void (*reopen)(grn_ctx *ctx, void *user_data);
- void (*fin)(grn_ctx *ctx, void *user_data);
-};
-
-GRN_API grn_rc grn_query_logger_set(grn_ctx *ctx, const grn_query_logger *logger);
-
-GRN_API void grn_query_logger_put(grn_ctx *ctx, unsigned int flag,
- const char *mark,
- const char *format, ...) GRN_ATTRIBUTE_PRINTF(4);
-GRN_API void grn_query_logger_reopen(grn_ctx *ctx);
-
-GRN_API grn_bool grn_query_logger_pass(grn_ctx *ctx, unsigned int flag);
-
-GRN_API void grn_default_query_logger_set_flags(unsigned int flags);
-GRN_API unsigned int grn_default_query_logger_get_flags(void);
-GRN_API void grn_default_query_logger_set_path(const char *path);
-GRN_API const char *grn_default_query_logger_get_path(void);
-
-#define GRN_QUERY_LOG(ctx, flag, mark, format, ...) do {\
- if (grn_query_logger_pass(ctx, flag)) {\
- grn_query_logger_put(ctx, (flag), (mark), format, __VA_ARGS__);\
- }\
-} while (0)
-
-/* grn_bulk */
-
-#define GRN_BULK_BUFSIZE (sizeof(grn_obj) - sizeof(grn_obj_header))
-/* This assumes that GRN_BULK_BUFSIZE is less than 32 (= 0x20). */
-#define GRN_BULK_BUFSIZE_MAX 0x1f
-#define GRN_BULK_SIZE_IN_FLAGS(flags) ((flags) & GRN_BULK_BUFSIZE_MAX)
-#define GRN_BULK_OUTP(bulk) ((bulk)->header.impl_flags & GRN_OBJ_OUTPLACE)
-#define GRN_BULK_REWIND(bulk) do {\
- if ((bulk)->header.type == GRN_VECTOR) {\
- grn_obj *_body = (bulk)->u.v.body;\
- if (_body) {\
- if (GRN_BULK_OUTP(_body)) {\
- (_body)->u.b.curr = (_body)->u.b.head;\
- } else {\
- (_body)->header.flags &= ~GRN_BULK_BUFSIZE_MAX;\
- }\
- }\
- (bulk)->u.v.n_sections = 0;\
- } else {\
- if (GRN_BULK_OUTP(bulk)) {\
- (bulk)->u.b.curr = (bulk)->u.b.head;\
- } else {\
- (bulk)->header.flags &= ~GRN_BULK_BUFSIZE_MAX;\
- }\
- }\
-} while (0)
-#define GRN_BULK_WSIZE(bulk) \
- (GRN_BULK_OUTP(bulk)\
- ? ((bulk)->u.b.tail - (bulk)->u.b.head)\
- : GRN_BULK_BUFSIZE)
-#define GRN_BULK_REST(bulk) \
- (GRN_BULK_OUTP(bulk)\
- ? ((bulk)->u.b.tail - (bulk)->u.b.curr)\
- : GRN_BULK_BUFSIZE - (bulk)->header.flags)
-#define GRN_BULK_VSIZE(bulk) \
- (GRN_BULK_OUTP(bulk)\
- ? ((bulk)->u.b.curr - (bulk)->u.b.head)\
- : GRN_BULK_SIZE_IN_FLAGS((bulk)->header.flags))
-#define GRN_BULK_EMPTYP(bulk) \
- (GRN_BULK_OUTP(bulk)\
- ? ((bulk)->u.b.curr == (bulk)->u.b.head)\
- : !(GRN_BULK_SIZE_IN_FLAGS((bulk)->header.flags)))
-#define GRN_BULK_HEAD(bulk) \
- (GRN_BULK_OUTP(bulk)\
- ? ((bulk)->u.b.head)\
- : (char *)&((bulk)->u.b.head))
-#define GRN_BULK_CURR(bulk) \
- (GRN_BULK_OUTP(bulk)\
- ? ((bulk)->u.b.curr)\
- : (char *)&((bulk)->u.b.head) + GRN_BULK_SIZE_IN_FLAGS((bulk)->header.flags))
-#define GRN_BULK_TAIL(bulk) \
- (GRN_BULK_OUTP(bulk)\
- ? ((bulk)->u.b.tail)\
- : (char *)&((bulk)[1]))
-
-GRN_API grn_rc grn_bulk_reinit(grn_ctx *ctx, grn_obj *bulk, unsigned int size);
-GRN_API grn_rc grn_bulk_resize(grn_ctx *ctx, grn_obj *bulk, unsigned int newsize);
-GRN_API grn_rc grn_bulk_write(grn_ctx *ctx, grn_obj *bulk,
- const char *str, unsigned int len);
-GRN_API grn_rc grn_bulk_write_from(grn_ctx *ctx, grn_obj *bulk,
- const char *str, unsigned int from, unsigned int len);
-GRN_API grn_rc grn_bulk_reserve(grn_ctx *ctx, grn_obj *bulk, unsigned int len);
-GRN_API grn_rc grn_bulk_space(grn_ctx *ctx, grn_obj *bulk, unsigned int len);
-GRN_API grn_rc grn_bulk_truncate(grn_ctx *ctx, grn_obj *bulk, unsigned int len);
-GRN_API grn_rc grn_bulk_fin(grn_ctx *ctx, grn_obj *bulk);
-
-/* grn_text */
-
-GRN_API grn_rc grn_text_itoa(grn_ctx *ctx, grn_obj *bulk, int i);
-GRN_API grn_rc grn_text_itoa_padded(grn_ctx *ctx, grn_obj *bulk, int i, char ch, unsigned int len);
-GRN_API grn_rc grn_text_lltoa(grn_ctx *ctx, grn_obj *bulk, long long int i);
-GRN_API grn_rc grn_text_ftoa(grn_ctx *ctx, grn_obj *bulk, double d);
-GRN_API grn_rc grn_text_itoh(grn_ctx *ctx, grn_obj *bulk, int i, unsigned int len);
-GRN_API grn_rc grn_text_itob(grn_ctx *ctx, grn_obj *bulk, grn_id id);
-GRN_API grn_rc grn_text_lltob32h(grn_ctx *ctx, grn_obj *bulk, long long int i);
-GRN_API grn_rc grn_text_benc(grn_ctx *ctx, grn_obj *bulk, unsigned int v);
-GRN_API grn_rc grn_text_esc(grn_ctx *ctx, grn_obj *bulk, const char *s, unsigned int len);
-GRN_API grn_rc grn_text_urlenc(grn_ctx *ctx, grn_obj *buf,
- const char *str, unsigned int len);
-GRN_API const char *grn_text_urldec(grn_ctx *ctx, grn_obj *buf,
- const char *s, const char *e, char d);
-GRN_API grn_rc grn_text_escape_xml(grn_ctx *ctx, grn_obj *buf,
- const char *s, unsigned int len);
-GRN_API grn_rc grn_text_time2rfc1123(grn_ctx *ctx, grn_obj *bulk, int sec);
-GRN_API grn_rc grn_text_printf(grn_ctx *ctx, grn_obj *bulk,
- const char *format, ...) GRN_ATTRIBUTE_PRINTF(3);
-GRN_API grn_rc grn_text_vprintf(grn_ctx *ctx, grn_obj *bulk,
- const char *format, va_list args);
-
-typedef struct _grn_obj_format grn_obj_format;
-
-#define GRN_OBJ_FORMAT_WITH_COLUMN_NAMES (0x01<<0)
-#define GRN_OBJ_FORMAT_AS_ARRAY (0x01<<3)
-/* Deprecated since 4.0.1. It will be removed at 5.0.0.
- Use GRN_OBJ_FORMAT_AS_ARRAY instead.*/
-#define GRN_OBJ_FORMAT_ASARRAY GRN_OBJ_FORMAT_AS_ARRAY
-#define GRN_OBJ_FORMAT_WITH_WEIGHT (0x01<<4)
-
-struct _grn_obj_format {
- grn_obj columns;
- const void *min;
- const void *max;
- unsigned int min_size;
- unsigned int max_size;
- int nhits;
- int offset;
- int limit;
- int hits_offset;
- int flags;
- grn_obj *expression;
-};
-
-#define GRN_OBJ_FORMAT_INIT(format,format_nhits,format_offset,format_limit,format_hits_offset) do { \
- GRN_PTR_INIT(&(format)->columns, GRN_OBJ_VECTOR, GRN_ID_NIL);\
- (format)->nhits = (format_nhits);\
- (format)->offset = (format_offset);\
- (format)->limit = (format_limit);\
- (format)->hits_offset = (format_hits_offset);\
- (format)->flags = 0;\
- (format)->expression = NULL;\
-} while (0)
-
-#define GRN_OBJ_FORMAT_FIN(ctx,format) do {\
- int ncolumns = GRN_BULK_VSIZE(&(format)->columns) / sizeof(grn_obj *);\
- grn_obj **columns = (grn_obj **)GRN_BULK_HEAD(&(format)->columns);\
- while (ncolumns--) { grn_obj_unlink((ctx), *columns++); }\
- GRN_OBJ_FIN((ctx), &(format)->columns);\
- if ((format)->expression) { GRN_OBJ_FIN((ctx), (format)->expression); } \
-} while (0)
-
-GRN_API void grn_output_obj(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type,
- grn_obj *obj, grn_obj_format *format);
-GRN_API void grn_output_envelope(grn_ctx *ctx, grn_rc rc,
- grn_obj *head, grn_obj *body, grn_obj *foot,
- const char *file, int line);
-
-GRN_API void grn_ctx_output_array_open(grn_ctx *ctx,
- const char *name, int nelements);
-GRN_API void grn_ctx_output_array_close(grn_ctx *ctx);
-GRN_API void grn_ctx_output_map_open(grn_ctx *ctx,
- const char *name, int nelements);
-GRN_API void grn_ctx_output_map_close(grn_ctx *ctx);
-GRN_API void grn_ctx_output_int32(grn_ctx *ctx, int value);
-GRN_API void grn_ctx_output_int64(grn_ctx *ctx, long long int value);
-GRN_API void grn_ctx_output_float(grn_ctx *ctx, double value);
-GRN_API void grn_ctx_output_cstr(grn_ctx *ctx, const char *value);
-GRN_API void grn_ctx_output_str(grn_ctx *ctx,
- const char *value, unsigned int value_len);
-GRN_API void grn_ctx_output_bool(grn_ctx *ctx, grn_bool value);
-GRN_API void grn_ctx_output_obj(grn_ctx *ctx,
- grn_obj *value, grn_obj_format *format);
-
-
-GRN_API const char *grn_ctx_get_mime_type(grn_ctx *ctx);
-GRN_API void grn_ctx_recv_handler_set(grn_ctx *,
- void (*func)(grn_ctx *, int, void *),
- void *func_arg);
-
-/* obsolete */
-GRN_API grn_rc grn_text_otoj(grn_ctx *ctx, grn_obj *bulk, grn_obj *obj,
- grn_obj_format *format);
-
-/* various values exchanged via grn_obj */
-
-#define GRN_OBJ_DO_SHALLOW_COPY (GRN_OBJ_REFER|GRN_OBJ_OUTPLACE)
-#define GRN_OBJ_VECTOR (0x01<<7)
-
-#define GRN_OBJ_MUTABLE(obj) ((obj) && (obj)->header.type <= GRN_VECTOR)
-
-#define GRN_VALUE_FIX_SIZE_INIT(obj,flags,domain)\
- GRN_OBJ_INIT((obj), ((flags) & GRN_OBJ_VECTOR) ? GRN_UVECTOR : GRN_BULK,\
- ((flags) & GRN_OBJ_DO_SHALLOW_COPY), (domain))
-#define GRN_VALUE_VAR_SIZE_INIT(obj,flags,domain)\
- GRN_OBJ_INIT((obj), ((flags) & GRN_OBJ_VECTOR) ? GRN_VECTOR : GRN_BULK,\
- ((flags) & GRN_OBJ_DO_SHALLOW_COPY), (domain))
-
-#define GRN_VOID_INIT(obj) GRN_OBJ_INIT((obj), GRN_VOID, 0, GRN_DB_VOID)
-#define GRN_TEXT_INIT(obj,flags) \
- GRN_VALUE_VAR_SIZE_INIT(obj, flags, GRN_DB_TEXT)
-#define GRN_SHORT_TEXT_INIT(obj,flags) \
- GRN_VALUE_VAR_SIZE_INIT(obj, flags, GRN_DB_SHORT_TEXT)
-#define GRN_LONG_TEXT_INIT(obj,flags) \
- GRN_VALUE_VAR_SIZE_INIT(obj, flags, GRN_DB_LONG_TEXT)
-#define GRN_TEXT_SET_REF(obj,str,len) do {\
- (obj)->u.b.head = (char *)(str);\
- (obj)->u.b.curr = (char *)(str) + (len);\
-} while (0)
-#define GRN_TEXT_SET(ctx,obj,str,len) do {\
- if ((obj)->header.impl_flags & GRN_OBJ_REFER) {\
- GRN_TEXT_SET_REF((obj), (str), (len));\
- } else {\
- grn_bulk_write_from((ctx), (obj), (const char *)(str), 0, (unsigned int)(len));\
- }\
-} while (0)
-#define GRN_TEXT_PUT(ctx,obj,str,len) \
- grn_bulk_write((ctx), (obj), (const char *)(str), (unsigned int)(len))
-#define GRN_TEXT_PUTC(ctx,obj,c) do {\
- char _c = (c); grn_bulk_write((ctx), (obj), &_c, 1);\
-} while (0)
-
-#define GRN_TEXT_PUTS(ctx,obj,str) GRN_TEXT_PUT((ctx), (obj), (str), strlen(str))
-#define GRN_TEXT_SETS(ctx,obj,str) GRN_TEXT_SET((ctx), (obj), (str), strlen(str))
-#define GRN_TEXT_VALUE(obj) GRN_BULK_HEAD(obj)
-#define GRN_TEXT_LEN(obj) GRN_BULK_VSIZE(obj)
-
-#define GRN_BOOL_INIT(obj,flags) \
- GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_BOOL)
-#define GRN_INT8_INIT(obj,flags) \
- GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_INT8)
-#define GRN_UINT8_INIT(obj,flags) \
- GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_UINT8)
-#define GRN_INT16_INIT(obj,flags) \
- GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_INT16)
-#define GRN_UINT16_INIT(obj,flags) \
- GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_UINT16)
-#define GRN_INT32_INIT(obj,flags) \
- GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_INT32)
-#define GRN_UINT32_INIT(obj,flags) \
- GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_UINT32)
-#define GRN_INT64_INIT(obj,flags) \
- GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_INT64)
-#define GRN_UINT64_INIT(obj,flags) \
- GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_UINT64)
-#define GRN_FLOAT_INIT(obj,flags) \
- GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_FLOAT)
-#define GRN_TIME_INIT(obj,flags) \
- GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_TIME)
-#define GRN_RECORD_INIT GRN_VALUE_FIX_SIZE_INIT
-#define GRN_PTR_INIT(obj,flags,domain)\
- GRN_OBJ_INIT((obj), ((flags) & GRN_OBJ_VECTOR) ? GRN_PVECTOR : GRN_PTR,\
- ((flags) & GRN_OBJ_DO_SHALLOW_COPY), (domain))
-#define GRN_TOKYO_GEO_POINT_INIT(obj,flags) \
- GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_TOKYO_GEO_POINT)
-#define GRN_WGS84_GEO_POINT_INIT(obj,flags) \
- GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_WGS84_GEO_POINT)
-
-#define GRN_BOOL_SET(ctx,obj,val) do {\
- unsigned char _val = (unsigned char)(val);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(unsigned char));\
-} while (0)
-#define GRN_INT8_SET(ctx,obj,val) do {\
- signed char _val = (signed char)(val);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(signed char));\
-} while (0)
-#define GRN_UINT8_SET(ctx,obj,val) do {\
- unsigned char _val = (unsigned char)(val);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(unsigned char));\
-} while (0)
-#define GRN_INT16_SET(ctx,obj,val) do {\
- signed short _val = (signed short)(val);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(signed short));\
-} while (0)
-#define GRN_UINT16_SET(ctx,obj,val) do {\
- unsigned short _val = (unsigned short)(val);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(unsigned short));\
-} while (0)
-#define GRN_INT32_SET(ctx,obj,val) do {\
- int _val = (int)(val);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(int));\
-} while (0)
-#define GRN_UINT32_SET(ctx,obj,val) do {\
- unsigned int _val = (unsigned int)(val);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(unsigned int));\
-} while (0)
-#define GRN_INT64_SET(ctx,obj,val) do {\
- long long int _val = (long long int)(val);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(long long int));\
-} while (0)
-#define GRN_UINT64_SET(ctx,obj,val) do {\
- long long unsigned int _val = (long long unsigned int)(val);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(long long unsigned int));\
-} while (0)
-#define GRN_FLOAT_SET(ctx,obj,val) do {\
- double _val = (double)(val);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(double));\
-} while (0)
-#define GRN_TIME_SET GRN_INT64_SET
-#define GRN_RECORD_SET(ctx,obj,val) do {\
- grn_id _val = (grn_id)(val);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(grn_id));\
-} while (0)
-#define GRN_PTR_SET(ctx,obj,val) do {\
- grn_obj *_val = (grn_obj *)(val);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(grn_obj *));\
-} while (0)
-
-#define GRN_GEO_DEGREE2MSEC(degree)\
- ((int)((degree) * 3600 * 1000 + ((degree) > 0 ? 0.5 : -0.5)))
-#define GRN_GEO_MSEC2DEGREE(msec)\
- ((((int)(msec)) / 3600.0) * 0.001)
-
-#define GRN_GEO_POINT_SET(ctx,obj,_latitude,_longitude) do {\
- grn_geo_point _val;\
- _val.latitude = (int)(_latitude);\
- _val.longitude = (int)(_longitude);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(grn_geo_point));\
-} while (0)
-
-#define GRN_BOOL_SET_AT(ctx,obj,offset,val) do {\
- unsigned char _val = (unsigned char)(val);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val,\
- (offset), sizeof(unsigned char));\
-} while (0)
-#define GRN_INT8_SET_AT(ctx,obj,offset,val) do {\
- signed char _val = (signed char)(val);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val,\
- (offset) * sizeof(signed char), sizeof(signed char));\
-} while (0)
-#define GRN_UINT8_SET_AT(ctx,obj,offset,val) do { \
- unsigned char _val = (unsigned char)(val);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val,\
- (offset) * sizeof(unsigned char), sizeof(unsigned char));\
-} while (0)
-#define GRN_INT16_SET_AT(ctx,obj,offset,val) do {\
- signed short _val = (signed short)(val);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val,\
- (offset) * sizeof(signed short), sizeof(signed short));\
-} while (0)
-#define GRN_UINT16_SET_AT(ctx,obj,offset,val) do { \
- unsigned short _val = (unsigned short)(val);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val,\
- (offset) * sizeof(unsigned short), sizeof(unsigned short));\
-} while (0)
-#define GRN_INT32_SET_AT(ctx,obj,offset,val) do {\
- int _val = (int)(val);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val,\
- (offset) * sizeof(int), sizeof(int));\
-} while (0)
-#define GRN_UINT32_SET_AT(ctx,obj,offset,val) do { \
- unsigned int _val = (unsigned int)(val);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val,\
- (offset) * sizeof(unsigned int), sizeof(unsigned int));\
-} while (0)
-#define GRN_INT64_SET_AT(ctx,obj,offset,val) do {\
- long long int _val = (long long int)(val);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val,\
- (offset) * sizeof(long long int), sizeof(long long int));\
-} while (0)
-#define GRN_UINT64_SET_AT(ctx,obj,offset,val) do {\
- long long unsigned int _val = (long long unsigned int)(val);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val,\
- (offset) * sizeof(long long unsigned int),\
- sizeof(long long unsigned int));\
-} while (0)
-#define GRN_FLOAT_SET_AT(ctx,obj,offset,val) do {\
- double _val = (double)(val);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val,\
- (offset) * sizeof(double), sizeof(double));\
-} while (0)
-#define GRN_TIME_SET_AT GRN_INT64_SET_AT
-#define GRN_RECORD_SET_AT(ctx,obj,offset,val) do {\
- grn_id _val = (grn_id)(val);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val,\
- (offset) * sizeof(grn_id), sizeof(grn_id));\
-} while (0)
-#define GRN_PTR_SET_AT(ctx,obj,offset,val) do {\
- grn_obj *_val = (grn_obj *)(val);\
- grn_bulk_write_from((ctx), (obj), (char *)&_val,\
- (offset) * sizeof(grn_obj *), sizeof(grn_obj *));\
-} while (0)
-
-#define GRN_TIME_USEC_PER_SEC 1000000
-#define GRN_TIME_PACK(sec, usec) ((long long int)(sec) * GRN_TIME_USEC_PER_SEC + (usec))
-#define GRN_TIME_UNPACK(time_value, sec, usec) do {\
- sec = (time_value) / GRN_TIME_USEC_PER_SEC;\
- usec = (time_value) % GRN_TIME_USEC_PER_SEC;\
-} while (0)
-
-GRN_API void grn_time_now(grn_ctx *ctx, grn_obj *obj);
-
-#define GRN_TIME_NOW(ctx,obj) (grn_time_now((ctx), (obj)))
-
-#define GRN_BOOL_VALUE(obj) (*((unsigned char *)GRN_BULK_HEAD(obj)))
-#define GRN_INT8_VALUE(obj) (*((signed char *)GRN_BULK_HEAD(obj)))
-#define GRN_UINT8_VALUE(obj) (*((unsigned char *)GRN_BULK_HEAD(obj)))
-#define GRN_INT16_VALUE(obj) (*((signed short *)GRN_BULK_HEAD(obj)))
-#define GRN_UINT16_VALUE(obj) (*((unsigned short *)GRN_BULK_HEAD(obj)))
-#define GRN_INT32_VALUE(obj) (*((int *)GRN_BULK_HEAD(obj)))
-#define GRN_UINT32_VALUE(obj) (*((unsigned int *)GRN_BULK_HEAD(obj)))
-#define GRN_INT64_VALUE(obj) (*((long long int *)GRN_BULK_HEAD(obj)))
-#define GRN_UINT64_VALUE(obj) (*((long long unsigned int *)GRN_BULK_HEAD(obj)))
-#define GRN_FLOAT_VALUE(obj) (*((double *)GRN_BULK_HEAD(obj)))
-#define GRN_TIME_VALUE GRN_INT64_VALUE
-#define GRN_RECORD_VALUE(obj) (*((grn_id *)GRN_BULK_HEAD(obj)))
-#define GRN_PTR_VALUE(obj) (*((grn_obj **)GRN_BULK_HEAD(obj)))
-#define GRN_GEO_POINT_VALUE(obj,_latitude,_longitude) do {\
- grn_geo_point *_val = (grn_geo_point *)GRN_BULK_HEAD(obj);\
- _latitude = _val->latitude;\
- _longitude = _val->longitude;\
-} while (0)
-
-#define GRN_BOOL_VALUE_AT(obj,offset) (((unsigned char *)GRN_BULK_HEAD(obj))[offset])
-#define GRN_INT8_VALUE_AT(obj,offset) (((signed char *)GRN_BULK_HEAD(obj))[offset])
-#define GRN_UINT8_VALUE_AT(obj,offset) (((unsigned char *)GRN_BULK_HEAD(obj))[offset])
-#define GRN_INT16_VALUE_AT(obj,offset) (((signed short *)GRN_BULK_HEAD(obj))[offset])
-#define GRN_UINT16_VALUE_AT(obj,offset) (((unsigned short *)GRN_BULK_HEAD(obj))[offset])
-#define GRN_INT32_VALUE_AT(obj,offset) (((int *)GRN_BULK_HEAD(obj))[offset])
-#define GRN_UINT32_VALUE_AT(obj,offset) (((unsigned int *)GRN_BULK_HEAD(obj))[offset])
-#define GRN_INT64_VALUE_AT(obj,offset) (((long long int *)GRN_BULK_HEAD(obj))[offset])
-#define GRN_UINT64_VALUE_AT(obj,offset) (((long long unsigned int *)GRN_BULK_HEAD(obj))[offset])
-#define GRN_FLOAT_VALUE_AT(obj,offset) (((double *)GRN_BULK_HEAD(obj))[offset])
-#define GRN_TIME_VALUE_AT GRN_INT64_VALUE_AT
-#define GRN_RECORD_VALUE_AT(obj,offset) (((grn_id *)GRN_BULK_HEAD(obj))[offset])
-#define GRN_PTR_VALUE_AT(obj,offset) (((grn_obj **)GRN_BULK_HEAD(obj))[offset])
-
-#define GRN_BOOL_PUT(ctx,obj,val) do {\
- unsigned char _val = (unsigned char)(val);\
- grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(unsigned char));\
-} while (0)
-#define GRN_INT8_PUT(ctx,obj,val) do {\
- signed char _val = (signed char)(val); grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(signed char));\
-} while (0)
-#define GRN_UINT8_PUT(ctx,obj,val) do {\
- unsigned char _val = (unsigned char)(val);\
- grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(unsigned char));\
-} while (0)
-#define GRN_INT16_PUT(ctx,obj,val) do {\
- signed short _val = (signed short)(val); grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(signed short));\
-} while (0)
-#define GRN_UINT16_PUT(ctx,obj,val) do {\
- unsigned short _val = (unsigned short)(val);\
- grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(unsigned short));\
-} while (0)
-#define GRN_INT32_PUT(ctx,obj,val) do {\
- int _val = (int)(val); grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(int));\
-} while (0)
-#define GRN_UINT32_PUT(ctx,obj,val) do {\
- unsigned int _val = (unsigned int)(val);\
- grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(unsigned int));\
-} while (0)
-#define GRN_INT64_PUT(ctx,obj,val) do {\
- long long int _val = (long long int)(val);\
- grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(long long int));\
-} while (0)
-#define GRN_UINT64_PUT(ctx,obj,val) do {\
- long long unsigned int _val = (long long unsigned int)(val);\
- grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(long long unsigned int));\
-} while (0)
-#define GRN_FLOAT_PUT(ctx,obj,val) do {\
- double _val = (double)(val); grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(double));\
-} while (0)
-#define GRN_TIME_PUT GRN_INT64_PUT
-#define GRN_RECORD_PUT(ctx,obj,val) do {\
- grn_id _val = (grn_id)(val); grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(grn_id));\
-} while (0)
-#define GRN_PTR_PUT(ctx,obj,val) do {\
- grn_obj *_val = (grn_obj *)(val);\
- grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(grn_obj *));\
-} while (0)
-
-/* grn_str: deprecated. use grn_string instead. */
-
-typedef struct {
- const char *orig;
- char *norm;
- short *checks;
- unsigned char *ctypes;
- int flags;
- unsigned int orig_blen;
- unsigned int norm_blen;
- unsigned int length;
- grn_encoding encoding;
-} grn_str;
-
-#define GRN_STR_REMOVEBLANK (0x01<<0)
-#define GRN_STR_WITH_CTYPES (0x01<<1)
-#define GRN_STR_WITH_CHECKS (0x01<<2)
-#define GRN_STR_NORMALIZE GRN_OBJ_KEY_NORMALIZE
-
-GRN_API grn_str *grn_str_open(grn_ctx *ctx, const char *str, unsigned int str_len,
- int flags);
-GRN_API grn_rc grn_str_close(grn_ctx *ctx, grn_str *nstr);
-
-/* grn_string */
-
-#define GRN_STRING_REMOVE_BLANK (0x01<<0)
-#define GRN_STRING_WITH_TYPES (0x01<<1)
-#define GRN_STRING_WITH_CHECKS (0x01<<2)
-#define GRN_STRING_REMOVE_TOKENIZED_DELIMITER (0x01<<3)
-
-#define GRN_NORMALIZER_AUTO ((grn_obj *)1)
-
-#define GRN_CHAR_BLANK 0x80
-#define GRN_CHAR_IS_BLANK(c) ((c) & (GRN_CHAR_BLANK))
-#define GRN_CHAR_TYPE(c) ((c) & 0x7f)
-
-typedef enum {
- GRN_CHAR_NULL = 0,
- GRN_CHAR_ALPHA,
- GRN_CHAR_DIGIT,
- GRN_CHAR_SYMBOL,
- GRN_CHAR_HIRAGANA,
- GRN_CHAR_KATAKANA,
- GRN_CHAR_KANJI,
- GRN_CHAR_OTHERS
-} grn_char_type;
-
-GRN_API grn_obj *grn_string_open(grn_ctx *ctx,
- const char *string,
- unsigned int length_in_bytes,
- grn_obj *normalizer, int flags);
-GRN_API grn_rc grn_string_get_original(grn_ctx *ctx, grn_obj *string,
- const char **original,
- unsigned int *length_in_bytes);
-GRN_API int grn_string_get_flags(grn_ctx *ctx, grn_obj *string);
-GRN_API grn_rc grn_string_get_normalized(grn_ctx *ctx, grn_obj *string,
- const char **normalized,
- unsigned int *length_in_bytes,
- unsigned int *n_characters);
-GRN_API grn_rc grn_string_set_normalized(grn_ctx *ctx, grn_obj *string,
- char *normalized,
- unsigned int length_in_bytes,
- unsigned int n_characters);
-GRN_API const short *grn_string_get_checks(grn_ctx *ctx, grn_obj *string);
-GRN_API grn_rc grn_string_set_checks(grn_ctx *ctx,
- grn_obj *string,
- short *checks);
-GRN_API const unsigned char *grn_string_get_types(grn_ctx *ctx, grn_obj *string);
-GRN_API grn_rc grn_string_set_types(grn_ctx *ctx,
- grn_obj *string,
- unsigned char *types);
-GRN_API grn_encoding grn_string_get_encoding(grn_ctx *ctx, grn_obj *string);
-
-
-GRN_API int grn_charlen(grn_ctx *ctx, const char *str, const char *end);
-
-/* expr */
-
-GRN_API grn_obj *grn_expr_create(grn_ctx *ctx, const char *name, unsigned int name_size);
-GRN_API grn_rc grn_expr_close(grn_ctx *ctx, grn_obj *expr);
-GRN_API grn_obj *grn_expr_add_var(grn_ctx *ctx, grn_obj *expr,
- const char *name, unsigned int name_size);
-GRN_API grn_obj *grn_expr_get_var(grn_ctx *ctx, grn_obj *expr,
- const char *name, unsigned int name_size);
-GRN_API grn_obj *grn_expr_get_var_by_offset(grn_ctx *ctx, grn_obj *expr, unsigned int offset);
-
-GRN_API grn_obj *grn_expr_append_obj(grn_ctx *ctx, grn_obj *expr, grn_obj *obj,
- grn_operator op, int nargs);
-GRN_API grn_obj *grn_expr_append_const(grn_ctx *ctx, grn_obj *expr, grn_obj *obj,
- grn_operator op, int nargs);
-GRN_API grn_obj *grn_expr_append_const_str(grn_ctx *ctx, grn_obj *expr,
- const char *str, unsigned int str_size,
- grn_operator op, int nargs);
-GRN_API grn_obj *grn_expr_append_const_int(grn_ctx *ctx, grn_obj *expr, int i,
- grn_operator op, int nargs);
-GRN_API grn_rc grn_expr_append_op(grn_ctx *ctx, grn_obj *expr, grn_operator op, int nargs);
-
-GRN_API grn_rc grn_expr_get_keywords(grn_ctx *ctx, grn_obj *expr, grn_obj *keywords);
-
-GRN_API grn_rc grn_expr_syntax_escape(grn_ctx *ctx,
- const char *query, int query_size,
- const char *target_characters,
- char escape_character,
- grn_obj *escaped_query);
-GRN_API grn_rc grn_expr_syntax_escape_query(grn_ctx *ctx,
- const char *query, int query_size,
- grn_obj *escaped_query);
-
-GRN_API grn_rc grn_expr_compile(grn_ctx *ctx, grn_obj *expr);
-GRN_API grn_obj *grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs);
-GRN_API grn_rc grn_ctx_push(grn_ctx *ctx, grn_obj *obj);
-GRN_API grn_obj *grn_ctx_pop(grn_ctx *ctx);
-
-GRN_API grn_obj *grn_expr_alloc(grn_ctx *ctx, grn_obj *expr,
- grn_id domain, grn_obj_flags flags);
-
-GRN_API grn_obj *grn_table_select(grn_ctx *ctx, grn_obj *table, grn_obj *expr,
- grn_obj *res, grn_operator op);
-
-GRN_API int grn_obj_columns(grn_ctx *ctx, grn_obj *table,
- const char *str, unsigned int str_size, grn_obj *res);
-
-#define GRN_EXPR_CREATE_FOR_QUERY(ctx,table,expr,var) do {\
- if (((expr) = grn_expr_create((ctx), NULL, 0)) &&\
- ((var) = grn_expr_add_var((ctx), (expr), NULL, 0))) {\
- GRN_RECORD_INIT((var), 0, grn_obj_id((ctx), (table)));\
- } else {\
- (var) = NULL;\
- }\
-} while (0)
-
-typedef unsigned int grn_expr_flags;
-
-#define GRN_EXPR_SYNTAX_QUERY (0x00)
-#define GRN_EXPR_SYNTAX_SCRIPT (0x01)
-#define GRN_EXPR_SYNTAX_OUTPUT_COLUMNS (0x20)
-#define GRN_EXPR_SYNTAX_ADJUSTER (0x40)
-#define GRN_EXPR_ALLOW_PRAGMA (0x02)
-#define GRN_EXPR_ALLOW_COLUMN (0x04)
-#define GRN_EXPR_ALLOW_UPDATE (0x08)
-#define GRN_EXPR_ALLOW_LEADING_NOT (0x10)
-
-GRN_API grn_rc grn_expr_parse(grn_ctx *ctx, grn_obj *expr,
- const char *str, unsigned int str_size,
- grn_obj *default_column, grn_operator default_mode,
- grn_operator default_op, grn_expr_flags flags);
-
-GRN_API grn_obj *grn_expr_snip(grn_ctx *ctx, grn_obj *expr, int flags,
- unsigned int width, unsigned int max_results,
- unsigned int n_tags,
- const char **opentags, unsigned int *opentag_lens,
- const char **closetags, unsigned int *closetag_lens,
- grn_snip_mapping *mapping);
-GRN_API grn_rc grn_expr_snip_add_conditions(grn_ctx *ctx,
- grn_obj *expr,
- grn_obj *snip,
- unsigned int n_tags,
- const char **opentags,
- unsigned int *opentag_lens,
- const char **closetags,
- unsigned int *closetag_lens);
-
-GRN_API grn_table_sort_key *grn_table_sort_key_from_str(grn_ctx *ctx,
- const char *str, unsigned int str_size,
- grn_obj *table, unsigned int *nkeys);
-GRN_API grn_rc grn_table_sort_key_close(grn_ctx *ctx,
- grn_table_sort_key *keys, unsigned int nkeys);
-
-GRN_API grn_bool grn_table_is_grouped(grn_ctx *ctx, grn_obj *table);
-
-GRN_API unsigned int grn_table_max_n_subrecs(grn_ctx *ctx, grn_obj *table);
-
-GRN_API grn_obj *grn_table_create_for_group(grn_ctx *ctx,
- const char *name,
- unsigned int name_size,
- const char *path,
- grn_obj *group_key,
- grn_obj *value_type,
- unsigned int max_n_subrecs);
-
-GRN_API unsigned int grn_table_get_subrecs(grn_ctx *ctx, grn_obj *table,
- grn_id id, grn_id *subrecbuf,
- int *scorebuf, int buf_size);
-
-GRN_API grn_obj *grn_table_tokenize(grn_ctx *ctx, grn_obj *table,
- const char *str, unsigned int str_len,
- grn_obj *buf, grn_bool addp);
-
-GRN_API grn_rc grn_load(grn_ctx *ctx, grn_content_type input_type,
- const char *table, unsigned int table_len,
- const char *columns, unsigned int columns_len,
- const char *values, unsigned int values_len,
- const char *ifexists, unsigned int ifexists_len,
- const char *each, unsigned int each_len);
-
-#define GRN_CTX_MORE (0x01<<0)
-#define GRN_CTX_TAIL (0x01<<1)
-#define GRN_CTX_HEAD (0x01<<2)
-#define GRN_CTX_QUIET (0x01<<3)
-#define GRN_CTX_QUIT (0x01<<4)
-
-GRN_API grn_rc grn_ctx_connect(grn_ctx *ctx, const char *host, int port, int flags);
-GRN_API unsigned int grn_ctx_send(grn_ctx *ctx, const char *str, unsigned int str_len, int flags);
-GRN_API unsigned int grn_ctx_recv(grn_ctx *ctx, char **str, unsigned int *str_len, int *flags);
-
-typedef struct _grn_ctx_info grn_ctx_info;
-
-struct _grn_ctx_info {
- int fd;
- unsigned int com_status;
- grn_obj *outbuf;
- unsigned char stat;
-};
-
-GRN_API grn_rc grn_ctx_info_get(grn_ctx *ctx, grn_ctx_info *info);
-
-GRN_API grn_rc grn_set_segv_handler(void);
-GRN_API grn_rc grn_set_int_handler(void);
-GRN_API grn_rc grn_set_term_handler(void);
-
-/* hash */
-
-typedef struct _grn_hash grn_hash;
-typedef struct _grn_hash_cursor grn_hash_cursor;
-
-GRN_API grn_hash *grn_hash_create(grn_ctx *ctx, const char *path, unsigned int key_size,
- unsigned int value_size, unsigned int flags);
-
-GRN_API grn_hash *grn_hash_open(grn_ctx *ctx, const char *path);
-
-GRN_API grn_rc grn_hash_close(grn_ctx *ctx, grn_hash *hash);
-
-GRN_API grn_id grn_hash_add(grn_ctx *ctx, grn_hash *hash, const void *key,
- unsigned int key_size, void **value, int *added);
-GRN_API grn_id grn_hash_get(grn_ctx *ctx, grn_hash *hash, const void *key,
- unsigned int key_size, void **value);
-
-GRN_API int grn_hash_get_key(grn_ctx *ctx, grn_hash *hash, grn_id id, void *keybuf, int bufsize);
-GRN_API int grn_hash_get_key2(grn_ctx *ctx, grn_hash *hash, grn_id id, grn_obj *bulk);
-GRN_API int grn_hash_get_value(grn_ctx *ctx, grn_hash *hash, grn_id id, void *valuebuf);
-GRN_API grn_rc grn_hash_set_value(grn_ctx *ctx, grn_hash *hash, grn_id id,
- const void *value, int flags);
-
-typedef struct _grn_table_delete_optarg grn_table_delete_optarg;
-
-struct _grn_table_delete_optarg {
- int flags;
- int (*func)(grn_ctx *ctx, grn_obj *, grn_id, void *);
- void *func_arg;
-};
-
-GRN_API grn_rc grn_hash_delete_by_id(grn_ctx *ctx, grn_hash *hash, grn_id id,
- grn_table_delete_optarg *optarg);
-GRN_API grn_rc grn_hash_delete(grn_ctx *ctx, grn_hash *hash,
- const void *key, unsigned int key_size,
- grn_table_delete_optarg *optarg);
-
-GRN_API grn_hash_cursor *grn_hash_cursor_open(grn_ctx *ctx, grn_hash *hash,
- const void *min, unsigned int min_size,
- const void *max, unsigned int max_size,
- int offset, int limit, int flags);
-GRN_API grn_id grn_hash_cursor_next(grn_ctx *ctx, grn_hash_cursor *c);
-GRN_API void grn_hash_cursor_close(grn_ctx *ctx, grn_hash_cursor *c);
-
-GRN_API int grn_hash_cursor_get_key(grn_ctx *ctx, grn_hash_cursor *c, void **key);
-GRN_API int grn_hash_cursor_get_value(grn_ctx *ctx, grn_hash_cursor *c, void **value);
-GRN_API grn_rc grn_hash_cursor_set_value(grn_ctx *ctx, grn_hash_cursor *c,
- const void *value, int flags);
-
-GRN_API int grn_hash_cursor_get_key_value(grn_ctx *ctx, grn_hash_cursor *c,
- void **key, unsigned int *key_size, void **value);
-
-GRN_API grn_rc grn_hash_cursor_delete(grn_ctx *ctx, grn_hash_cursor *c,
- grn_table_delete_optarg *optarg);
-
-#define GRN_HASH_EACH(ctx,hash,id,key,key_size,value,block) do {\
- grn_hash_cursor *_sc = grn_hash_cursor_open(ctx, hash, NULL, 0, NULL, 0, 0, -1, 0); \
- if (_sc) {\
- grn_id id;\
- while ((id = grn_hash_cursor_next(ctx, _sc))) {\
- grn_hash_cursor_get_key_value(ctx, _sc, (void **)(key),\
- (key_size), (void **)(value));\
- block\
- }\
- grn_hash_cursor_close(ctx, _sc);\
- }\
-} while (0)
-
-/* array */
-
-typedef struct _grn_array grn_array;
-typedef struct _grn_array_cursor grn_array_cursor;
-
-GRN_API grn_array *grn_array_create(grn_ctx *ctx, const char *path,
- unsigned int value_size, unsigned int flags);
-GRN_API grn_array *grn_array_open(grn_ctx *ctx, const char *path);
-GRN_API grn_rc grn_array_close(grn_ctx *ctx, grn_array *array);
-GRN_API grn_id grn_array_add(grn_ctx *ctx, grn_array *array, void **value);
-GRN_API grn_id grn_array_push(grn_ctx *ctx, grn_array *array,
- void (*func)(grn_ctx *ctx, grn_array *array,
- grn_id id, void *func_arg),
- void *func_arg);
-GRN_API grn_id grn_array_pull(grn_ctx *ctx, grn_array *array, grn_bool blockp,
- void (*func)(grn_ctx *ctx, grn_array *array,
- grn_id id, void *func_arg),
- void *func_arg);
-GRN_API void grn_array_unblock(grn_ctx *ctx, grn_array *array);
-GRN_API int grn_array_get_value(grn_ctx *ctx, grn_array *array, grn_id id, void *valuebuf);
-GRN_API grn_rc grn_array_set_value(grn_ctx *ctx, grn_array *array, grn_id id,
- const void *value, int flags);
-GRN_API grn_array_cursor *grn_array_cursor_open(grn_ctx *ctx, grn_array *array,
- grn_id min, grn_id max,
- int offset, int limit, int flags);
-GRN_API grn_id grn_array_cursor_next(grn_ctx *ctx, grn_array_cursor *cursor);
-GRN_API int grn_array_cursor_get_value(grn_ctx *ctx, grn_array_cursor *cursor, void **value);
-GRN_API grn_rc grn_array_cursor_set_value(grn_ctx *ctx, grn_array_cursor *cursor,
- const void *value, int flags);
-GRN_API grn_rc grn_array_cursor_delete(grn_ctx *ctx, grn_array_cursor *cursor,
- grn_table_delete_optarg *optarg);
-GRN_API void grn_array_cursor_close(grn_ctx *ctx, grn_array_cursor *cursor);
-GRN_API grn_rc grn_array_delete_by_id(grn_ctx *ctx, grn_array *array, grn_id id,
- grn_table_delete_optarg *optarg);
-
-GRN_API grn_id grn_array_next(grn_ctx *ctx, grn_array *array, grn_id id);
-
-GRN_API void *_grn_array_get_value(grn_ctx *ctx, grn_array *array, grn_id id);
-
-#define GRN_ARRAY_EACH(ctx,array,head,tail,id,value,block) do {\
- grn_array_cursor *_sc = grn_array_cursor_open(ctx, array, head, tail, 0, -1, 0); \
- if (_sc) {\
- grn_id id;\
- while ((id = grn_array_cursor_next(ctx, _sc))) {\
- grn_array_cursor_get_value(ctx, _sc, (void **)(value));\
- block\
- }\
- grn_array_cursor_close(ctx, _sc); \
- }\
-} while (0)
-
-/* pat */
-
-typedef struct _grn_pat grn_pat;
-typedef struct _grn_pat_cursor grn_pat_cursor;
-
-GRN_API grn_pat *grn_pat_create(grn_ctx *ctx, const char *path, unsigned int key_size,
- unsigned int value_size, unsigned int flags);
-
-GRN_API grn_pat *grn_pat_open(grn_ctx *ctx, const char *path);
-
-GRN_API grn_rc grn_pat_close(grn_ctx *ctx, grn_pat *pat);
-
-GRN_API grn_rc grn_pat_remove(grn_ctx *ctx, const char *path);
-
-GRN_API grn_id grn_pat_get(grn_ctx *ctx, grn_pat *pat, const void *key,
- unsigned int key_size, void **value);
-GRN_API grn_id grn_pat_add(grn_ctx *ctx, grn_pat *pat, const void *key,
- unsigned int key_size, void **value, int *added);
-
-GRN_API int grn_pat_get_key(grn_ctx *ctx, grn_pat *pat, grn_id id, void *keybuf, int bufsize);
-GRN_API int grn_pat_get_key2(grn_ctx *ctx, grn_pat *pat, grn_id id, grn_obj *bulk);
-GRN_API int grn_pat_get_value(grn_ctx *ctx, grn_pat *pat, grn_id id, void *valuebuf);
-GRN_API grn_rc grn_pat_set_value(grn_ctx *ctx, grn_pat *pat, grn_id id,
- const void *value, int flags);
-
-GRN_API grn_rc grn_pat_delete_by_id(grn_ctx *ctx, grn_pat *pat, grn_id id,
- grn_table_delete_optarg *optarg);
-GRN_API grn_rc grn_pat_delete(grn_ctx *ctx, grn_pat *pat, const void *key, unsigned int key_size,
- grn_table_delete_optarg *optarg);
-GRN_API int grn_pat_delete_with_sis(grn_ctx *ctx, grn_pat *pat, grn_id id,
- grn_table_delete_optarg *optarg);
-
-typedef struct _grn_pat_scan_hit grn_pat_scan_hit;
-
-struct _grn_pat_scan_hit {
- grn_id id;
- unsigned int offset;
- unsigned int length;
-};
-
-GRN_API int grn_pat_scan(grn_ctx *ctx, grn_pat *pat, const char *str, unsigned int str_len,
- grn_pat_scan_hit *sh, unsigned int sh_size, const char **rest);
-
-GRN_API grn_rc grn_pat_prefix_search(grn_ctx *ctx, grn_pat *pat,
- const void *key, unsigned int key_size, grn_hash *h);
-GRN_API grn_rc grn_pat_suffix_search(grn_ctx *ctx, grn_pat *pat,
- const void *key, unsigned int key_size, grn_hash *h);
-GRN_API grn_id grn_pat_lcp_search(grn_ctx *ctx, grn_pat *pat,
- const void *key, unsigned int key_size);
-
-GRN_API unsigned int grn_pat_size(grn_ctx *ctx, grn_pat *pat);
-
-GRN_API grn_pat_cursor *grn_pat_cursor_open(grn_ctx *ctx, grn_pat *pat,
- const void *min, unsigned int min_size,
- const void *max, unsigned int max_size,
- int offset, int limit, int flags);
-GRN_API grn_id grn_pat_cursor_next(grn_ctx *ctx, grn_pat_cursor *c);
-GRN_API void grn_pat_cursor_close(grn_ctx *ctx, grn_pat_cursor *c);
-
-GRN_API int grn_pat_cursor_get_key(grn_ctx *ctx, grn_pat_cursor *c, void **key);
-GRN_API int grn_pat_cursor_get_value(grn_ctx *ctx, grn_pat_cursor *c, void **value);
-
-GRN_API int grn_pat_cursor_get_key_value(grn_ctx *ctx, grn_pat_cursor *c,
- void **key, unsigned int *key_size, void **value);
-GRN_API grn_rc grn_pat_cursor_set_value(grn_ctx *ctx, grn_pat_cursor *c,
- const void *value, int flags);
-GRN_API grn_rc grn_pat_cursor_delete(grn_ctx *ctx, grn_pat_cursor *c,
- grn_table_delete_optarg *optarg);
-
-#define GRN_PAT_EACH(ctx,pat,id,key,key_size,value,block) do { \
- grn_pat_cursor *_sc = grn_pat_cursor_open(ctx, pat, NULL, 0, NULL, 0, 0, -1, 0); \
- if (_sc) {\
- grn_id id;\
- while ((id = grn_pat_cursor_next(ctx, _sc))) {\
- grn_pat_cursor_get_key_value(ctx, _sc, (void **)(key),\
- (key_size), (void **)(value));\
- block\
- }\
- grn_pat_cursor_close(ctx, _sc);\
- }\
-} while (0)
-
-/* dat */
-
-typedef struct _grn_dat grn_dat;
-typedef struct _grn_dat_cursor grn_dat_cursor;
-
-GRN_API grn_dat *grn_dat_create(grn_ctx *ctx, const char *path, unsigned int key_size,
- unsigned int value_size, unsigned int flags);
-
-GRN_API grn_dat *grn_dat_open(grn_ctx *ctx, const char *path);
-
-GRN_API grn_rc grn_dat_close(grn_ctx *ctx, grn_dat *dat);
-
-GRN_API grn_rc grn_dat_remove(grn_ctx *ctx, const char *path);
-
-GRN_API grn_id grn_dat_get(grn_ctx *ctx, grn_dat *dat, const void *key,
- unsigned int key_size, void **value);
-GRN_API grn_id grn_dat_add(grn_ctx *ctx, grn_dat *dat, const void *key,
- unsigned int key_size, void **value, int *added);
-
-GRN_API int grn_dat_get_key(grn_ctx *ctx, grn_dat *dat, grn_id id, void *keybuf, int bufsize);
-GRN_API int grn_dat_get_key2(grn_ctx *ctx, grn_dat *dat, grn_id id, grn_obj *bulk);
-
-GRN_API grn_rc grn_dat_delete_by_id(grn_ctx *ctx, grn_dat *dat, grn_id id,
- grn_table_delete_optarg *optarg);
-GRN_API grn_rc grn_dat_delete(grn_ctx *ctx, grn_dat *dat, const void *key, unsigned int key_size,
- grn_table_delete_optarg *optarg);
-
-GRN_API grn_rc grn_dat_update_by_id(grn_ctx *ctx, grn_dat *dat, grn_id src_key_id,
- const void *dest_key, unsigned int dest_key_size);
-GRN_API grn_rc grn_dat_update(grn_ctx *ctx, grn_dat *dat,
- const void *src_key, unsigned int src_key_size,
- const void *dest_key, unsigned int dest_key_size);
-
-GRN_API unsigned int grn_dat_size(grn_ctx *ctx, grn_dat *dat);
-
-GRN_API grn_dat_cursor *grn_dat_cursor_open(grn_ctx *ctx, grn_dat *dat,
- const void *min, unsigned int min_size,
- const void *max, unsigned int max_size,
- int offset, int limit, int flags);
-GRN_API grn_id grn_dat_cursor_next(grn_ctx *ctx, grn_dat_cursor *c);
-GRN_API void grn_dat_cursor_close(grn_ctx *ctx, grn_dat_cursor *c);
-
-GRN_API int grn_dat_cursor_get_key(grn_ctx *ctx, grn_dat_cursor *c, const void **key);
-GRN_API grn_rc grn_dat_cursor_delete(grn_ctx *ctx, grn_dat_cursor *c,
- grn_table_delete_optarg *optarg);
-
-#define GRN_DAT_EACH(ctx,dat,id,key,key_size,block) do {\
- grn_dat_cursor *_sc = grn_dat_cursor_open(ctx, dat, NULL, 0, NULL, 0, 0, -1, 0);\
- if (_sc) {\
- grn_id id;\
- unsigned int *_ks = (key_size);\
- if (_ks) {\
- while ((id = grn_dat_cursor_next(ctx, _sc))) {\
- int _ks_raw = grn_dat_cursor_get_key(ctx, _sc, (const void **)(key));\
- *(_ks) = (unsigned int)_ks_raw;\
- block\
- }\
- } else {\
- while ((id = grn_dat_cursor_next(ctx, _sc))) {\
- grn_dat_cursor_get_key(ctx, _sc, (const void **)(key));\
- block\
- }\
- }\
- grn_dat_cursor_close(ctx, _sc);\
- }\
-} while (0)
-
-/* buffered index builder */
-
-typedef struct _grn_ii grn_ii;
-typedef struct _grn_ii_buffer grn_ii_buffer;
-
-grn_ii_buffer *grn_ii_buffer_open(grn_ctx *ctx, grn_ii *ii,
- long long unsigned int update_buffer_size);
-grn_rc grn_ii_buffer_append(grn_ctx *ctx, grn_ii_buffer *ii_buffer,
- grn_id rid, unsigned int section, grn_obj *value);
-grn_rc grn_ii_buffer_commit(grn_ctx *ctx, grn_ii_buffer *ii_buffer);
-grn_rc grn_ii_buffer_close(grn_ctx *ctx, grn_ii_buffer *ii_buffer);
-
-
-#ifdef __cplusplus
-}
-#endif
+#include "groonga/groonga.h"
+#include "groonga/obj.h"
+#include "groonga/ii.h"
+#include "groonga/expr.h"
+#include "groonga/output.h"
+#include "groonga/util.h"
+#include "groonga/request_canceler.h"
#endif /* GROONGA_H */
diff --git a/storage/mroonga/vendor/groonga/include/groonga/Makefile.am b/storage/mroonga/vendor/groonga/include/groonga/Makefile.am
index 5cfb61937fb..63dcc1e7ba9 100644
--- a/storage/mroonga/vendor/groonga/include/groonga/Makefile.am
+++ b/storage/mroonga/vendor/groonga/include/groonga/Makefile.am
@@ -1,7 +1,16 @@
groonga_includedir = $(pkgincludedir)/groonga
groonga_include_HEADERS = \
+ command.h \
+ expr.h \
+ groonga.h \
+ ii.h \
+ obj.h \
+ output.h \
plugin.h \
+ request_canceler.h \
+ token.h \
tokenizer.h \
token_filter.h \
nfkc.h \
- normalizer.h
+ normalizer.h \
+ util.h
diff --git a/storage/mroonga/vendor/groonga/include/groonga/command.h b/storage/mroonga/vendor/groonga/include/groonga/command.h
new file mode 100644
index 00000000000..101956a04f9
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/include/groonga/command.h
@@ -0,0 +1,79 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2015 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#ifndef GROONGA_COMMAND_H
+#define GROONGA_COMMAND_H
+
+#include <groonga/plugin.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _grn_command_input grn_command_input;
+
+GRN_PLUGIN_EXPORT grn_command_input *grn_command_input_open(grn_ctx *ctx,
+ grn_obj *command);
+GRN_PLUGIN_EXPORT grn_rc grn_command_input_close(grn_ctx *ctx,
+ grn_command_input *input);
+
+GRN_PLUGIN_EXPORT grn_obj *grn_command_input_add(grn_ctx *ctx,
+ grn_command_input *input,
+ const char *name,
+ int name_size,
+ grn_bool *added);
+GRN_PLUGIN_EXPORT grn_obj *grn_command_input_get(grn_ctx *ctx,
+ grn_command_input *input,
+ const char *name,
+ int name_size);
+GRN_PLUGIN_EXPORT grn_obj *grn_command_input_at(grn_ctx *ctx,
+ grn_command_input *input,
+ unsigned int offset);
+
+typedef void grn_command_run_func(grn_ctx *ctx,
+ grn_obj *command,
+ grn_command_input *input,
+ void *user_data);
+
+/*
+ grn_command_register() registers a command to the database which is
+ associated with `ctx'. `command_name' and `command_name_size'
+ specify the command name. Alphabetic letters ('A'-'Z' and 'a'-'z'),
+ digits ('0'-'9') and an underscore ('_') are capable characters.
+
+ `run' is called for running the command.
+
+ grn_command_register() returns GRN_SUCCESS on success, an error
+ code on failure.
+ */
+GRN_PLUGIN_EXPORT grn_rc grn_command_register(grn_ctx *ctx,
+ const char *command_name,
+ int command_name_size,
+ grn_command_run_func *run,
+ grn_expr_var *vars,
+ unsigned int n_vars,
+ void *user_data);
+
+GRN_PLUGIN_EXPORT grn_rc grn_command_run(grn_ctx *ctx,
+ grn_obj *command,
+ grn_command_input *input);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* GROONGA_COMMAND_H */
diff --git a/storage/mroonga/vendor/groonga/include/groonga/expr.h b/storage/mroonga/vendor/groonga/include/groonga/expr.h
new file mode 100644
index 00000000000..cf8fb3519ca
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/include/groonga/expr.h
@@ -0,0 +1,108 @@
+/*
+ Copyright(C) 2009-2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#ifndef GROONGA_EXPR_H
+#define GROONGA_EXPR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+GRN_API grn_obj *grn_expr_create(grn_ctx *ctx, const char *name, unsigned int name_size);
+GRN_API grn_rc grn_expr_close(grn_ctx *ctx, grn_obj *expr);
+GRN_API grn_obj *grn_expr_add_var(grn_ctx *ctx, grn_obj *expr,
+ const char *name, unsigned int name_size);
+GRN_API grn_obj *grn_expr_get_var(grn_ctx *ctx, grn_obj *expr,
+ const char *name, unsigned int name_size);
+GRN_API grn_obj *grn_expr_get_var_by_offset(grn_ctx *ctx, grn_obj *expr, unsigned int offset);
+GRN_API grn_rc grn_expr_clear_vars(grn_ctx *ctx, grn_obj *expr);
+
+
+GRN_API grn_obj *grn_expr_append_obj(grn_ctx *ctx, grn_obj *expr, grn_obj *obj,
+ grn_operator op, int nargs);
+GRN_API grn_obj *grn_expr_append_const(grn_ctx *ctx, grn_obj *expr, grn_obj *obj,
+ grn_operator op, int nargs);
+GRN_API grn_obj *grn_expr_append_const_str(grn_ctx *ctx, grn_obj *expr,
+ const char *str, unsigned int str_size,
+ grn_operator op, int nargs);
+GRN_API grn_obj *grn_expr_append_const_int(grn_ctx *ctx, grn_obj *expr, int i,
+ grn_operator op, int nargs);
+GRN_API grn_rc grn_expr_append_op(grn_ctx *ctx, grn_obj *expr, grn_operator op, int nargs);
+
+GRN_API grn_rc grn_expr_get_keywords(grn_ctx *ctx, grn_obj *expr, grn_obj *keywords);
+
+GRN_API grn_rc grn_expr_syntax_escape(grn_ctx *ctx,
+ const char *query, int query_size,
+ const char *target_characters,
+ char escape_character,
+ grn_obj *escaped_query);
+GRN_API grn_rc grn_expr_syntax_escape_query(grn_ctx *ctx,
+ const char *query, int query_size,
+ grn_obj *escaped_query);
+
+GRN_API grn_rc grn_expr_compile(grn_ctx *ctx, grn_obj *expr);
+GRN_API grn_rc grn_expr_dump_plan(grn_ctx *ctx, grn_obj *expr, grn_obj *buffer);
+GRN_API grn_obj *grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs);
+
+GRN_API grn_obj *grn_expr_alloc(grn_ctx *ctx, grn_obj *expr,
+ grn_id domain, grn_obj_flags flags);
+
+#define GRN_EXPR_CREATE_FOR_QUERY(ctx,table,expr,var) do {\
+ if (((expr) = grn_expr_create((ctx), NULL, 0)) &&\
+ ((var) = grn_expr_add_var((ctx), (expr), NULL, 0))) {\
+ GRN_RECORD_INIT((var), 0, grn_obj_id((ctx), (table)));\
+ } else {\
+ (var) = NULL;\
+ }\
+} while (0)
+
+typedef unsigned int grn_expr_flags;
+
+#define GRN_EXPR_SYNTAX_QUERY (0x00)
+#define GRN_EXPR_SYNTAX_SCRIPT (0x01)
+#define GRN_EXPR_SYNTAX_OUTPUT_COLUMNS (0x20)
+#define GRN_EXPR_SYNTAX_ADJUSTER (0x40)
+#define GRN_EXPR_ALLOW_PRAGMA (0x02)
+#define GRN_EXPR_ALLOW_COLUMN (0x04)
+#define GRN_EXPR_ALLOW_UPDATE (0x08)
+#define GRN_EXPR_ALLOW_LEADING_NOT (0x10)
+
+GRN_API grn_rc grn_expr_parse(grn_ctx *ctx, grn_obj *expr,
+ const char *str, unsigned int str_size,
+ grn_obj *default_column, grn_operator default_mode,
+ grn_operator default_op, grn_expr_flags flags);
+
+GRN_API grn_obj *grn_expr_snip(grn_ctx *ctx, grn_obj *expr, int flags,
+ unsigned int width, unsigned int max_results,
+ unsigned int n_tags,
+ const char **opentags, unsigned int *opentag_lens,
+ const char **closetags, unsigned int *closetag_lens,
+ grn_snip_mapping *mapping);
+GRN_API grn_rc grn_expr_snip_add_conditions(grn_ctx *ctx,
+ grn_obj *expr,
+ grn_obj *snip,
+ unsigned int n_tags,
+ const char **opentags,
+ unsigned int *opentag_lens,
+ const char **closetags,
+ unsigned int *closetag_lens);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GROONGA_EXPR_H */
diff --git a/storage/mroonga/vendor/groonga/include/groonga/groonga.h b/storage/mroonga/vendor/groonga/include/groonga/groonga.h
new file mode 100644
index 00000000000..16bc424b8c1
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/include/groonga/groonga.h
@@ -0,0 +1,1994 @@
+/*
+ Copyright(C) 2009-2015 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#ifndef GROONGA_GROONGA_H
+#define GROONGA_GROONGA_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdarg.h>
+
+#ifndef GRN_API
+# if defined(_WIN32) || defined(_WIN64)
+# define GRN_API __declspec(dllimport)
+# else
+# define GRN_API
+# endif /* defined(_WIN32) || defined(_WIN64) */
+#endif /* GRN_API */
+
+typedef unsigned int grn_id;
+typedef unsigned char grn_bool;
+
+#define GRN_ID_NIL (0x00)
+#define GRN_ID_MAX (0x3fffffff)
+
+#define GRN_TRUE (1)
+#define GRN_FALSE (0)
+
+typedef enum {
+ GRN_SUCCESS = 0,
+ GRN_END_OF_DATA = 1,
+ GRN_UNKNOWN_ERROR = -1,
+ GRN_OPERATION_NOT_PERMITTED = -2,
+ GRN_NO_SUCH_FILE_OR_DIRECTORY = -3,
+ GRN_NO_SUCH_PROCESS = -4,
+ GRN_INTERRUPTED_FUNCTION_CALL = -5,
+ GRN_INPUT_OUTPUT_ERROR = -6,
+ GRN_NO_SUCH_DEVICE_OR_ADDRESS = -7,
+ GRN_ARG_LIST_TOO_LONG = -8,
+ GRN_EXEC_FORMAT_ERROR = -9,
+ GRN_BAD_FILE_DESCRIPTOR = -10,
+ GRN_NO_CHILD_PROCESSES = -11,
+ GRN_RESOURCE_TEMPORARILY_UNAVAILABLE = -12,
+ GRN_NOT_ENOUGH_SPACE = -13,
+ GRN_PERMISSION_DENIED = -14,
+ GRN_BAD_ADDRESS = -15,
+ GRN_RESOURCE_BUSY = -16,
+ GRN_FILE_EXISTS = -17,
+ GRN_IMPROPER_LINK = -18,
+ GRN_NO_SUCH_DEVICE = -19,
+ GRN_NOT_A_DIRECTORY = -20,
+ GRN_IS_A_DIRECTORY = -21,
+ GRN_INVALID_ARGUMENT = -22,
+ GRN_TOO_MANY_OPEN_FILES_IN_SYSTEM = -23,
+ GRN_TOO_MANY_OPEN_FILES = -24,
+ GRN_INAPPROPRIATE_I_O_CONTROL_OPERATION = -25,
+ GRN_FILE_TOO_LARGE = -26,
+ GRN_NO_SPACE_LEFT_ON_DEVICE = -27,
+ GRN_INVALID_SEEK = -28,
+ GRN_READ_ONLY_FILE_SYSTEM = -29,
+ GRN_TOO_MANY_LINKS = -30,
+ GRN_BROKEN_PIPE = -31,
+ GRN_DOMAIN_ERROR = -32,
+ GRN_RESULT_TOO_LARGE = -33,
+ GRN_RESOURCE_DEADLOCK_AVOIDED = -34,
+ GRN_NO_MEMORY_AVAILABLE = -35,
+ GRN_FILENAME_TOO_LONG = -36,
+ GRN_NO_LOCKS_AVAILABLE = -37,
+ GRN_FUNCTION_NOT_IMPLEMENTED = -38,
+ GRN_DIRECTORY_NOT_EMPTY = -39,
+ GRN_ILLEGAL_BYTE_SEQUENCE = -40,
+ GRN_SOCKET_NOT_INITIALIZED = -41,
+ GRN_OPERATION_WOULD_BLOCK = -42,
+ GRN_ADDRESS_IS_NOT_AVAILABLE = -43,
+ GRN_NETWORK_IS_DOWN = -44,
+ GRN_NO_BUFFER = -45,
+ GRN_SOCKET_IS_ALREADY_CONNECTED = -46,
+ GRN_SOCKET_IS_NOT_CONNECTED = -47,
+ GRN_SOCKET_IS_ALREADY_SHUTDOWNED = -48,
+ GRN_OPERATION_TIMEOUT = -49,
+ GRN_CONNECTION_REFUSED = -50,
+ GRN_RANGE_ERROR = -51,
+ GRN_TOKENIZER_ERROR = -52,
+ GRN_FILE_CORRUPT = -53,
+ GRN_INVALID_FORMAT = -54,
+ GRN_OBJECT_CORRUPT = -55,
+ GRN_TOO_MANY_SYMBOLIC_LINKS = -56,
+ GRN_NOT_SOCKET = -57,
+ GRN_OPERATION_NOT_SUPPORTED = -58,
+ GRN_ADDRESS_IS_IN_USE = -59,
+ GRN_ZLIB_ERROR = -60,
+ GRN_LZ4_ERROR = -61,
+/* Just for backward compatibility. We'll remove it at 5.0.0. */
+#define GRN_LZO_ERROR GRN_LZ4_ERROR
+ GRN_STACK_OVER_FLOW = -62,
+ GRN_SYNTAX_ERROR = -63,
+ GRN_RETRY_MAX = -64,
+ GRN_INCOMPATIBLE_FILE_FORMAT = -65,
+ GRN_UPDATE_NOT_ALLOWED = -66,
+ GRN_TOO_SMALL_OFFSET = -67,
+ GRN_TOO_LARGE_OFFSET = -68,
+ GRN_TOO_SMALL_LIMIT = -69,
+ GRN_CAS_ERROR = -70,
+ GRN_UNSUPPORTED_COMMAND_VERSION = -71,
+ GRN_NORMALIZER_ERROR = -72,
+ GRN_TOKEN_FILTER_ERROR = -73,
+ GRN_COMMAND_ERROR = -74,
+ GRN_PLUGIN_ERROR = -75,
+ GRN_SCORER_ERROR = -76
+} grn_rc;
+
+GRN_API grn_rc grn_init(void);
+GRN_API grn_rc grn_fin(void);
+
+typedef enum {
+ GRN_ENC_DEFAULT = 0,
+ GRN_ENC_NONE,
+ GRN_ENC_EUC_JP,
+ GRN_ENC_UTF8,
+ GRN_ENC_SJIS,
+ GRN_ENC_LATIN1,
+ GRN_ENC_KOI8R
+} grn_encoding;
+
+typedef enum {
+ GRN_COMMAND_VERSION_DEFAULT = 0,
+ GRN_COMMAND_VERSION_1,
+ GRN_COMMAND_VERSION_2
+} grn_command_version;
+
+#define GRN_COMMAND_VERSION_MIN GRN_COMMAND_VERSION_1
+#define GRN_COMMAND_VERSION_STABLE GRN_COMMAND_VERSION_1
+#define GRN_COMMAND_VERSION_MAX GRN_COMMAND_VERSION_2
+
+typedef enum {
+ GRN_LOG_NONE = 0,
+ GRN_LOG_EMERG,
+ GRN_LOG_ALERT,
+ GRN_LOG_CRIT,
+ GRN_LOG_ERROR,
+ GRN_LOG_WARNING,
+ GRN_LOG_NOTICE,
+ GRN_LOG_INFO,
+ GRN_LOG_DEBUG,
+ GRN_LOG_DUMP
+} grn_log_level;
+
+/* query log flags */
+#define GRN_QUERY_LOG_NONE (0x00)
+#define GRN_QUERY_LOG_COMMAND (0x01<<0)
+#define GRN_QUERY_LOG_RESULT_CODE (0x01<<1)
+#define GRN_QUERY_LOG_DESTINATION (0x01<<2)
+#define GRN_QUERY_LOG_CACHE (0x01<<3)
+#define GRN_QUERY_LOG_SIZE (0x01<<4)
+#define GRN_QUERY_LOG_SCORE (0x01<<5)
+#define GRN_QUERY_LOG_ALL\
+ (GRN_QUERY_LOG_COMMAND |\
+ GRN_QUERY_LOG_RESULT_CODE |\
+ GRN_QUERY_LOG_DESTINATION |\
+ GRN_QUERY_LOG_CACHE |\
+ GRN_QUERY_LOG_SIZE |\
+ GRN_QUERY_LOG_SCORE)
+#define GRN_QUERY_LOG_DEFAULT GRN_QUERY_LOG_ALL
+
+typedef enum {
+ GRN_CONTENT_NONE = 0,
+ GRN_CONTENT_TSV,
+ GRN_CONTENT_JSON,
+ GRN_CONTENT_XML,
+ GRN_CONTENT_MSGPACK
+} grn_content_type;
+
+typedef struct _grn_obj grn_obj;
+typedef struct _grn_ctx grn_ctx;
+
+#define GRN_CTX_MSGSIZE (0x80)
+#define GRN_CTX_FIN (0xff)
+
+typedef union {
+ int int_value;
+ grn_id id;
+ void *ptr;
+} grn_user_data;
+
+typedef grn_obj *grn_proc_func(grn_ctx *ctx, int nargs, grn_obj **args,
+ grn_user_data *user_data);
+
+struct _grn_ctx {
+ grn_rc rc;
+ int flags;
+ grn_encoding encoding;
+ unsigned char ntrace;
+ unsigned char errlvl;
+ unsigned char stat;
+ unsigned int seqno;
+ unsigned int subno;
+ unsigned int seqno2;
+ unsigned int errline;
+ grn_user_data user_data;
+ grn_ctx *prev;
+ grn_ctx *next;
+ const char *errfile;
+ const char *errfunc;
+ struct _grn_ctx_impl *impl;
+ void *trace[16];
+ char errbuf[GRN_CTX_MSGSIZE];
+};
+
+#define GRN_CTX_USER_DATA(ctx) (&((ctx)->user_data))
+
+/* Deprecated since 4.0.3. Don't use it. */
+#define GRN_CTX_USE_QL (0x03)
+/* Deprecated since 4.0.3. Don't use it. */
+#define GRN_CTX_BATCH_MODE (0x04)
+#define GRN_CTX_PER_DB (0x08)
+
+GRN_API grn_rc grn_ctx_init(grn_ctx *ctx, int flags);
+GRN_API grn_rc grn_ctx_fin(grn_ctx *ctx);
+GRN_API grn_ctx *grn_ctx_open(int flags);
+GRN_API grn_rc grn_ctx_close(grn_ctx *ctx);
+GRN_API grn_rc grn_ctx_set_finalizer(grn_ctx *ctx, grn_proc_func *func);
+
+GRN_API grn_encoding grn_get_default_encoding(void);
+GRN_API grn_rc grn_set_default_encoding(grn_encoding encoding);
+
+#define GRN_CTX_GET_ENCODING(ctx) ((ctx)->encoding)
+#define GRN_CTX_SET_ENCODING(ctx,enc) \
+ ((ctx)->encoding = (enc == GRN_ENC_DEFAULT) ? grn_get_default_encoding() : enc)
+
+GRN_API const char *grn_get_version(void);
+GRN_API const char *grn_get_package(void);
+
+GRN_API grn_command_version grn_get_default_command_version(void);
+GRN_API grn_rc grn_set_default_command_version(grn_command_version version);
+GRN_API grn_command_version grn_ctx_get_command_version(grn_ctx *ctx);
+GRN_API grn_rc grn_ctx_set_command_version(grn_ctx *ctx, grn_command_version version);
+GRN_API long long int grn_ctx_get_match_escalation_threshold(grn_ctx *ctx);
+GRN_API grn_rc grn_ctx_set_match_escalation_threshold(grn_ctx *ctx, long long int threshold);
+GRN_API long long int grn_get_default_match_escalation_threshold(void);
+GRN_API grn_rc grn_set_default_match_escalation_threshold(long long int threshold);
+
+GRN_API int grn_get_lock_timeout(void);
+GRN_API grn_rc grn_set_lock_timeout(int timeout);
+
+/* cache */
+#define GRN_CACHE_DEFAULT_MAX_N_ENTRIES 100
+typedef struct _grn_cache grn_cache;
+
+GRN_API grn_cache *grn_cache_open(grn_ctx *ctx);
+GRN_API grn_rc grn_cache_close(grn_ctx *ctx, grn_cache *cache);
+
+GRN_API grn_rc grn_cache_current_set(grn_ctx *ctx, grn_cache *cache);
+GRN_API grn_cache *grn_cache_current_get(grn_ctx *ctx);
+
+GRN_API grn_rc grn_cache_set_max_n_entries(grn_ctx *ctx,
+ grn_cache *cache,
+ unsigned int n);
+GRN_API unsigned int grn_cache_get_max_n_entries(grn_ctx *ctx,
+ grn_cache *cache);
+
+/* grn_encoding */
+
+GRN_API const char *grn_encoding_to_string(grn_encoding encoding);
+GRN_API grn_encoding grn_encoding_parse(const char *name);
+
+/* obj */
+
+typedef unsigned short int grn_obj_flags;
+
+#define GRN_OBJ_TABLE_TYPE_MASK (0x07)
+#define GRN_OBJ_TABLE_HASH_KEY (0x00)
+#define GRN_OBJ_TABLE_PAT_KEY (0x01)
+#define GRN_OBJ_TABLE_DAT_KEY (0x02)
+#define GRN_OBJ_TABLE_NO_KEY (0x03)
+
+#define GRN_OBJ_KEY_MASK (0x07<<3)
+#define GRN_OBJ_KEY_UINT (0x00<<3)
+#define GRN_OBJ_KEY_INT (0x01<<3)
+#define GRN_OBJ_KEY_FLOAT (0x02<<3)
+#define GRN_OBJ_KEY_GEO_POINT (0x03<<3)
+
+#define GRN_OBJ_KEY_WITH_SIS (0x01<<6)
+#define GRN_OBJ_KEY_NORMALIZE (0x01<<7)
+
+#define GRN_OBJ_COLUMN_TYPE_MASK (0x07)
+#define GRN_OBJ_COLUMN_SCALAR (0x00)
+#define GRN_OBJ_COLUMN_VECTOR (0x01)
+#define GRN_OBJ_COLUMN_INDEX (0x02)
+
+#define GRN_OBJ_COMPRESS_MASK (0x07<<4)
+#define GRN_OBJ_COMPRESS_NONE (0x00<<4)
+#define GRN_OBJ_COMPRESS_ZLIB (0x01<<4)
+#define GRN_OBJ_COMPRESS_LZ4 (0x02<<4)
+/* Just for backward compatibility. We'll remove it at 5.0.0. */
+#define GRN_OBJ_COMPRESS_LZO GRN_OBJ_COMPRESS_LZ4
+
+#define GRN_OBJ_WITH_SECTION (0x01<<7)
+#define GRN_OBJ_WITH_WEIGHT (0x01<<8)
+#define GRN_OBJ_WITH_POSITION (0x01<<9)
+#define GRN_OBJ_RING_BUFFER (0x01<<10)
+
+#define GRN_OBJ_UNIT_MASK (0x0f<<8)
+#define GRN_OBJ_UNIT_DOCUMENT_NONE (0x00<<8)
+#define GRN_OBJ_UNIT_DOCUMENT_SECTION (0x01<<8)
+#define GRN_OBJ_UNIT_DOCUMENT_POSITION (0x02<<8)
+#define GRN_OBJ_UNIT_SECTION_NONE (0x03<<8)
+#define GRN_OBJ_UNIT_SECTION_POSITION (0x04<<8)
+#define GRN_OBJ_UNIT_POSITION_NONE (0x05<<8)
+#define GRN_OBJ_UNIT_USERDEF_DOCUMENT (0x06<<8)
+#define GRN_OBJ_UNIT_USERDEF_SECTION (0x07<<8)
+#define GRN_OBJ_UNIT_USERDEF_POSITION (0x08<<8)
+
+#define GRN_OBJ_NO_SUBREC (0x00<<13)
+#define GRN_OBJ_WITH_SUBREC (0x01<<13)
+
+#define GRN_OBJ_KEY_VAR_SIZE (0x01<<14)
+
+#define GRN_OBJ_TEMPORARY (0x00<<15)
+#define GRN_OBJ_PERSISTENT (0x01<<15)
+
+/* obj types */
+
+#define GRN_VOID (0x00)
+#define GRN_BULK (0x02)
+#define GRN_PTR (0x03)
+#define GRN_UVECTOR (0x04) /* vector of fixed size data especially grn_id */
+#define GRN_PVECTOR (0x05) /* vector of grn_obj* */
+#define GRN_VECTOR (0x06) /* vector of arbitrary data */
+#define GRN_MSG (0x07)
+#define GRN_QUERY (0x08)
+#define GRN_ACCESSOR (0x09)
+#define GRN_SNIP (0x0b)
+#define GRN_PATSNIP (0x0c)
+#define GRN_STRING (0x0d)
+#define GRN_CURSOR_TABLE_HASH_KEY (0x10)
+#define GRN_CURSOR_TABLE_PAT_KEY (0x11)
+#define GRN_CURSOR_TABLE_DAT_KEY (0x12)
+#define GRN_CURSOR_TABLE_NO_KEY (0x13)
+#define GRN_CURSOR_COLUMN_INDEX (0x18)
+#define GRN_CURSOR_COLUMN_GEO_INDEX (0x1a)
+#define GRN_TYPE (0x20)
+#define GRN_PROC (0x21)
+#define GRN_EXPR (0x22)
+#define GRN_TABLE_HASH_KEY (0x30)
+#define GRN_TABLE_PAT_KEY (0x31)
+#define GRN_TABLE_DAT_KEY (0x32)
+#define GRN_TABLE_NO_KEY (0x33)
+#define GRN_DB (0x37)
+#define GRN_COLUMN_FIX_SIZE (0x40)
+#define GRN_COLUMN_VAR_SIZE (0x41)
+#define GRN_COLUMN_INDEX (0x48)
+
+typedef struct _grn_section grn_section;
+typedef struct _grn_obj_header grn_obj_header;
+
+struct _grn_section {
+ unsigned int offset;
+ unsigned int length;
+ unsigned int weight;
+ grn_id domain;
+};
+
+struct _grn_obj_header {
+ unsigned char type;
+ unsigned char impl_flags;
+ grn_obj_flags flags;
+ grn_id domain;
+};
+
+struct _grn_obj {
+ grn_obj_header header;
+ union {
+ struct {
+ char *head;
+ char *curr;
+ char *tail;
+ } b;
+ struct {
+ grn_obj *body;
+ grn_section *sections;
+ int n_sections;
+ } v;
+ } u;
+};
+
+#define GRN_OBJ_REFER (0x01<<0)
+#define GRN_OBJ_OUTPLACE (0x01<<1)
+
+#define GRN_OBJ_INIT(obj,obj_type,obj_flags,obj_domain) do { \
+ (obj)->header.type = (obj_type);\
+ (obj)->header.impl_flags = (obj_flags);\
+ (obj)->header.flags = 0;\
+ (obj)->header.domain = (obj_domain);\
+ (obj)->u.b.head = NULL;\
+ (obj)->u.b.curr = NULL;\
+ (obj)->u.b.tail = NULL;\
+} while (0)
+
+#define GRN_OBJ_FIN(ctx,obj) (grn_obj_close((ctx), (obj)))
+
+typedef struct _grn_db_create_optarg grn_db_create_optarg;
+
+struct _grn_db_create_optarg {
+ char **builtin_type_names;
+ int n_builtin_type_names;
+};
+
+GRN_API grn_obj *grn_db_create(grn_ctx *ctx, const char *path, grn_db_create_optarg *optarg);
+
+#define GRN_DB_OPEN_OR_CREATE(ctx,path,optarg,db) \
+ (((db) = grn_db_open((ctx), (path))) || (db = grn_db_create((ctx), (path), (optarg))))
+
+GRN_API grn_obj *grn_db_open(grn_ctx *ctx, const char *path);
+GRN_API void grn_db_touch(grn_ctx *ctx, grn_obj *db);
+GRN_API grn_rc grn_db_recover(grn_ctx *ctx, grn_obj *db);
+
+GRN_API grn_rc grn_ctx_use(grn_ctx *ctx, grn_obj *db);
+GRN_API grn_obj *grn_ctx_db(grn_ctx *ctx);
+GRN_API grn_obj *grn_ctx_get(grn_ctx *ctx, const char *name, int name_size);
+GRN_API grn_rc grn_ctx_get_all_tables(grn_ctx *ctx, grn_obj *tables_buffer);
+
+typedef enum {
+ GRN_DB_VOID = 0,
+ GRN_DB_DB,
+ GRN_DB_OBJECT,
+ GRN_DB_BOOL,
+ GRN_DB_INT8,
+ GRN_DB_UINT8,
+ GRN_DB_INT16,
+ GRN_DB_UINT16,
+ GRN_DB_INT32,
+ GRN_DB_UINT32,
+ GRN_DB_INT64,
+ GRN_DB_UINT64,
+ GRN_DB_FLOAT,
+ GRN_DB_TIME,
+ GRN_DB_SHORT_TEXT,
+ GRN_DB_TEXT,
+ GRN_DB_LONG_TEXT,
+ GRN_DB_TOKYO_GEO_POINT,
+ GRN_DB_WGS84_GEO_POINT
+} grn_builtin_type;
+
+typedef enum {
+ GRN_DB_MECAB = 64,
+ GRN_DB_DELIMIT,
+ GRN_DB_UNIGRAM,
+ GRN_DB_BIGRAM,
+ GRN_DB_TRIGRAM
+} grn_builtin_tokenizer;
+
+GRN_API grn_obj *grn_ctx_at(grn_ctx *ctx, grn_id id);
+
+GRN_API grn_obj *grn_type_create(grn_ctx *ctx, const char *name, unsigned int name_size,
+ grn_obj_flags flags, unsigned int size);
+
+GRN_API grn_rc grn_plugin_register(grn_ctx *ctx, const char *name);
+GRN_API grn_rc grn_plugin_register_by_path(grn_ctx *ctx, const char *path);
+GRN_API const char *grn_plugin_get_system_plugins_dir(void);
+GRN_API const char *grn_plugin_get_suffix(void);
+
+typedef struct {
+ const char *name;
+ unsigned int name_size;
+ grn_obj value;
+} grn_expr_var;
+
+typedef grn_rc (*grn_plugin_func)(grn_ctx *ctx);
+
+typedef enum {
+ GRN_PROC_INVALID = 0,
+ GRN_PROC_TOKENIZER,
+ GRN_PROC_COMMAND,
+ GRN_PROC_FUNCTION,
+ GRN_PROC_HOOK,
+ GRN_PROC_NORMALIZER,
+ GRN_PROC_TOKEN_FILTER,
+ GRN_PROC_SCORER
+} grn_proc_type;
+
+GRN_API grn_obj *grn_proc_create(grn_ctx *ctx,
+ const char *name, int name_size, grn_proc_type type,
+ grn_proc_func *init, grn_proc_func *next, grn_proc_func *fin,
+ unsigned int nvars, grn_expr_var *vars);
+GRN_API grn_obj *grn_proc_get_info(grn_ctx *ctx, grn_user_data *user_data,
+ grn_expr_var **vars, unsigned int *nvars, grn_obj **caller);
+GRN_API grn_proc_type grn_proc_get_type(grn_ctx *ctx, grn_obj *proc);
+
+/*-------------------------------------------------------------
+ * API for table
+ */
+
+#define GRN_TABLE_MAX_KEY_SIZE (0x1000)
+
+GRN_API grn_obj *grn_table_create(grn_ctx *ctx,
+ const char *name, unsigned int name_size,
+ const char *path, grn_obj_flags flags,
+ grn_obj *key_type, grn_obj *value_type);
+
+#define GRN_TABLE_OPEN_OR_CREATE(ctx,name,name_size,path,flags,key_type,value_type,table) \
+ (((table) = grn_ctx_get((ctx), (name), (name_size))) ||\
+ ((table) = grn_table_create((ctx), (name), (name_size), (path), (flags), (key_type), (value_type))))
+
+/* TODO: int *added -> grn_bool *added */
+GRN_API grn_id grn_table_add(grn_ctx *ctx, grn_obj *table,
+ const void *key, unsigned int key_size, int *added);
+GRN_API grn_id grn_table_get(grn_ctx *ctx, grn_obj *table,
+ const void *key, unsigned int key_size);
+GRN_API grn_id grn_table_at(grn_ctx *ctx, grn_obj *table, grn_id id);
+GRN_API grn_id grn_table_lcp_search(grn_ctx *ctx, grn_obj *table,
+ const void *key, unsigned int key_size);
+GRN_API int grn_table_get_key(grn_ctx *ctx, grn_obj *table,
+ grn_id id, void *keybuf, int buf_size);
+GRN_API grn_rc grn_table_delete(grn_ctx *ctx, grn_obj *table,
+ const void *key, unsigned int key_size);
+GRN_API grn_rc grn_table_delete_by_id(grn_ctx *ctx, grn_obj *table, grn_id id);
+GRN_API grn_rc grn_table_update_by_id(grn_ctx *ctx, grn_obj *table, grn_id id,
+ const void *dest_key, unsigned int dest_key_size);
+GRN_API grn_rc grn_table_update(grn_ctx *ctx, grn_obj *table,
+ const void *src_key, unsigned int src_key_size,
+ const void *dest_key, unsigned int dest_key_size);
+GRN_API grn_rc grn_table_truncate(grn_ctx *ctx, grn_obj *table);
+
+typedef grn_obj grn_table_cursor;
+
+#define GRN_CURSOR_ASCENDING (0x00<<0)
+#define GRN_CURSOR_DESCENDING (0x01<<0)
+#define GRN_CURSOR_GE (0x00<<1)
+#define GRN_CURSOR_GT (0x01<<1)
+#define GRN_CURSOR_LE (0x00<<2)
+#define GRN_CURSOR_LT (0x01<<2)
+#define GRN_CURSOR_BY_KEY (0x00<<3)
+#define GRN_CURSOR_BY_ID (0x01<<3)
+#define GRN_CURSOR_PREFIX (0x01<<4)
+#define GRN_CURSOR_SIZE_BY_BIT (0x01<<5)
+#define GRN_CURSOR_RK (0x01<<6)
+
+GRN_API grn_table_cursor *grn_table_cursor_open(grn_ctx *ctx, grn_obj *table,
+ const void *min, unsigned int min_size,
+ const void *max, unsigned int max_size,
+ int offset, int limit, int flags);
+GRN_API grn_rc grn_table_cursor_close(grn_ctx *ctx, grn_table_cursor *tc);
+GRN_API grn_id grn_table_cursor_next(grn_ctx *ctx, grn_table_cursor *tc);
+GRN_API int grn_table_cursor_get_key(grn_ctx *ctx, grn_table_cursor *tc, void **key);
+GRN_API int grn_table_cursor_get_value(grn_ctx *ctx, grn_table_cursor *tc, void **value);
+GRN_API grn_rc grn_table_cursor_set_value(grn_ctx *ctx, grn_table_cursor *tc,
+ const void *value, int flags);
+GRN_API grn_rc grn_table_cursor_delete(grn_ctx *ctx, grn_table_cursor *tc);
+GRN_API grn_obj *grn_table_cursor_table(grn_ctx *ctx, grn_table_cursor *tc);
+
+typedef struct {
+ grn_id rid;
+ grn_id sid;
+ unsigned int pos;
+ unsigned int tf;
+ unsigned int weight;
+ unsigned int rest;
+} grn_posting;
+
+GRN_API grn_obj *grn_index_cursor_open(grn_ctx *ctx, grn_table_cursor *tc, grn_obj *index,
+ grn_id rid_min, grn_id rid_max, int flags);
+GRN_API grn_posting *grn_index_cursor_next(grn_ctx *ctx, grn_obj *ic, grn_id *tid);
+
+#define GRN_TABLE_EACH(ctx,table,head,tail,id,key,key_size,value,block) do {\
+ (ctx)->errlvl = GRN_LOG_NOTICE;\
+ (ctx)->rc = GRN_SUCCESS;\
+ if ((ctx)->seqno & 1) {\
+ (ctx)->subno++;\
+ } else {\
+ (ctx)->seqno++;\
+ }\
+ if (table) {\
+ switch ((table)->header.type) {\
+ case GRN_TABLE_PAT_KEY :\
+ GRN_PAT_EACH((ctx), (grn_pat *)(table), (id), (key), (key_size), (value), block);\
+ break;\
+ case GRN_TABLE_DAT_KEY :\
+ GRN_DAT_EACH((ctx), (grn_dat *)(table), (id), (key), (key_size), block);\
+ break;\
+ case GRN_TABLE_HASH_KEY :\
+ GRN_HASH_EACH((ctx), (grn_hash *)(table), (id), (key), (key_size), (value), block);\
+ break;\
+ case GRN_TABLE_NO_KEY :\
+ GRN_ARRAY_EACH((ctx), (grn_array *)(table), (head), (tail), (id), (value), block);\
+ break;\
+ }\
+ }\
+ if ((ctx)->subno) {\
+ (ctx)->subno--;\
+ } else {\
+ (ctx)->seqno++;\
+ }\
+} while (0)
+
+typedef struct _grn_table_sort_key grn_table_sort_key;
+typedef unsigned char grn_table_sort_flags;
+
+#define GRN_TABLE_SORT_ASC (0x00<<0)
+#define GRN_TABLE_SORT_DESC (0x01<<0)
+
+struct _grn_table_sort_key {
+ grn_obj *key;
+ grn_table_sort_flags flags;
+ int offset;
+};
+
+GRN_API int grn_table_sort(grn_ctx *ctx, grn_obj *table, int offset, int limit,
+ grn_obj *result, grn_table_sort_key *keys, int n_keys);
+
+typedef struct _grn_table_group_result grn_table_group_result;
+typedef unsigned int grn_table_group_flags;
+
+#define GRN_TABLE_GROUP_CALC_COUNT (0x01<<3)
+#define GRN_TABLE_GROUP_CALC_MAX (0x01<<4)
+#define GRN_TABLE_GROUP_CALC_MIN (0x01<<5)
+#define GRN_TABLE_GROUP_CALC_SUM (0x01<<6)
+#define GRN_TABLE_GROUP_CALC_AVG (0x01<<7)
+
+typedef enum {
+ GRN_OP_PUSH = 0,
+ GRN_OP_POP,
+ GRN_OP_NOP,
+ GRN_OP_CALL,
+ GRN_OP_INTERN,
+ GRN_OP_GET_REF,
+ GRN_OP_GET_VALUE,
+ GRN_OP_AND,
+ GRN_OP_AND_NOT,
+ /* Deprecated. Just for backward compatibility. */
+#define GRN_OP_BUT GRN_OP_AND_NOT
+ GRN_OP_OR,
+ GRN_OP_ASSIGN,
+ GRN_OP_STAR_ASSIGN,
+ GRN_OP_SLASH_ASSIGN,
+ GRN_OP_MOD_ASSIGN,
+ GRN_OP_PLUS_ASSIGN,
+ GRN_OP_MINUS_ASSIGN,
+ GRN_OP_SHIFTL_ASSIGN,
+ GRN_OP_SHIFTR_ASSIGN,
+ GRN_OP_SHIFTRR_ASSIGN,
+ GRN_OP_AND_ASSIGN,
+ GRN_OP_XOR_ASSIGN,
+ GRN_OP_OR_ASSIGN,
+ GRN_OP_JUMP,
+ GRN_OP_CJUMP,
+ GRN_OP_COMMA,
+ GRN_OP_BITWISE_OR,
+ GRN_OP_BITWISE_XOR,
+ GRN_OP_BITWISE_AND,
+ GRN_OP_BITWISE_NOT,
+ GRN_OP_EQUAL,
+ GRN_OP_NOT_EQUAL,
+ GRN_OP_LESS,
+ GRN_OP_GREATER,
+ GRN_OP_LESS_EQUAL,
+ GRN_OP_GREATER_EQUAL,
+ GRN_OP_IN,
+ GRN_OP_MATCH,
+ GRN_OP_NEAR,
+ GRN_OP_NEAR2,
+ GRN_OP_SIMILAR,
+ GRN_OP_TERM_EXTRACT,
+ GRN_OP_SHIFTL,
+ GRN_OP_SHIFTR,
+ GRN_OP_SHIFTRR,
+ GRN_OP_PLUS,
+ GRN_OP_MINUS,
+ GRN_OP_STAR,
+ GRN_OP_SLASH,
+ GRN_OP_MOD,
+ GRN_OP_DELETE,
+ GRN_OP_INCR,
+ GRN_OP_DECR,
+ GRN_OP_INCR_POST,
+ GRN_OP_DECR_POST,
+ GRN_OP_NOT,
+ GRN_OP_ADJUST,
+ GRN_OP_EXACT,
+ GRN_OP_LCP,
+ GRN_OP_PARTIAL,
+ GRN_OP_UNSPLIT,
+ GRN_OP_PREFIX,
+ GRN_OP_SUFFIX,
+ GRN_OP_GEO_DISTANCE1,
+ GRN_OP_GEO_DISTANCE2,
+ GRN_OP_GEO_DISTANCE3,
+ GRN_OP_GEO_DISTANCE4,
+ GRN_OP_GEO_WITHINP5,
+ GRN_OP_GEO_WITHINP6,
+ GRN_OP_GEO_WITHINP8,
+ GRN_OP_OBJ_SEARCH,
+ GRN_OP_EXPR_GET_VAR,
+ GRN_OP_TABLE_CREATE,
+ GRN_OP_TABLE_SELECT,
+ GRN_OP_TABLE_SORT,
+ GRN_OP_TABLE_GROUP,
+ GRN_OP_JSON_PUT,
+ GRN_OP_GET_MEMBER
+} grn_operator;
+
+GRN_API const char *grn_operator_to_string(grn_operator op);
+GRN_API grn_bool grn_operator_exec_equal(grn_ctx *ctx, grn_obj *x, grn_obj *y);
+GRN_API grn_bool grn_operator_exec_not_equal(grn_ctx *ctx,
+ grn_obj *x, grn_obj *y);
+GRN_API grn_bool grn_operator_exec_less(grn_ctx *ctx, grn_obj *x, grn_obj *y);
+GRN_API grn_bool grn_operator_exec_greater(grn_ctx *ctx, grn_obj *x, grn_obj *y);
+GRN_API grn_bool grn_operator_exec_less_equal(grn_ctx *ctx,
+ grn_obj *x, grn_obj *y);
+GRN_API grn_bool grn_operator_exec_greater_equal(grn_ctx *ctx,
+ grn_obj *x, grn_obj *y);
+
+struct _grn_table_group_result {
+ grn_obj *table;
+ unsigned char key_begin;
+ unsigned char key_end;
+ int limit;
+ grn_table_group_flags flags;
+ grn_operator op;
+ unsigned int max_n_subrecs;
+ grn_obj *calc_target;
+};
+
+GRN_API grn_rc grn_table_group(grn_ctx *ctx, grn_obj *table,
+ grn_table_sort_key *keys, int n_keys,
+ grn_table_group_result *results, int n_results);
+GRN_API grn_rc grn_table_setoperation(grn_ctx *ctx, grn_obj *table1, grn_obj *table2,
+ grn_obj *res, grn_operator op);
+GRN_API grn_rc grn_table_difference(grn_ctx *ctx, grn_obj *table1, grn_obj *table2,
+ grn_obj *res1, grn_obj *res2);
+GRN_API int grn_table_columns(grn_ctx *ctx, grn_obj *table,
+ const char *name, unsigned int name_size,
+ grn_obj *res);
+
+GRN_API grn_obj *grn_obj_column(grn_ctx *ctx, grn_obj *table,
+ const char *name, unsigned int name_size);
+
+GRN_API unsigned int grn_table_size(grn_ctx *ctx, grn_obj *table);
+
+/*-------------------------------------------------------------
+ * API for column
+ */
+
+#define GRN_COLUMN_NAME_ID "_id"
+#define GRN_COLUMN_NAME_ID_LEN (sizeof(GRN_COLUMN_NAME_ID) - 1)
+#define GRN_COLUMN_NAME_KEY "_key"
+#define GRN_COLUMN_NAME_KEY_LEN (sizeof(GRN_COLUMN_NAME_KEY) - 1)
+#define GRN_COLUMN_NAME_VALUE "_value"
+#define GRN_COLUMN_NAME_VALUE_LEN (sizeof(GRN_COLUMN_NAME_VALUE) - 1)
+#define GRN_COLUMN_NAME_SCORE "_score"
+#define GRN_COLUMN_NAME_SCORE_LEN (sizeof(GRN_COLUMN_NAME_SCORE) - 1)
+#define GRN_COLUMN_NAME_NSUBRECS "_nsubrecs"
+#define GRN_COLUMN_NAME_NSUBRECS_LEN (sizeof(GRN_COLUMN_NAME_NSUBRECS) - 1)
+#define GRN_COLUMN_NAME_MAX "_max"
+#define GRN_COLUMN_NAME_MAX_LEN (sizeof(GRN_COLUMN_NAME_MAX) - 1)
+#define GRN_COLUMN_NAME_MIN "_min"
+#define GRN_COLUMN_NAME_MIN_LEN (sizeof(GRN_COLUMN_NAME_MIN) - 1)
+#define GRN_COLUMN_NAME_SUM "_sum"
+#define GRN_COLUMN_NAME_SUM_LEN (sizeof(GRN_COLUMN_NAME_SUM) - 1)
+#define GRN_COLUMN_NAME_AVG "_avg"
+#define GRN_COLUMN_NAME_AVG_LEN (sizeof(GRN_COLUMN_NAME_AVG) - 1)
+
+GRN_API grn_obj *grn_column_create(grn_ctx *ctx, grn_obj *table,
+ const char *name, unsigned int name_size,
+ const char *path, grn_obj_flags flags, grn_obj *type);
+
+#define GRN_COLUMN_OPEN_OR_CREATE(ctx,table,name,name_size,path,flags,type,column) \
+ (((column) = grn_obj_column((ctx), (table), (name), (name_size))) ||\
+ ((column) = grn_column_create((ctx), (table), (name), (name_size), (path), (flags), (type))))
+
+GRN_API grn_rc grn_column_index_update(grn_ctx *ctx, grn_obj *column,
+ grn_id id, unsigned int section,
+ grn_obj *oldvalue, grn_obj *newvalue);
+GRN_API grn_obj *grn_column_table(grn_ctx *ctx, grn_obj *column);
+GRN_API grn_rc grn_column_truncate(grn_ctx *ctx, grn_obj *column);
+
+/*-------------------------------------------------------------
+ * API for db, table and/or column
+ */
+
+typedef enum {
+ GRN_INFO_ENCODING = 0,
+ GRN_INFO_SOURCE,
+ GRN_INFO_DEFAULT_TOKENIZER,
+ GRN_INFO_ELEMENT_SIZE,
+ GRN_INFO_CURR_MAX,
+ GRN_INFO_MAX_ELEMENT_SIZE,
+ GRN_INFO_SEG_SIZE,
+ GRN_INFO_CHUNK_SIZE,
+ GRN_INFO_MAX_SECTION,
+ GRN_INFO_HOOK_LOCAL_DATA,
+ GRN_INFO_ELEMENT_A,
+ GRN_INFO_ELEMENT_CHUNK,
+ GRN_INFO_ELEMENT_CHUNK_SIZE,
+ GRN_INFO_ELEMENT_BUFFER_FREE,
+ GRN_INFO_ELEMENT_NTERMS,
+ GRN_INFO_ELEMENT_NTERMS_VOID,
+ GRN_INFO_ELEMENT_SIZE_IN_CHUNK,
+ GRN_INFO_ELEMENT_POS_IN_CHUNK,
+ GRN_INFO_ELEMENT_SIZE_IN_BUFFER,
+ GRN_INFO_ELEMENT_POS_IN_BUFFER,
+ GRN_INFO_ELEMENT_ESTIMATE_SIZE,
+ GRN_INFO_NGRAM_UNIT_SIZE,
+ /*
+ GRN_INFO_VERSION,
+ GRN_INFO_CONFIGURE_OPTIONS,
+ GRN_INFO_CONFIG_PATH,
+ */
+ GRN_INFO_PARTIAL_MATCH_THRESHOLD,
+ GRN_INFO_II_SPLIT_THRESHOLD,
+ GRN_INFO_SUPPORT_ZLIB,
+ GRN_INFO_SUPPORT_LZ4,
+/* Just for backward compatibility. We'll remove it at 5.0.0. */
+#define GRN_INFO_SUPPORT_LZO GRN_INFO_SUPPORT_LZ4
+ GRN_INFO_NORMALIZER,
+ GRN_INFO_TOKEN_FILTERS
+} grn_info_type;
+
+GRN_API grn_obj *grn_obj_get_info(grn_ctx *ctx, grn_obj *obj, grn_info_type type, grn_obj *valuebuf);
+GRN_API grn_rc grn_obj_set_info(grn_ctx *ctx, grn_obj *obj, grn_info_type type, grn_obj *value);
+GRN_API grn_obj *grn_obj_get_element_info(grn_ctx *ctx, grn_obj *obj, grn_id id,
+ grn_info_type type, grn_obj *value);
+GRN_API grn_rc grn_obj_set_element_info(grn_ctx *ctx, grn_obj *obj, grn_id id,
+ grn_info_type type, grn_obj *value);
+
+GRN_API grn_obj *grn_obj_get_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value);
+GRN_API int grn_obj_get_values(grn_ctx *ctx, grn_obj *obj, grn_id offset, void **values);
+
+#define GRN_COLUMN_EACH(ctx,column,id,value,block) do {\
+ int _n;\
+ grn_id id = 1;\
+ while ((_n = grn_obj_get_values(ctx, column, id, (void **)&value)) > 0) {\
+ for (; _n; _n--, id++, value++) {\
+ block\
+ }\
+ }\
+} while (0)
+
+#define GRN_OBJ_SET_MASK (0x07)
+#define GRN_OBJ_SET (0x01)
+#define GRN_OBJ_INCR (0x02)
+#define GRN_OBJ_DECR (0x03)
+#define GRN_OBJ_APPEND (0x04)
+#define GRN_OBJ_PREPEND (0x05)
+#define GRN_OBJ_GET (0x01<<4)
+#define GRN_OBJ_COMPARE (0x01<<5)
+#define GRN_OBJ_LOCK (0x01<<6)
+#define GRN_OBJ_UNLOCK (0x01<<7)
+
+GRN_API grn_rc grn_obj_set_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value, int flags);
+GRN_API grn_rc grn_obj_remove(grn_ctx *ctx, grn_obj *obj);
+GRN_API grn_rc grn_obj_rename(grn_ctx *ctx, grn_obj *obj,
+ const char *name, unsigned int name_size);
+GRN_API grn_rc grn_table_rename(grn_ctx *ctx, grn_obj *table,
+ const char *name, unsigned int name_size);
+
+GRN_API grn_rc grn_column_rename(grn_ctx *ctx, grn_obj *column,
+ const char *name, unsigned int name_size);
+
+GRN_API grn_rc grn_obj_close(grn_ctx *ctx, grn_obj *obj);
+GRN_API grn_rc grn_obj_reinit(grn_ctx *ctx, grn_obj *obj, grn_id domain, unsigned char flags);
+GRN_API void grn_obj_unlink(grn_ctx *ctx, grn_obj *obj);
+
+GRN_API grn_user_data *grn_obj_user_data(grn_ctx *ctx, grn_obj *obj);
+
+GRN_API grn_rc grn_obj_set_finalizer(grn_ctx *ctx, grn_obj *obj, grn_proc_func *func);
+
+GRN_API const char *grn_obj_path(grn_ctx *ctx, grn_obj *obj);
+GRN_API int grn_obj_name(grn_ctx *ctx, grn_obj *obj, char *namebuf, int buf_size);
+
+GRN_API int grn_column_name(grn_ctx *ctx, grn_obj *obj, char *namebuf, int buf_size);
+
+GRN_API grn_id grn_obj_get_range(grn_ctx *ctx, grn_obj *obj);
+
+#define GRN_OBJ_GET_DOMAIN(obj) \
+ ((obj)->header.type == GRN_TABLE_NO_KEY ? GRN_ID_NIL : (obj)->header.domain)
+
+GRN_API int grn_obj_expire(grn_ctx *ctx, grn_obj *obj, int threshold);
+GRN_API int grn_obj_check(grn_ctx *ctx, grn_obj *obj);
+GRN_API grn_rc grn_obj_lock(grn_ctx *ctx, grn_obj *obj, grn_id id, int timeout);
+GRN_API grn_rc grn_obj_unlock(grn_ctx *ctx, grn_obj *obj, grn_id id);
+GRN_API grn_rc grn_obj_clear_lock(grn_ctx *ctx, grn_obj *obj);
+GRN_API unsigned int grn_obj_is_locked(grn_ctx *ctx, grn_obj *obj);
+GRN_API int grn_obj_defrag(grn_ctx *ctx, grn_obj *obj, int threshold);
+
+GRN_API grn_obj *grn_obj_db(grn_ctx *ctx, grn_obj *obj);
+
+GRN_API grn_id grn_obj_id(grn_ctx *ctx, grn_obj *obj);
+
+typedef struct _grn_search_optarg grn_search_optarg;
+
+struct _grn_search_optarg {
+ grn_operator mode;
+ int similarity_threshold;
+ int max_interval;
+ int *weight_vector;
+ int vector_size;
+ grn_obj *proc;
+ int max_size;
+ grn_obj *scorer;
+};
+
+GRN_API grn_rc grn_obj_search(grn_ctx *ctx, grn_obj *obj, grn_obj *query,
+ grn_obj *res, grn_operator op, grn_search_optarg *optarg);
+
+typedef grn_rc grn_selector_func(grn_ctx *ctx, grn_obj *table, grn_obj *index,
+ int nargs, grn_obj **args,
+ grn_obj *res, grn_operator op);
+
+GRN_API grn_rc grn_proc_set_selector(grn_ctx *ctx, grn_obj *proc,
+ grn_selector_func selector);
+
+/*-------------------------------------------------------------
+ * grn_vector
+*/
+
+GRN_API unsigned int grn_vector_size(grn_ctx *ctx, grn_obj *vector);
+
+GRN_API grn_rc grn_vector_add_element(grn_ctx *ctx, grn_obj *vector,
+ const char *str, unsigned int str_len,
+ unsigned int weight, grn_id domain);
+
+GRN_API unsigned int grn_vector_get_element(grn_ctx *ctx, grn_obj *vector,
+ unsigned int offset, const char **str,
+ unsigned int *weight, grn_id *domain);
+
+/*-------------------------------------------------------------
+ * grn_uvector
+*/
+
+GRN_API unsigned int grn_uvector_size(grn_ctx *ctx, grn_obj *uvector);
+GRN_API unsigned int grn_uvector_element_size(grn_ctx *ctx, grn_obj *uvector);
+
+GRN_API grn_rc grn_uvector_add_element(grn_ctx *ctx, grn_obj *vector,
+ grn_id id, unsigned int weight);
+
+GRN_API grn_id grn_uvector_get_element(grn_ctx *ctx, grn_obj *uvector,
+ unsigned int offset,
+ unsigned int *weight);
+
+/*-------------------------------------------------------------
+ * API for hook
+ */
+
+GRN_API int grn_proc_call_next(grn_ctx *ctx, grn_obj *exec_info, grn_obj *in, grn_obj *out);
+GRN_API void *grn_proc_get_ctx_local_data(grn_ctx *ctx, grn_obj *exec_info);
+GRN_API void *grn_proc_get_hook_local_data(grn_ctx *ctx, grn_obj *exec_info);
+
+typedef enum {
+ GRN_HOOK_SET = 0,
+ GRN_HOOK_GET,
+ GRN_HOOK_INSERT,
+ GRN_HOOK_DELETE,
+ GRN_HOOK_SELECT
+} grn_hook_entry;
+
+GRN_API grn_rc grn_obj_add_hook(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry,
+ int offset, grn_obj *proc, grn_obj *data);
+GRN_API int grn_obj_get_nhooks(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry);
+GRN_API grn_obj *grn_obj_get_hook(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry,
+ int offset, grn_obj *data);
+GRN_API grn_rc grn_obj_delete_hook(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry, int offset);
+
+GRN_API grn_obj *grn_obj_open(grn_ctx *ctx, unsigned char type, grn_obj_flags flags, grn_id domain);
+
+GRN_API int grn_column_index(grn_ctx *ctx, grn_obj *column, grn_operator op,
+ grn_obj **indexbuf, int buf_size, int *section);
+
+GRN_API grn_rc grn_obj_delete_by_id(grn_ctx *ctx, grn_obj *db, grn_id id, grn_bool removep);
+GRN_API grn_rc grn_obj_path_by_id(grn_ctx *ctx, grn_obj *db, grn_id id, char *buffer);
+
+/* geo */
+
+typedef struct {
+ int latitude;
+ int longitude;
+} grn_geo_point;
+
+GRN_API grn_rc grn_geo_select_in_rectangle(grn_ctx *ctx,
+ grn_obj *index,
+ grn_obj *top_left_point,
+ grn_obj *bottom_right_point,
+ grn_obj *res,
+ grn_operator op);
+GRN_API unsigned int grn_geo_estimate_size_in_rectangle(grn_ctx *ctx,
+ grn_obj *index,
+ grn_obj *top_left_point,
+ grn_obj *bottom_right_point);
+/* Deprecated since 4.0.8. Use grn_geo_estimate_size_in_rectangle() instead. */
+GRN_API int grn_geo_estimate_in_rectangle(grn_ctx *ctx,
+ grn_obj *index,
+ grn_obj *top_left_point,
+ grn_obj *bottom_right_point);
+GRN_API grn_obj *grn_geo_cursor_open_in_rectangle(grn_ctx *ctx,
+ grn_obj *index,
+ grn_obj *top_left_point,
+ grn_obj *bottom_right_point,
+ int offset,
+ int limit);
+GRN_API grn_posting *grn_geo_cursor_next(grn_ctx *ctx, grn_obj *cursor);
+
+
+/* query & snippet */
+
+#ifndef GRN_QUERY_AND
+#define GRN_QUERY_AND '+'
+#endif /* GRN_QUERY_AND */
+#ifndef GRN_QUERY_AND_NOT
+# ifdef GRN_QUERY_BUT
+ /* Deprecated. Just for backward compatibility. */
+# define GRN_QUERY_AND_NOT GRN_QUERY_BUT
+# else
+# define GRN_QUERY_AND_NOT '-'
+# endif /* GRN_QUERY_BUT */
+#endif /* GRN_QUERY_AND_NOT */
+#ifndef GRN_QUERY_ADJ_INC
+#define GRN_QUERY_ADJ_INC '>'
+#endif /* GRN_QUERY_ADJ_POS2 */
+#ifndef GRN_QUERY_ADJ_DEC
+#define GRN_QUERY_ADJ_DEC '<'
+#endif /* GRN_QUERY_ADJ_POS1 */
+#ifndef GRN_QUERY_ADJ_NEG
+#define GRN_QUERY_ADJ_NEG '~'
+#endif /* GRN_QUERY_ADJ_NEG */
+#ifndef GRN_QUERY_PREFIX
+#define GRN_QUERY_PREFIX '*'
+#endif /* GRN_QUERY_PREFIX */
+#ifndef GRN_QUERY_PARENL
+#define GRN_QUERY_PARENL '('
+#endif /* GRN_QUERY_PARENL */
+#ifndef GRN_QUERY_PARENR
+#define GRN_QUERY_PARENR ')'
+#endif /* GRN_QUERY_PARENR */
+#ifndef GRN_QUERY_QUOTEL
+#define GRN_QUERY_QUOTEL '"'
+#endif /* GRN_QUERY_QUOTEL */
+#ifndef GRN_QUERY_QUOTER
+#define GRN_QUERY_QUOTER '"'
+#endif /* GRN_QUERY_QUOTER */
+#ifndef GRN_QUERY_ESCAPE
+#define GRN_QUERY_ESCAPE '\\'
+#endif /* GRN_QUERY_ESCAPE */
+#ifndef GRN_QUERY_COLUMN
+#define GRN_QUERY_COLUMN ':'
+#endif /* GRN_QUERY_COLUMN */
+
+typedef struct _grn_snip_mapping grn_snip_mapping;
+
+struct _grn_snip_mapping {
+ void *dummy;
+};
+
+#define GRN_SNIP_NORMALIZE (0x01<<0)
+#define GRN_SNIP_COPY_TAG (0x01<<1)
+#define GRN_SNIP_SKIP_LEADING_SPACES (0x01<<2)
+
+#define GRN_SNIP_MAPPING_HTML_ESCAPE ((grn_snip_mapping *)-1)
+
+GRN_API grn_obj *grn_snip_open(grn_ctx *ctx, int flags, unsigned int width,
+ unsigned int max_results,
+ const char *defaultopentag, unsigned int defaultopentag_len,
+ const char *defaultclosetag, unsigned int defaultclosetag_len,
+ grn_snip_mapping *mapping);
+GRN_API grn_rc grn_snip_add_cond(grn_ctx *ctx, grn_obj *snip,
+ const char *keyword, unsigned int keyword_len,
+ const char *opentag, unsigned int opentag_len,
+ const char *closetag, unsigned int closetag_len);
+GRN_API grn_rc grn_snip_set_normalizer(grn_ctx *ctx, grn_obj *snip,
+ grn_obj *normalizer);
+GRN_API grn_obj *grn_snip_get_normalizer(grn_ctx *ctx, grn_obj *snip);
+GRN_API grn_rc grn_snip_exec(grn_ctx *ctx, grn_obj *snip,
+ const char *string, unsigned int string_len,
+ unsigned int *nresults, unsigned int *max_tagged_len);
+GRN_API grn_rc grn_snip_get_result(grn_ctx *ctx, grn_obj *snip, const unsigned int index,
+ char *result, unsigned int *result_len);
+
+/* log */
+
+#define GRN_LOG_TIME (0x01<<0)
+#define GRN_LOG_TITLE (0x01<<1)
+#define GRN_LOG_MESSAGE (0x01<<2)
+#define GRN_LOG_LOCATION (0x01<<3)
+
+/* Deprecated since 2.1.2. Use grn_logger instead. */
+typedef struct _grn_logger_info grn_logger_info;
+
+/* Deprecated since 2.1.2. Use grn_logger instead. */
+struct _grn_logger_info {
+ grn_log_level max_level;
+ int flags;
+ void (*func)(int, const char *, const char *, const char *, const char *, void *);
+ void *func_arg;
+};
+
+/* Deprecated since 2.1.2. Use grn_logger_set() instead. */
+GRN_API grn_rc grn_logger_info_set(grn_ctx *ctx, const grn_logger_info *info);
+
+typedef struct _grn_logger grn_logger;
+
+struct _grn_logger {
+ grn_log_level max_level;
+ int flags;
+ void *user_data;
+ void (*log)(grn_ctx *ctx, grn_log_level level,
+ const char *timestamp, const char *title, const char *message,
+ const char *location, void *user_data);
+ void (*reopen)(grn_ctx *ctx, void *user_data);
+ void (*fin)(grn_ctx *ctx, void *user_data);
+};
+
+GRN_API grn_rc grn_logger_set(grn_ctx *ctx, const grn_logger *logger);
+
+GRN_API void grn_logger_set_max_level(grn_ctx *ctx, grn_log_level max_level);
+GRN_API grn_log_level grn_logger_get_max_level(grn_ctx *ctx);
+
+#ifdef __GNUC__
+#define GRN_ATTRIBUTE_PRINTF(fmt_pos) \
+ __attribute__ ((format(printf, fmt_pos, fmt_pos + 1)))
+#else
+#define GRN_ATTRIBUTE_PRINTF(fmt_pos)
+#endif /* __GNUC__ */
+
+GRN_API void grn_logger_put(grn_ctx *ctx, grn_log_level level,
+ const char *file, int line, const char *func, const char *fmt, ...) GRN_ATTRIBUTE_PRINTF(6);
+GRN_API void grn_logger_reopen(grn_ctx *ctx);
+
+GRN_API grn_bool grn_logger_pass(grn_ctx *ctx, grn_log_level level);
+
+#ifndef GRN_LOG_DEFAULT_LEVEL
+#define GRN_LOG_DEFAULT_LEVEL GRN_LOG_NOTICE
+#endif /* GRN_LOG_DEFAULT_LEVEL */
+
+GRN_API void grn_default_logger_set_max_level(grn_log_level level);
+GRN_API grn_log_level grn_default_logger_get_max_level(void);
+GRN_API void grn_default_logger_set_path(const char *path);
+GRN_API const char *grn_default_logger_get_path(void);
+
+#define GRN_LOG(ctx,level,...) do {\
+ if (grn_logger_pass(ctx, level)) {\
+ grn_logger_put(ctx, (level), __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__); \
+ }\
+} while (0)
+
+typedef struct _grn_query_logger grn_query_logger;
+
+struct _grn_query_logger {
+ unsigned int flags;
+ void *user_data;
+ void (*log)(grn_ctx *ctx, unsigned int flag,
+ const char *timestamp, const char *info, const char *message,
+ void *user_data);
+ void (*reopen)(grn_ctx *ctx, void *user_data);
+ void (*fin)(grn_ctx *ctx, void *user_data);
+};
+
+GRN_API grn_rc grn_query_logger_set(grn_ctx *ctx, const grn_query_logger *logger);
+
+GRN_API void grn_query_logger_put(grn_ctx *ctx, unsigned int flag,
+ const char *mark,
+ const char *format, ...) GRN_ATTRIBUTE_PRINTF(4);
+GRN_API void grn_query_logger_reopen(grn_ctx *ctx);
+
+GRN_API grn_bool grn_query_logger_pass(grn_ctx *ctx, unsigned int flag);
+
+GRN_API void grn_default_query_logger_set_flags(unsigned int flags);
+GRN_API unsigned int grn_default_query_logger_get_flags(void);
+GRN_API void grn_default_query_logger_set_path(const char *path);
+GRN_API const char *grn_default_query_logger_get_path(void);
+
+#define GRN_QUERY_LOG(ctx, flag, mark, format, ...) do {\
+ if (grn_query_logger_pass(ctx, flag)) {\
+ grn_query_logger_put(ctx, (flag), (mark), format, __VA_ARGS__);\
+ }\
+} while (0)
+
+/* grn_bulk */
+
+#define GRN_BULK_BUFSIZE (sizeof(grn_obj) - sizeof(grn_obj_header))
+/* This assumes that GRN_BULK_BUFSIZE is less than 32 (= 0x20). */
+#define GRN_BULK_BUFSIZE_MAX 0x1f
+#define GRN_BULK_SIZE_IN_FLAGS(flags) ((flags) & GRN_BULK_BUFSIZE_MAX)
+#define GRN_BULK_OUTP(bulk) ((bulk)->header.impl_flags & GRN_OBJ_OUTPLACE)
+#define GRN_BULK_REWIND(bulk) do {\
+ if ((bulk)->header.type == GRN_VECTOR) {\
+ grn_obj *_body = (bulk)->u.v.body;\
+ if (_body) {\
+ if (GRN_BULK_OUTP(_body)) {\
+ (_body)->u.b.curr = (_body)->u.b.head;\
+ } else {\
+ (_body)->header.flags &= ~GRN_BULK_BUFSIZE_MAX;\
+ }\
+ }\
+ (bulk)->u.v.n_sections = 0;\
+ } else {\
+ if (GRN_BULK_OUTP(bulk)) {\
+ (bulk)->u.b.curr = (bulk)->u.b.head;\
+ } else {\
+ (bulk)->header.flags &= ~GRN_BULK_BUFSIZE_MAX;\
+ }\
+ }\
+} while (0)
+#define GRN_BULK_WSIZE(bulk) \
+ (GRN_BULK_OUTP(bulk)\
+ ? ((bulk)->u.b.tail - (bulk)->u.b.head)\
+ : GRN_BULK_BUFSIZE)
+#define GRN_BULK_REST(bulk) \
+ (GRN_BULK_OUTP(bulk)\
+ ? ((bulk)->u.b.tail - (bulk)->u.b.curr)\
+ : GRN_BULK_BUFSIZE - GRN_BULK_SIZE_IN_FLAGS((bulk)->header.flags))
+#define GRN_BULK_VSIZE(bulk) \
+ (GRN_BULK_OUTP(bulk)\
+ ? ((bulk)->u.b.curr - (bulk)->u.b.head)\
+ : GRN_BULK_SIZE_IN_FLAGS((bulk)->header.flags))
+#define GRN_BULK_EMPTYP(bulk) \
+ (GRN_BULK_OUTP(bulk)\
+ ? ((bulk)->u.b.curr == (bulk)->u.b.head)\
+ : !(GRN_BULK_SIZE_IN_FLAGS((bulk)->header.flags)))
+#define GRN_BULK_HEAD(bulk) \
+ (GRN_BULK_OUTP(bulk)\
+ ? ((bulk)->u.b.head)\
+ : (char *)&((bulk)->u.b.head))
+#define GRN_BULK_CURR(bulk) \
+ (GRN_BULK_OUTP(bulk)\
+ ? ((bulk)->u.b.curr)\
+ : (char *)&((bulk)->u.b.head) + GRN_BULK_SIZE_IN_FLAGS((bulk)->header.flags))
+#define GRN_BULK_TAIL(bulk) \
+ (GRN_BULK_OUTP(bulk)\
+ ? ((bulk)->u.b.tail)\
+ : (char *)&((bulk)[1]))
+
+GRN_API grn_rc grn_bulk_reinit(grn_ctx *ctx, grn_obj *bulk, unsigned int size);
+GRN_API grn_rc grn_bulk_resize(grn_ctx *ctx, grn_obj *bulk, unsigned int newsize);
+GRN_API grn_rc grn_bulk_write(grn_ctx *ctx, grn_obj *bulk,
+ const char *str, unsigned int len);
+GRN_API grn_rc grn_bulk_write_from(grn_ctx *ctx, grn_obj *bulk,
+ const char *str, unsigned int from, unsigned int len);
+GRN_API grn_rc grn_bulk_reserve(grn_ctx *ctx, grn_obj *bulk, unsigned int len);
+GRN_API grn_rc grn_bulk_space(grn_ctx *ctx, grn_obj *bulk, unsigned int len);
+GRN_API grn_rc grn_bulk_truncate(grn_ctx *ctx, grn_obj *bulk, unsigned int len);
+GRN_API grn_rc grn_bulk_fin(grn_ctx *ctx, grn_obj *bulk);
+
+/* grn_text */
+
+GRN_API grn_rc grn_text_itoa(grn_ctx *ctx, grn_obj *bulk, int i);
+GRN_API grn_rc grn_text_itoa_padded(grn_ctx *ctx, grn_obj *bulk, int i, char ch, unsigned int len);
+GRN_API grn_rc grn_text_lltoa(grn_ctx *ctx, grn_obj *bulk, long long int i);
+GRN_API grn_rc grn_text_ftoa(grn_ctx *ctx, grn_obj *bulk, double d);
+GRN_API grn_rc grn_text_itoh(grn_ctx *ctx, grn_obj *bulk, int i, unsigned int len);
+GRN_API grn_rc grn_text_itob(grn_ctx *ctx, grn_obj *bulk, grn_id id);
+GRN_API grn_rc grn_text_lltob32h(grn_ctx *ctx, grn_obj *bulk, long long int i);
+GRN_API grn_rc grn_text_benc(grn_ctx *ctx, grn_obj *bulk, unsigned int v);
+GRN_API grn_rc grn_text_esc(grn_ctx *ctx, grn_obj *bulk, const char *s, unsigned int len);
+GRN_API grn_rc grn_text_urlenc(grn_ctx *ctx, grn_obj *buf,
+ const char *str, unsigned int len);
+GRN_API const char *grn_text_urldec(grn_ctx *ctx, grn_obj *buf,
+ const char *s, const char *e, char d);
+GRN_API grn_rc grn_text_escape_xml(grn_ctx *ctx, grn_obj *buf,
+ const char *s, unsigned int len);
+GRN_API grn_rc grn_text_time2rfc1123(grn_ctx *ctx, grn_obj *bulk, int sec);
+GRN_API grn_rc grn_text_printf(grn_ctx *ctx, grn_obj *bulk,
+ const char *format, ...) GRN_ATTRIBUTE_PRINTF(3);
+GRN_API grn_rc grn_text_vprintf(grn_ctx *ctx, grn_obj *bulk,
+ const char *format, va_list args);
+
+GRN_API void grn_ctx_recv_handler_set(grn_ctx *,
+ void (*func)(grn_ctx *, int, void *),
+ void *func_arg);
+
+/* various values exchanged via grn_obj */
+
+#define GRN_OBJ_DO_SHALLOW_COPY (GRN_OBJ_REFER|GRN_OBJ_OUTPLACE)
+#define GRN_OBJ_VECTOR (0x01<<7)
+
+#define GRN_OBJ_MUTABLE(obj) ((obj) && (obj)->header.type <= GRN_VECTOR)
+
+#define GRN_VALUE_FIX_SIZE_INIT(obj,flags,domain)\
+ GRN_OBJ_INIT((obj), ((flags) & GRN_OBJ_VECTOR) ? GRN_UVECTOR : GRN_BULK,\
+ ((flags) & GRN_OBJ_DO_SHALLOW_COPY), (domain))
+#define GRN_VALUE_VAR_SIZE_INIT(obj,flags,domain)\
+ GRN_OBJ_INIT((obj), ((flags) & GRN_OBJ_VECTOR) ? GRN_VECTOR : GRN_BULK,\
+ ((flags) & GRN_OBJ_DO_SHALLOW_COPY), (domain))
+
+#define GRN_VOID_INIT(obj) GRN_OBJ_INIT((obj), GRN_VOID, 0, GRN_DB_VOID)
+#define GRN_TEXT_INIT(obj,flags) \
+ GRN_VALUE_VAR_SIZE_INIT(obj, flags, GRN_DB_TEXT)
+#define GRN_SHORT_TEXT_INIT(obj,flags) \
+ GRN_VALUE_VAR_SIZE_INIT(obj, flags, GRN_DB_SHORT_TEXT)
+#define GRN_LONG_TEXT_INIT(obj,flags) \
+ GRN_VALUE_VAR_SIZE_INIT(obj, flags, GRN_DB_LONG_TEXT)
+#define GRN_TEXT_SET_REF(obj,str,len) do {\
+ (obj)->u.b.head = (char *)(str);\
+ (obj)->u.b.curr = (char *)(str) + (len);\
+} while (0)
+#define GRN_TEXT_SET(ctx,obj,str,len) do {\
+ if ((obj)->header.impl_flags & GRN_OBJ_REFER) {\
+ GRN_TEXT_SET_REF((obj), (str), (len));\
+ } else {\
+ grn_bulk_write_from((ctx), (obj), (const char *)(str), 0, (unsigned int)(len));\
+ }\
+} while (0)
+#define GRN_TEXT_PUT(ctx,obj,str,len) \
+ grn_bulk_write((ctx), (obj), (const char *)(str), (unsigned int)(len))
+#define GRN_TEXT_PUTC(ctx,obj,c) do {\
+ char _c = (c); grn_bulk_write((ctx), (obj), &_c, 1);\
+} while (0)
+
+#define GRN_TEXT_PUTS(ctx,obj,str) GRN_TEXT_PUT((ctx), (obj), (str), strlen(str))
+#define GRN_TEXT_SETS(ctx,obj,str) GRN_TEXT_SET((ctx), (obj), (str), strlen(str))
+#define GRN_TEXT_VALUE(obj) GRN_BULK_HEAD(obj)
+#define GRN_TEXT_LEN(obj) GRN_BULK_VSIZE(obj)
+
+#define GRN_BOOL_INIT(obj,flags) \
+ GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_BOOL)
+#define GRN_INT8_INIT(obj,flags) \
+ GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_INT8)
+#define GRN_UINT8_INIT(obj,flags) \
+ GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_UINT8)
+#define GRN_INT16_INIT(obj,flags) \
+ GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_INT16)
+#define GRN_UINT16_INIT(obj,flags) \
+ GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_UINT16)
+#define GRN_INT32_INIT(obj,flags) \
+ GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_INT32)
+#define GRN_UINT32_INIT(obj,flags) \
+ GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_UINT32)
+#define GRN_INT64_INIT(obj,flags) \
+ GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_INT64)
+#define GRN_UINT64_INIT(obj,flags) \
+ GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_UINT64)
+#define GRN_FLOAT_INIT(obj,flags) \
+ GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_FLOAT)
+#define GRN_TIME_INIT(obj,flags) \
+ GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_TIME)
+#define GRN_RECORD_INIT GRN_VALUE_FIX_SIZE_INIT
+#define GRN_PTR_INIT(obj,flags,domain)\
+ GRN_OBJ_INIT((obj), ((flags) & GRN_OBJ_VECTOR) ? GRN_PVECTOR : GRN_PTR,\
+ ((flags) & GRN_OBJ_DO_SHALLOW_COPY), (domain))
+#define GRN_TOKYO_GEO_POINT_INIT(obj,flags) \
+ GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_TOKYO_GEO_POINT)
+#define GRN_WGS84_GEO_POINT_INIT(obj,flags) \
+ GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_WGS84_GEO_POINT)
+
+#define GRN_BOOL_SET(ctx,obj,val) do {\
+ unsigned char _val = (unsigned char)(val);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(unsigned char));\
+} while (0)
+#define GRN_INT8_SET(ctx,obj,val) do {\
+ signed char _val = (signed char)(val);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(signed char));\
+} while (0)
+#define GRN_UINT8_SET(ctx,obj,val) do {\
+ unsigned char _val = (unsigned char)(val);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(unsigned char));\
+} while (0)
+#define GRN_INT16_SET(ctx,obj,val) do {\
+ signed short _val = (signed short)(val);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(signed short));\
+} while (0)
+#define GRN_UINT16_SET(ctx,obj,val) do {\
+ unsigned short _val = (unsigned short)(val);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(unsigned short));\
+} while (0)
+#define GRN_INT32_SET(ctx,obj,val) do {\
+ int _val = (int)(val);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(int));\
+} while (0)
+#define GRN_UINT32_SET(ctx,obj,val) do {\
+ unsigned int _val = (unsigned int)(val);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(unsigned int));\
+} while (0)
+#define GRN_INT64_SET(ctx,obj,val) do {\
+ long long int _val = (long long int)(val);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(long long int));\
+} while (0)
+#define GRN_UINT64_SET(ctx,obj,val) do {\
+ long long unsigned int _val = (long long unsigned int)(val);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(long long unsigned int));\
+} while (0)
+#define GRN_FLOAT_SET(ctx,obj,val) do {\
+ double _val = (double)(val);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(double));\
+} while (0)
+#define GRN_TIME_SET GRN_INT64_SET
+#define GRN_RECORD_SET(ctx,obj,val) do {\
+ grn_id _val = (grn_id)(val);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(grn_id));\
+} while (0)
+#define GRN_PTR_SET(ctx,obj,val) do {\
+ grn_obj *_val = (grn_obj *)(val);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(grn_obj *));\
+} while (0)
+
+#define GRN_GEO_DEGREE2MSEC(degree)\
+ ((int)((degree) * 3600 * 1000 + ((degree) > 0 ? 0.5 : -0.5)))
+#define GRN_GEO_MSEC2DEGREE(msec)\
+ ((((int)(msec)) / 3600.0) * 0.001)
+
+#define GRN_GEO_POINT_SET(ctx,obj,_latitude,_longitude) do {\
+ grn_geo_point _val;\
+ _val.latitude = (int)(_latitude);\
+ _val.longitude = (int)(_longitude);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(grn_geo_point));\
+} while (0)
+
+#define GRN_BOOL_SET_AT(ctx,obj,offset,val) do {\
+ unsigned char _val = (unsigned char)(val);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val,\
+ (offset), sizeof(unsigned char));\
+} while (0)
+#define GRN_INT8_SET_AT(ctx,obj,offset,val) do {\
+ signed char _val = (signed char)(val);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val,\
+ (offset) * sizeof(signed char), sizeof(signed char));\
+} while (0)
+#define GRN_UINT8_SET_AT(ctx,obj,offset,val) do { \
+ unsigned char _val = (unsigned char)(val);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val,\
+ (offset) * sizeof(unsigned char), sizeof(unsigned char));\
+} while (0)
+#define GRN_INT16_SET_AT(ctx,obj,offset,val) do {\
+ signed short _val = (signed short)(val);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val,\
+ (offset) * sizeof(signed short), sizeof(signed short));\
+} while (0)
+#define GRN_UINT16_SET_AT(ctx,obj,offset,val) do { \
+ unsigned short _val = (unsigned short)(val);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val,\
+ (offset) * sizeof(unsigned short), sizeof(unsigned short));\
+} while (0)
+#define GRN_INT32_SET_AT(ctx,obj,offset,val) do {\
+ int _val = (int)(val);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val,\
+ (offset) * sizeof(int), sizeof(int));\
+} while (0)
+#define GRN_UINT32_SET_AT(ctx,obj,offset,val) do { \
+ unsigned int _val = (unsigned int)(val);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val,\
+ (offset) * sizeof(unsigned int), sizeof(unsigned int));\
+} while (0)
+#define GRN_INT64_SET_AT(ctx,obj,offset,val) do {\
+ long long int _val = (long long int)(val);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val,\
+ (offset) * sizeof(long long int), sizeof(long long int));\
+} while (0)
+#define GRN_UINT64_SET_AT(ctx,obj,offset,val) do {\
+ long long unsigned int _val = (long long unsigned int)(val);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val,\
+ (offset) * sizeof(long long unsigned int),\
+ sizeof(long long unsigned int));\
+} while (0)
+#define GRN_FLOAT_SET_AT(ctx,obj,offset,val) do {\
+ double _val = (double)(val);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val,\
+ (offset) * sizeof(double), sizeof(double));\
+} while (0)
+#define GRN_TIME_SET_AT GRN_INT64_SET_AT
+#define GRN_RECORD_SET_AT(ctx,obj,offset,val) do {\
+ grn_id _val = (grn_id)(val);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val,\
+ (offset) * sizeof(grn_id), sizeof(grn_id));\
+} while (0)
+#define GRN_PTR_SET_AT(ctx,obj,offset,val) do {\
+ grn_obj *_val = (grn_obj *)(val);\
+ grn_bulk_write_from((ctx), (obj), (char *)&_val,\
+ (offset) * sizeof(grn_obj *), sizeof(grn_obj *));\
+} while (0)
+
+#define GRN_TIME_USEC_PER_SEC 1000000
+#define GRN_TIME_PACK(sec, usec) ((long long int)(sec) * GRN_TIME_USEC_PER_SEC + (usec))
+#define GRN_TIME_UNPACK(time_value, sec, usec) do {\
+ sec = (time_value) / GRN_TIME_USEC_PER_SEC;\
+ usec = (time_value) % GRN_TIME_USEC_PER_SEC;\
+} while (0)
+
+GRN_API void grn_time_now(grn_ctx *ctx, grn_obj *obj);
+
+#define GRN_TIME_NOW(ctx,obj) (grn_time_now((ctx), (obj)))
+
+#define GRN_BOOL_VALUE(obj) (*((unsigned char *)GRN_BULK_HEAD(obj)))
+#define GRN_INT8_VALUE(obj) (*((signed char *)GRN_BULK_HEAD(obj)))
+#define GRN_UINT8_VALUE(obj) (*((unsigned char *)GRN_BULK_HEAD(obj)))
+#define GRN_INT16_VALUE(obj) (*((signed short *)GRN_BULK_HEAD(obj)))
+#define GRN_UINT16_VALUE(obj) (*((unsigned short *)GRN_BULK_HEAD(obj)))
+#define GRN_INT32_VALUE(obj) (*((int *)GRN_BULK_HEAD(obj)))
+#define GRN_UINT32_VALUE(obj) (*((unsigned int *)GRN_BULK_HEAD(obj)))
+#define GRN_INT64_VALUE(obj) (*((long long int *)GRN_BULK_HEAD(obj)))
+#define GRN_UINT64_VALUE(obj) (*((long long unsigned int *)GRN_BULK_HEAD(obj)))
+#define GRN_FLOAT_VALUE(obj) (*((double *)GRN_BULK_HEAD(obj)))
+#define GRN_TIME_VALUE GRN_INT64_VALUE
+#define GRN_RECORD_VALUE(obj) (*((grn_id *)GRN_BULK_HEAD(obj)))
+#define GRN_PTR_VALUE(obj) (*((grn_obj **)GRN_BULK_HEAD(obj)))
+#define GRN_GEO_POINT_VALUE(obj,_latitude,_longitude) do {\
+ grn_geo_point *_val = (grn_geo_point *)GRN_BULK_HEAD(obj);\
+ _latitude = _val->latitude;\
+ _longitude = _val->longitude;\
+} while (0)
+
+#define GRN_BOOL_VALUE_AT(obj,offset) (((unsigned char *)GRN_BULK_HEAD(obj))[offset])
+#define GRN_INT8_VALUE_AT(obj,offset) (((signed char *)GRN_BULK_HEAD(obj))[offset])
+#define GRN_UINT8_VALUE_AT(obj,offset) (((unsigned char *)GRN_BULK_HEAD(obj))[offset])
+#define GRN_INT16_VALUE_AT(obj,offset) (((signed short *)GRN_BULK_HEAD(obj))[offset])
+#define GRN_UINT16_VALUE_AT(obj,offset) (((unsigned short *)GRN_BULK_HEAD(obj))[offset])
+#define GRN_INT32_VALUE_AT(obj,offset) (((int *)GRN_BULK_HEAD(obj))[offset])
+#define GRN_UINT32_VALUE_AT(obj,offset) (((unsigned int *)GRN_BULK_HEAD(obj))[offset])
+#define GRN_INT64_VALUE_AT(obj,offset) (((long long int *)GRN_BULK_HEAD(obj))[offset])
+#define GRN_UINT64_VALUE_AT(obj,offset) (((long long unsigned int *)GRN_BULK_HEAD(obj))[offset])
+#define GRN_FLOAT_VALUE_AT(obj,offset) (((double *)GRN_BULK_HEAD(obj))[offset])
+#define GRN_TIME_VALUE_AT GRN_INT64_VALUE_AT
+#define GRN_RECORD_VALUE_AT(obj,offset) (((grn_id *)GRN_BULK_HEAD(obj))[offset])
+#define GRN_PTR_VALUE_AT(obj,offset) (((grn_obj **)GRN_BULK_HEAD(obj))[offset])
+
+#define GRN_BOOL_PUT(ctx,obj,val) do {\
+ unsigned char _val = (unsigned char)(val);\
+ grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(unsigned char));\
+} while (0)
+#define GRN_INT8_PUT(ctx,obj,val) do {\
+ signed char _val = (signed char)(val); grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(signed char));\
+} while (0)
+#define GRN_UINT8_PUT(ctx,obj,val) do {\
+ unsigned char _val = (unsigned char)(val);\
+ grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(unsigned char));\
+} while (0)
+#define GRN_INT16_PUT(ctx,obj,val) do {\
+ signed short _val = (signed short)(val); grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(signed short));\
+} while (0)
+#define GRN_UINT16_PUT(ctx,obj,val) do {\
+ unsigned short _val = (unsigned short)(val);\
+ grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(unsigned short));\
+} while (0)
+#define GRN_INT32_PUT(ctx,obj,val) do {\
+ int _val = (int)(val); grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(int));\
+} while (0)
+#define GRN_UINT32_PUT(ctx,obj,val) do {\
+ unsigned int _val = (unsigned int)(val);\
+ grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(unsigned int));\
+} while (0)
+#define GRN_INT64_PUT(ctx,obj,val) do {\
+ long long int _val = (long long int)(val);\
+ grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(long long int));\
+} while (0)
+#define GRN_UINT64_PUT(ctx,obj,val) do {\
+ long long unsigned int _val = (long long unsigned int)(val);\
+ grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(long long unsigned int));\
+} while (0)
+#define GRN_FLOAT_PUT(ctx,obj,val) do {\
+ double _val = (double)(val); grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(double));\
+} while (0)
+#define GRN_TIME_PUT GRN_INT64_PUT
+#define GRN_RECORD_PUT(ctx,obj,val) do {\
+ grn_id _val = (grn_id)(val); grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(grn_id));\
+} while (0)
+#define GRN_PTR_PUT(ctx,obj,val) do {\
+ grn_obj *_val = (grn_obj *)(val);\
+ grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(grn_obj *));\
+} while (0)
+
+/* grn_str: deprecated. use grn_string instead. */
+
+typedef struct {
+ const char *orig;
+ char *norm;
+ short *checks;
+ unsigned char *ctypes;
+ int flags;
+ unsigned int orig_blen;
+ unsigned int norm_blen;
+ unsigned int length;
+ grn_encoding encoding;
+} grn_str;
+
+#define GRN_STR_REMOVEBLANK (0x01<<0)
+#define GRN_STR_WITH_CTYPES (0x01<<1)
+#define GRN_STR_WITH_CHECKS (0x01<<2)
+#define GRN_STR_NORMALIZE GRN_OBJ_KEY_NORMALIZE
+
+GRN_API grn_str *grn_str_open(grn_ctx *ctx, const char *str, unsigned int str_len,
+ int flags);
+GRN_API grn_rc grn_str_close(grn_ctx *ctx, grn_str *nstr);
+
+/* grn_string */
+
+#define GRN_STRING_REMOVE_BLANK (0x01<<0)
+#define GRN_STRING_WITH_TYPES (0x01<<1)
+#define GRN_STRING_WITH_CHECKS (0x01<<2)
+#define GRN_STRING_REMOVE_TOKENIZED_DELIMITER (0x01<<3)
+
+#define GRN_NORMALIZER_AUTO ((grn_obj *)1)
+
+#define GRN_CHAR_BLANK 0x80
+#define GRN_CHAR_IS_BLANK(c) ((c) & (GRN_CHAR_BLANK))
+#define GRN_CHAR_TYPE(c) ((c) & 0x7f)
+
+typedef enum {
+ GRN_CHAR_NULL = 0,
+ GRN_CHAR_ALPHA,
+ GRN_CHAR_DIGIT,
+ GRN_CHAR_SYMBOL,
+ GRN_CHAR_HIRAGANA,
+ GRN_CHAR_KATAKANA,
+ GRN_CHAR_KANJI,
+ GRN_CHAR_OTHERS
+} grn_char_type;
+
+GRN_API grn_obj *grn_string_open(grn_ctx *ctx,
+ const char *string,
+ unsigned int length_in_bytes,
+ grn_obj *normalizer, int flags);
+GRN_API grn_rc grn_string_get_original(grn_ctx *ctx, grn_obj *string,
+ const char **original,
+ unsigned int *length_in_bytes);
+GRN_API int grn_string_get_flags(grn_ctx *ctx, grn_obj *string);
+GRN_API grn_rc grn_string_get_normalized(grn_ctx *ctx, grn_obj *string,
+ const char **normalized,
+ unsigned int *length_in_bytes,
+ unsigned int *n_characters);
+GRN_API grn_rc grn_string_set_normalized(grn_ctx *ctx, grn_obj *string,
+ char *normalized,
+ unsigned int length_in_bytes,
+ unsigned int n_characters);
+GRN_API const short *grn_string_get_checks(grn_ctx *ctx, grn_obj *string);
+GRN_API grn_rc grn_string_set_checks(grn_ctx *ctx,
+ grn_obj *string,
+ short *checks);
+GRN_API const unsigned char *grn_string_get_types(grn_ctx *ctx, grn_obj *string);
+GRN_API grn_rc grn_string_set_types(grn_ctx *ctx,
+ grn_obj *string,
+ unsigned char *types);
+GRN_API grn_encoding grn_string_get_encoding(grn_ctx *ctx, grn_obj *string);
+
+
+GRN_API int grn_charlen(grn_ctx *ctx, const char *str, const char *end);
+
+GRN_API grn_rc grn_ctx_push(grn_ctx *ctx, grn_obj *obj);
+GRN_API grn_obj *grn_ctx_pop(grn_ctx *ctx);
+
+GRN_API grn_obj *grn_table_select(grn_ctx *ctx, grn_obj *table, grn_obj *expr,
+ grn_obj *res, grn_operator op);
+
+GRN_API int grn_obj_columns(grn_ctx *ctx, grn_obj *table,
+ const char *str, unsigned int str_size, grn_obj *res);
+
+GRN_API grn_table_sort_key *grn_table_sort_key_from_str(grn_ctx *ctx,
+ const char *str, unsigned int str_size,
+ grn_obj *table, unsigned int *nkeys);
+GRN_API grn_rc grn_table_sort_key_close(grn_ctx *ctx,
+ grn_table_sort_key *keys, unsigned int nkeys);
+
+GRN_API grn_bool grn_table_is_grouped(grn_ctx *ctx, grn_obj *table);
+
+GRN_API unsigned int grn_table_max_n_subrecs(grn_ctx *ctx, grn_obj *table);
+
+GRN_API grn_obj *grn_table_create_for_group(grn_ctx *ctx,
+ const char *name,
+ unsigned int name_size,
+ const char *path,
+ grn_obj *group_key,
+ grn_obj *value_type,
+ unsigned int max_n_subrecs);
+
+GRN_API unsigned int grn_table_get_subrecs(grn_ctx *ctx, grn_obj *table,
+ grn_id id, grn_id *subrecbuf,
+ int *scorebuf, int buf_size);
+
+GRN_API grn_obj *grn_table_tokenize(grn_ctx *ctx, grn_obj *table,
+ const char *str, unsigned int str_len,
+ grn_obj *buf, grn_bool addp);
+
+GRN_API grn_rc grn_load(grn_ctx *ctx, grn_content_type input_type,
+ const char *table, unsigned int table_len,
+ const char *columns, unsigned int columns_len,
+ const char *values, unsigned int values_len,
+ const char *ifexists, unsigned int ifexists_len,
+ const char *each, unsigned int each_len);
+
+#define GRN_CTX_MORE (0x01<<0)
+#define GRN_CTX_TAIL (0x01<<1)
+#define GRN_CTX_HEAD (0x01<<2)
+#define GRN_CTX_QUIET (0x01<<3)
+#define GRN_CTX_QUIT (0x01<<4)
+
+GRN_API grn_rc grn_ctx_connect(grn_ctx *ctx, const char *host, int port, int flags);
+GRN_API unsigned int grn_ctx_send(grn_ctx *ctx, const char *str, unsigned int str_len, int flags);
+GRN_API unsigned int grn_ctx_recv(grn_ctx *ctx, char **str, unsigned int *str_len, int *flags);
+
+typedef struct _grn_ctx_info grn_ctx_info;
+
+struct _grn_ctx_info {
+ int fd;
+ unsigned int com_status;
+ grn_obj *outbuf;
+ unsigned char stat;
+};
+
+GRN_API grn_rc grn_ctx_info_get(grn_ctx *ctx, grn_ctx_info *info);
+
+GRN_API grn_rc grn_set_segv_handler(void);
+GRN_API grn_rc grn_set_int_handler(void);
+GRN_API grn_rc grn_set_term_handler(void);
+
+/* hash */
+
+typedef struct _grn_hash grn_hash;
+typedef struct _grn_hash_cursor grn_hash_cursor;
+
+GRN_API grn_hash *grn_hash_create(grn_ctx *ctx, const char *path, unsigned int key_size,
+ unsigned int value_size, unsigned int flags);
+
+GRN_API grn_hash *grn_hash_open(grn_ctx *ctx, const char *path);
+
+GRN_API grn_rc grn_hash_close(grn_ctx *ctx, grn_hash *hash);
+
+GRN_API grn_id grn_hash_add(grn_ctx *ctx, grn_hash *hash, const void *key,
+ unsigned int key_size, void **value, int *added);
+GRN_API grn_id grn_hash_get(grn_ctx *ctx, grn_hash *hash, const void *key,
+ unsigned int key_size, void **value);
+
+GRN_API int grn_hash_get_key(grn_ctx *ctx, grn_hash *hash, grn_id id, void *keybuf, int bufsize);
+GRN_API int grn_hash_get_key2(grn_ctx *ctx, grn_hash *hash, grn_id id, grn_obj *bulk);
+GRN_API int grn_hash_get_value(grn_ctx *ctx, grn_hash *hash, grn_id id, void *valuebuf);
+GRN_API grn_rc grn_hash_set_value(grn_ctx *ctx, grn_hash *hash, grn_id id,
+ const void *value, int flags);
+
+typedef struct _grn_table_delete_optarg grn_table_delete_optarg;
+
+struct _grn_table_delete_optarg {
+ int flags;
+ int (*func)(grn_ctx *ctx, grn_obj *, grn_id, void *);
+ void *func_arg;
+};
+
+GRN_API grn_rc grn_hash_delete_by_id(grn_ctx *ctx, grn_hash *hash, grn_id id,
+ grn_table_delete_optarg *optarg);
+GRN_API grn_rc grn_hash_delete(grn_ctx *ctx, grn_hash *hash,
+ const void *key, unsigned int key_size,
+ grn_table_delete_optarg *optarg);
+
+GRN_API grn_hash_cursor *grn_hash_cursor_open(grn_ctx *ctx, grn_hash *hash,
+ const void *min, unsigned int min_size,
+ const void *max, unsigned int max_size,
+ int offset, int limit, int flags);
+GRN_API grn_id grn_hash_cursor_next(grn_ctx *ctx, grn_hash_cursor *c);
+GRN_API void grn_hash_cursor_close(grn_ctx *ctx, grn_hash_cursor *c);
+
+GRN_API int grn_hash_cursor_get_key(grn_ctx *ctx, grn_hash_cursor *c, void **key);
+GRN_API int grn_hash_cursor_get_value(grn_ctx *ctx, grn_hash_cursor *c, void **value);
+GRN_API grn_rc grn_hash_cursor_set_value(grn_ctx *ctx, grn_hash_cursor *c,
+ const void *value, int flags);
+
+GRN_API int grn_hash_cursor_get_key_value(grn_ctx *ctx, grn_hash_cursor *c,
+ void **key, unsigned int *key_size, void **value);
+
+GRN_API grn_rc grn_hash_cursor_delete(grn_ctx *ctx, grn_hash_cursor *c,
+ grn_table_delete_optarg *optarg);
+
+#define GRN_HASH_EACH(ctx,hash,id,key,key_size,value,block) do {\
+ grn_hash_cursor *_sc = grn_hash_cursor_open(ctx, hash, NULL, 0, NULL, 0, 0, -1, 0); \
+ if (_sc) {\
+ grn_id id;\
+ while ((id = grn_hash_cursor_next(ctx, _sc))) {\
+ grn_hash_cursor_get_key_value(ctx, _sc, (void **)(key),\
+ (key_size), (void **)(value));\
+ block\
+ }\
+ grn_hash_cursor_close(ctx, _sc);\
+ }\
+} while (0)
+
+/* array */
+
+typedef struct _grn_array grn_array;
+typedef struct _grn_array_cursor grn_array_cursor;
+
+GRN_API grn_array *grn_array_create(grn_ctx *ctx, const char *path,
+ unsigned int value_size, unsigned int flags);
+GRN_API grn_array *grn_array_open(grn_ctx *ctx, const char *path);
+GRN_API grn_rc grn_array_close(grn_ctx *ctx, grn_array *array);
+GRN_API grn_id grn_array_add(grn_ctx *ctx, grn_array *array, void **value);
+GRN_API grn_id grn_array_push(grn_ctx *ctx, grn_array *array,
+ void (*func)(grn_ctx *ctx, grn_array *array,
+ grn_id id, void *func_arg),
+ void *func_arg);
+GRN_API grn_id grn_array_pull(grn_ctx *ctx, grn_array *array, grn_bool blockp,
+ void (*func)(grn_ctx *ctx, grn_array *array,
+ grn_id id, void *func_arg),
+ void *func_arg);
+GRN_API void grn_array_unblock(grn_ctx *ctx, grn_array *array);
+GRN_API int grn_array_get_value(grn_ctx *ctx, grn_array *array, grn_id id, void *valuebuf);
+GRN_API grn_rc grn_array_set_value(grn_ctx *ctx, grn_array *array, grn_id id,
+ const void *value, int flags);
+GRN_API grn_array_cursor *grn_array_cursor_open(grn_ctx *ctx, grn_array *array,
+ grn_id min, grn_id max,
+ int offset, int limit, int flags);
+GRN_API grn_id grn_array_cursor_next(grn_ctx *ctx, grn_array_cursor *cursor);
+GRN_API int grn_array_cursor_get_value(grn_ctx *ctx, grn_array_cursor *cursor, void **value);
+GRN_API grn_rc grn_array_cursor_set_value(grn_ctx *ctx, grn_array_cursor *cursor,
+ const void *value, int flags);
+GRN_API grn_rc grn_array_cursor_delete(grn_ctx *ctx, grn_array_cursor *cursor,
+ grn_table_delete_optarg *optarg);
+GRN_API void grn_array_cursor_close(grn_ctx *ctx, grn_array_cursor *cursor);
+GRN_API grn_rc grn_array_delete_by_id(grn_ctx *ctx, grn_array *array, grn_id id,
+ grn_table_delete_optarg *optarg);
+
+GRN_API grn_id grn_array_next(grn_ctx *ctx, grn_array *array, grn_id id);
+
+GRN_API void *_grn_array_get_value(grn_ctx *ctx, grn_array *array, grn_id id);
+
+#define GRN_ARRAY_EACH(ctx,array,head,tail,id,value,block) do {\
+ grn_array_cursor *_sc = grn_array_cursor_open(ctx, array, head, tail, 0, -1, 0); \
+ if (_sc) {\
+ grn_id id;\
+ while ((id = grn_array_cursor_next(ctx, _sc))) {\
+ grn_array_cursor_get_value(ctx, _sc, (void **)(value));\
+ block\
+ }\
+ grn_array_cursor_close(ctx, _sc); \
+ }\
+} while (0)
+
+/* pat */
+
+typedef struct _grn_pat grn_pat;
+typedef struct _grn_pat_cursor grn_pat_cursor;
+
+GRN_API grn_pat *grn_pat_create(grn_ctx *ctx, const char *path, unsigned int key_size,
+ unsigned int value_size, unsigned int flags);
+
+GRN_API grn_pat *grn_pat_open(grn_ctx *ctx, const char *path);
+
+GRN_API grn_rc grn_pat_close(grn_ctx *ctx, grn_pat *pat);
+
+GRN_API grn_rc grn_pat_remove(grn_ctx *ctx, const char *path);
+
+GRN_API grn_id grn_pat_get(grn_ctx *ctx, grn_pat *pat, const void *key,
+ unsigned int key_size, void **value);
+GRN_API grn_id grn_pat_add(grn_ctx *ctx, grn_pat *pat, const void *key,
+ unsigned int key_size, void **value, int *added);
+
+GRN_API int grn_pat_get_key(grn_ctx *ctx, grn_pat *pat, grn_id id, void *keybuf, int bufsize);
+GRN_API int grn_pat_get_key2(grn_ctx *ctx, grn_pat *pat, grn_id id, grn_obj *bulk);
+GRN_API int grn_pat_get_value(grn_ctx *ctx, grn_pat *pat, grn_id id, void *valuebuf);
+GRN_API grn_rc grn_pat_set_value(grn_ctx *ctx, grn_pat *pat, grn_id id,
+ const void *value, int flags);
+
+GRN_API grn_rc grn_pat_delete_by_id(grn_ctx *ctx, grn_pat *pat, grn_id id,
+ grn_table_delete_optarg *optarg);
+GRN_API grn_rc grn_pat_delete(grn_ctx *ctx, grn_pat *pat, const void *key, unsigned int key_size,
+ grn_table_delete_optarg *optarg);
+GRN_API int grn_pat_delete_with_sis(grn_ctx *ctx, grn_pat *pat, grn_id id,
+ grn_table_delete_optarg *optarg);
+
+typedef struct _grn_table_scan_hit grn_pat_scan_hit;
+typedef struct _grn_table_scan_hit grn_dat_scan_hit;
+
+struct _grn_table_scan_hit {
+ grn_id id;
+ unsigned int offset;
+ unsigned int length;
+};
+
+GRN_API int grn_pat_scan(grn_ctx *ctx, grn_pat *pat, const char *str, unsigned int str_len,
+ grn_pat_scan_hit *sh, unsigned int sh_size, const char **rest);
+
+GRN_API grn_rc grn_pat_prefix_search(grn_ctx *ctx, grn_pat *pat,
+ const void *key, unsigned int key_size, grn_hash *h);
+GRN_API grn_rc grn_pat_suffix_search(grn_ctx *ctx, grn_pat *pat,
+ const void *key, unsigned int key_size, grn_hash *h);
+GRN_API grn_id grn_pat_lcp_search(grn_ctx *ctx, grn_pat *pat,
+ const void *key, unsigned int key_size);
+
+GRN_API unsigned int grn_pat_size(grn_ctx *ctx, grn_pat *pat);
+
+GRN_API grn_pat_cursor *grn_pat_cursor_open(grn_ctx *ctx, grn_pat *pat,
+ const void *min, unsigned int min_size,
+ const void *max, unsigned int max_size,
+ int offset, int limit, int flags);
+GRN_API grn_id grn_pat_cursor_next(grn_ctx *ctx, grn_pat_cursor *c);
+GRN_API void grn_pat_cursor_close(grn_ctx *ctx, grn_pat_cursor *c);
+
+GRN_API int grn_pat_cursor_get_key(grn_ctx *ctx, grn_pat_cursor *c, void **key);
+GRN_API int grn_pat_cursor_get_value(grn_ctx *ctx, grn_pat_cursor *c, void **value);
+
+GRN_API int grn_pat_cursor_get_key_value(grn_ctx *ctx, grn_pat_cursor *c,
+ void **key, unsigned int *key_size, void **value);
+GRN_API grn_rc grn_pat_cursor_set_value(grn_ctx *ctx, grn_pat_cursor *c,
+ const void *value, int flags);
+GRN_API grn_rc grn_pat_cursor_delete(grn_ctx *ctx, grn_pat_cursor *c,
+ grn_table_delete_optarg *optarg);
+
+#define GRN_PAT_EACH(ctx,pat,id,key,key_size,value,block) do { \
+ grn_pat_cursor *_sc = grn_pat_cursor_open(ctx, pat, NULL, 0, NULL, 0, 0, -1, 0); \
+ if (_sc) {\
+ grn_id id;\
+ while ((id = grn_pat_cursor_next(ctx, _sc))) {\
+ grn_pat_cursor_get_key_value(ctx, _sc, (void **)(key),\
+ (key_size), (void **)(value));\
+ block\
+ }\
+ grn_pat_cursor_close(ctx, _sc);\
+ }\
+} while (0)
+
+/* dat */
+
+typedef struct _grn_dat grn_dat;
+typedef struct _grn_dat_cursor grn_dat_cursor;
+
+GRN_API int grn_dat_scan(grn_ctx *ctx, grn_dat *dat, const char *str,
+ unsigned int str_size, grn_dat_scan_hit *scan_hits,
+ unsigned int max_num_scan_hits, const char **str_rest);
+
+GRN_API grn_id grn_dat_lcp_search(grn_ctx *ctx, grn_dat *dat,
+ const void *key, unsigned int key_size);
+
+GRN_API grn_dat *grn_dat_create(grn_ctx *ctx, const char *path, unsigned int key_size,
+ unsigned int value_size, unsigned int flags);
+
+GRN_API grn_dat *grn_dat_open(grn_ctx *ctx, const char *path);
+
+GRN_API grn_rc grn_dat_close(grn_ctx *ctx, grn_dat *dat);
+
+GRN_API grn_rc grn_dat_remove(grn_ctx *ctx, const char *path);
+
+GRN_API grn_id grn_dat_get(grn_ctx *ctx, grn_dat *dat, const void *key,
+ unsigned int key_size, void **value);
+GRN_API grn_id grn_dat_add(grn_ctx *ctx, grn_dat *dat, const void *key,
+ unsigned int key_size, void **value, int *added);
+
+GRN_API int grn_dat_get_key(grn_ctx *ctx, grn_dat *dat, grn_id id, void *keybuf, int bufsize);
+GRN_API int grn_dat_get_key2(grn_ctx *ctx, grn_dat *dat, grn_id id, grn_obj *bulk);
+
+GRN_API grn_rc grn_dat_delete_by_id(grn_ctx *ctx, grn_dat *dat, grn_id id,
+ grn_table_delete_optarg *optarg);
+GRN_API grn_rc grn_dat_delete(grn_ctx *ctx, grn_dat *dat, const void *key, unsigned int key_size,
+ grn_table_delete_optarg *optarg);
+
+GRN_API grn_rc grn_dat_update_by_id(grn_ctx *ctx, grn_dat *dat, grn_id src_key_id,
+ const void *dest_key, unsigned int dest_key_size);
+GRN_API grn_rc grn_dat_update(grn_ctx *ctx, grn_dat *dat,
+ const void *src_key, unsigned int src_key_size,
+ const void *dest_key, unsigned int dest_key_size);
+
+GRN_API unsigned int grn_dat_size(grn_ctx *ctx, grn_dat *dat);
+
+GRN_API grn_dat_cursor *grn_dat_cursor_open(grn_ctx *ctx, grn_dat *dat,
+ const void *min, unsigned int min_size,
+ const void *max, unsigned int max_size,
+ int offset, int limit, int flags);
+GRN_API grn_id grn_dat_cursor_next(grn_ctx *ctx, grn_dat_cursor *c);
+GRN_API void grn_dat_cursor_close(grn_ctx *ctx, grn_dat_cursor *c);
+
+GRN_API int grn_dat_cursor_get_key(grn_ctx *ctx, grn_dat_cursor *c, const void **key);
+GRN_API grn_rc grn_dat_cursor_delete(grn_ctx *ctx, grn_dat_cursor *c,
+ grn_table_delete_optarg *optarg);
+
+#define GRN_DAT_EACH(ctx,dat,id,key,key_size,block) do {\
+ grn_dat_cursor *_sc = grn_dat_cursor_open(ctx, dat, NULL, 0, NULL, 0, 0, -1, 0);\
+ if (_sc) {\
+ grn_id id;\
+ unsigned int *_ks = (key_size);\
+ if (_ks) {\
+ while ((id = grn_dat_cursor_next(ctx, _sc))) {\
+ int _ks_raw = grn_dat_cursor_get_key(ctx, _sc, (const void **)(key));\
+ *(_ks) = (unsigned int)_ks_raw;\
+ block\
+ }\
+ } else {\
+ while ((id = grn_dat_cursor_next(ctx, _sc))) {\
+ grn_dat_cursor_get_key(ctx, _sc, (const void **)(key));\
+ block\
+ }\
+ }\
+ grn_dat_cursor_close(ctx, _sc);\
+ }\
+} while (0)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GROONGA_GROONGA_H */
diff --git a/storage/mroonga/vendor/groonga/include/groonga/ii.h b/storage/mroonga/vendor/groonga/include/groonga/ii.h
new file mode 100644
index 00000000000..1bd8ce25309
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/include/groonga/ii.h
@@ -0,0 +1,46 @@
+/*
+ Copyright(C) 2009-2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#ifndef GROONGA_II_H
+#define GROONGA_II_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* buffered index builder */
+
+typedef struct _grn_ii grn_ii;
+typedef struct _grn_ii_buffer grn_ii_buffer;
+
+GRN_API unsigned int grn_ii_estimate_size(grn_ctx *ctx, grn_ii *ii, grn_id tid);
+
+GRN_API grn_ii_buffer *grn_ii_buffer_open(grn_ctx *ctx, grn_ii *ii,
+ long long unsigned int update_buffer_size);
+GRN_API grn_rc grn_ii_buffer_append(grn_ctx *ctx,
+ grn_ii_buffer *ii_buffer,
+ grn_id rid,
+ unsigned int section,
+ grn_obj *value);
+GRN_API grn_rc grn_ii_buffer_commit(grn_ctx *ctx, grn_ii_buffer *ii_buffer);
+GRN_API grn_rc grn_ii_buffer_close(grn_ctx *ctx, grn_ii_buffer *ii_buffer);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GROONGA_II_H */
diff --git a/storage/mroonga/vendor/groonga/include/groonga/nfkc.h b/storage/mroonga/vendor/groonga/include/groonga/nfkc.h
index 3b7e294fb97..f4e628de53c 100644
--- a/storage/mroonga/vendor/groonga/include/groonga/nfkc.h
+++ b/storage/mroonga/vendor/groonga/include/groonga/nfkc.h
@@ -14,8 +14,8 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef GRN_NFKC_H
-#define GRN_NFKC_H
+#ifndef GROONGA_NFKC_H
+#define GROONGA_NFKC_H
#include <groonga.h>
@@ -29,4 +29,4 @@ GRN_API grn_char_type grn_nfkc_char_type(const unsigned char *str);
}
#endif
-#endif /* GRN_NFKC_H */
+#endif /* GROONGA_NFKC_H */
diff --git a/storage/mroonga/vendor/groonga/include/groonga/obj.h b/storage/mroonga/vendor/groonga/include/groonga/obj.h
new file mode 100644
index 00000000000..7544a6cb382
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/include/groonga/obj.h
@@ -0,0 +1,37 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2015 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#ifndef GROONGA_OBJ_H
+#define GROONGA_OBJ_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+GRN_API grn_bool grn_obj_is_builtin(grn_ctx *ctx, grn_obj *obj);
+GRN_API grn_bool grn_obj_is_table(grn_ctx *ctx, grn_obj *obj);
+GRN_API grn_bool grn_obj_is_proc(grn_ctx *ctx, grn_obj *obj);
+GRN_API grn_bool grn_obj_is_function_proc(grn_ctx *ctx, grn_obj *obj);
+GRN_API grn_bool grn_obj_is_selector_proc(grn_ctx *ctx, grn_obj *obj);
+GRN_API grn_bool grn_obj_is_scorer_proc(grn_ctx *ctx, grn_obj *obj);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GROONGA_OBJ_H */
diff --git a/storage/mroonga/vendor/groonga/include/groonga/output.h b/storage/mroonga/vendor/groonga/include/groonga/output.h
new file mode 100644
index 00000000000..fc23bb2db01
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/include/groonga/output.h
@@ -0,0 +1,108 @@
+/*
+ Copyright(C) 2009-2015 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#ifndef GROONGA_OUTPUT_H
+#define GROONGA_OUTPUT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _grn_obj_format grn_obj_format;
+
+#define GRN_OBJ_FORMAT_WITH_COLUMN_NAMES (0x01<<0)
+#define GRN_OBJ_FORMAT_AS_ARRAY (0x01<<3)
+/* Deprecated since 4.0.1. It will be removed at 5.0.0.
+ Use GRN_OBJ_FORMAT_AS_ARRAY instead.*/
+#define GRN_OBJ_FORMAT_ASARRAY GRN_OBJ_FORMAT_AS_ARRAY
+#define GRN_OBJ_FORMAT_WITH_WEIGHT (0x01<<4)
+
+struct _grn_obj_format {
+ grn_obj columns;
+ const void *min;
+ const void *max;
+ unsigned int min_size;
+ unsigned int max_size;
+ int nhits;
+ int offset;
+ int limit;
+ int hits_offset;
+ int flags;
+ grn_obj *expression;
+};
+
+#define GRN_OBJ_FORMAT_INIT(format,format_nhits,format_offset,format_limit,format_hits_offset) do { \
+ GRN_PTR_INIT(&(format)->columns, GRN_OBJ_VECTOR, GRN_ID_NIL);\
+ (format)->nhits = (format_nhits);\
+ (format)->offset = (format_offset);\
+ (format)->limit = (format_limit);\
+ (format)->hits_offset = (format_hits_offset);\
+ (format)->flags = 0;\
+ (format)->expression = NULL;\
+} while (0)
+
+#define GRN_OBJ_FORMAT_FIN(ctx,format) do {\
+ int ncolumns = GRN_BULK_VSIZE(&(format)->columns) / sizeof(grn_obj *);\
+ grn_obj **columns = (grn_obj **)GRN_BULK_HEAD(&(format)->columns);\
+ while (ncolumns--) { grn_obj_unlink((ctx), *columns++); }\
+ GRN_OBJ_FIN((ctx), &(format)->columns);\
+ if ((format)->expression) { GRN_OBJ_FIN((ctx), (format)->expression); } \
+} while (0)
+
+GRN_API void grn_output_obj(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type,
+ grn_obj *obj, grn_obj_format *format);
+GRN_API void grn_output_envelope(grn_ctx *ctx, grn_rc rc,
+ grn_obj *head, grn_obj *body, grn_obj *foot,
+ const char *file, int line);
+
+GRN_API void grn_ctx_output_flush(grn_ctx *ctx, int flags);
+GRN_API void grn_ctx_output_array_open(grn_ctx *ctx,
+ const char *name, int nelements);
+GRN_API void grn_ctx_output_array_close(grn_ctx *ctx);
+GRN_API void grn_ctx_output_map_open(grn_ctx *ctx,
+ const char *name, int nelements);
+GRN_API void grn_ctx_output_map_close(grn_ctx *ctx);
+GRN_API void grn_ctx_output_int32(grn_ctx *ctx, int value);
+GRN_API void grn_ctx_output_int64(grn_ctx *ctx, long long int value);
+GRN_API void grn_ctx_output_float(grn_ctx *ctx, double value);
+GRN_API void grn_ctx_output_cstr(grn_ctx *ctx, const char *value);
+GRN_API void grn_ctx_output_str(grn_ctx *ctx,
+ const char *value, unsigned int value_len);
+GRN_API void grn_ctx_output_bool(grn_ctx *ctx, grn_bool value);
+GRN_API void grn_ctx_output_obj(grn_ctx *ctx,
+ grn_obj *value, grn_obj_format *format);
+GRN_API void grn_ctx_output_table_columns(grn_ctx *ctx,
+ grn_obj *table,
+ grn_obj_format *format);
+GRN_API void grn_ctx_output_table_records(grn_ctx *ctx,
+ grn_obj *table,
+ grn_obj_format *format);
+
+
+GRN_API grn_content_type grn_ctx_get_output_type(grn_ctx *ctx);
+GRN_API grn_rc grn_ctx_set_output_type(grn_ctx *ctx, grn_content_type type);
+GRN_API const char *grn_ctx_get_mime_type(grn_ctx *ctx);
+
+/* obsolete */
+GRN_API grn_rc grn_text_otoj(grn_ctx *ctx, grn_obj *bulk, grn_obj *obj,
+ grn_obj_format *format);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GROONGA_OUTPUT_H */
diff --git a/storage/mroonga/vendor/groonga/include/groonga/plugin.h b/storage/mroonga/vendor/groonga/include/groonga/plugin.h
index 98676acf6be..bbd8923e5d6 100644
--- a/storage/mroonga/vendor/groonga/include/groonga/plugin.h
+++ b/storage/mroonga/vendor/groonga/include/groonga/plugin.h
@@ -15,8 +15,8 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef GRN_PLUGIN_H
-#define GRN_PLUGIN_H
+#ifndef GROONGA_PLUGIN_H
+#define GROONGA_PLUGIN_H
#include <stddef.h>
@@ -26,9 +26,24 @@
extern "C" {
#endif
-#define GRN_PLUGIN_INIT grn_plugin_impl_init
-#define GRN_PLUGIN_REGISTER grn_plugin_impl_register
-#define GRN_PLUGIN_FIN grn_plugin_impl_fin
+# define GRN_PLUGIN_IMPL_NAME_RAW(type) \
+ grn_plugin_impl_ ## type
+# define GRN_PLUGIN_IMPL_NAME_TAGGED(type, tag) \
+ GRN_PLUGIN_IMPL_NAME_RAW(type ## _ ## tag)
+# define GRN_PLUGIN_IMPL_NAME_TAGGED_EXPANDABLE(type, tag) \
+ GRN_PLUGIN_IMPL_NAME_TAGGED(type, tag)
+
+#ifdef GRN_PLUGIN_FUNCTION_TAG
+# define GRN_PLUGIN_IMPL_NAME(type) \
+ GRN_PLUGIN_IMPL_NAME_TAGGED_EXPANDABLE(type, GRN_PLUGIN_FUNCTION_TAG)
+#else /* GRN_PLUGIN_FUNCTION_TAG */
+# define GRN_PLUGIN_IMPL_NAME(type) \
+ GRN_PLUGIN_IMPL_NAME_RAW(type)
+#endif /* GRN_PLUGIN_FUNCTION_TAG */
+
+#define GRN_PLUGIN_INIT GRN_PLUGIN_IMPL_NAME(init)
+#define GRN_PLUGIN_REGISTER GRN_PLUGIN_IMPL_NAME(register)
+#define GRN_PLUGIN_FIN GRN_PLUGIN_IMPL_NAME(fin)
#if defined(_WIN32) || defined(_WIN64)
# define GRN_PLUGIN_EXPORT __declspec(dllexport)
@@ -117,6 +132,8 @@ GRN_API void grn_plugin_mutex_unlock(grn_ctx *ctx, grn_plugin_mutex *mutex);
GRN_API grn_obj *grn_plugin_proc_alloc(grn_ctx *ctx, grn_user_data *user_data,
grn_id domain, grn_obj_flags flags);
+GRN_API grn_obj *grn_plugin_proc_get_vars(grn_ctx *ctx, grn_user_data *user_data);
+
GRN_API grn_obj *grn_plugin_proc_get_var(grn_ctx *ctx, grn_user_data *user_data,
const char *name, int name_size);
@@ -149,4 +166,4 @@ GRN_API grn_obj * grn_plugin_command_create(grn_ctx *ctx,
}
#endif
-#endif /* GRN_PLUGIN_H */
+#endif /* GROONGA_PLUGIN_H */
diff --git a/storage/mroonga/vendor/groonga/include/groonga/request_canceler.h b/storage/mroonga/vendor/groonga/include/groonga/request_canceler.h
new file mode 100644
index 00000000000..0032a778c25
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/include/groonga/request_canceler.h
@@ -0,0 +1,39 @@
+/*
+ Copyright(C) 2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef GROONGA_REQUEST_CANCELER_H
+#define GROONGA_REQUEST_CANCELER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+GRN_API void grn_request_canceler_register(grn_ctx *ctx,
+ const char *request_id,
+ unsigned int size);
+GRN_API void grn_request_canceler_unregister(grn_ctx *ctx,
+ const char *request_id,
+ unsigned int size);
+GRN_API grn_bool grn_request_canceler_cancel(const char *request_id,
+ unsigned int size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GROONGA_REQUEST_CANCELER_H */
diff --git a/storage/mroonga/vendor/groonga/include/groonga/scorer.h b/storage/mroonga/vendor/groonga/include/groonga/scorer.h
new file mode 100644
index 00000000000..a50d0d8cd71
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/include/groonga/scorer.h
@@ -0,0 +1,88 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2015 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#ifndef GROONGA_SCORER_H
+#define GROONGA_SCORER_H
+
+#include <groonga/plugin.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _grn_scorer_matched_record grn_scorer_matched_record;
+
+GRN_API grn_obj *
+ grn_scorer_matched_record_get_table(grn_ctx *ctx,
+ grn_scorer_matched_record *record);
+GRN_API grn_obj *
+ grn_scorer_matched_record_get_lexicon(grn_ctx *ctx,
+ grn_scorer_matched_record *record);
+GRN_API grn_id
+ grn_scorer_matched_record_get_id(grn_ctx *ctx,
+ grn_scorer_matched_record *record);
+GRN_API grn_obj *
+ grn_scorer_matched_record_get_terms(grn_ctx *ctx,
+ grn_scorer_matched_record *record);
+GRN_API grn_obj *
+ grn_scorer_matched_record_get_term_weights(grn_ctx *ctx,
+ grn_scorer_matched_record *record);
+GRN_API unsigned int
+ grn_scorer_matched_record_get_total_term_weights(grn_ctx *ctx,
+ grn_scorer_matched_record *record);
+GRN_API long long unsigned int
+ grn_scorer_matched_record_get_n_documents(grn_ctx *ctx,
+ grn_scorer_matched_record *record);
+GRN_API unsigned int
+ grn_scorer_matched_record_get_n_occurrences(grn_ctx *ctx,
+ grn_scorer_matched_record *record);
+GRN_API long long unsigned int
+ grn_scorer_matched_record_get_n_candidates(grn_ctx *ctx,
+ grn_scorer_matched_record *record);
+GRN_API unsigned int
+ grn_scorer_matched_record_get_n_tokens(grn_ctx *ctx,
+ grn_scorer_matched_record *record);
+GRN_API int
+ grn_scorer_matched_record_get_weight(grn_ctx *ctx,
+ grn_scorer_matched_record *record);
+
+
+
+typedef double grn_scorer_score_func(grn_ctx *ctx,
+ grn_scorer_matched_record *record);
+
+/*
+ grn_scorer_register() registers a plugin to the database which is
+ associated with `ctx'. `plugin_name_ptr' and `plugin_name_length' specify the
+ plugin name. Alphabetic letters ('A'-'Z' and 'a'-'z'), digits ('0'-'9') and
+ an underscore ('_') are capable characters.
+
+ `score' is called for scoring matched records one by one.
+
+ grn_scorer_register() returns GRN_SUCCESS on success, an error
+ code on failure.
+ */
+GRN_PLUGIN_EXPORT grn_rc grn_scorer_register(grn_ctx *ctx,
+ const char *plugin_name_ptr,
+ int plugin_name_length,
+ grn_scorer_score_func *score);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* GROONGA_SCORER_H */
diff --git a/storage/mroonga/vendor/groonga/include/groonga/token.h b/storage/mroonga/vendor/groonga/include/groonga/token.h
new file mode 100644
index 00000000000..5aeaf0b4361
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/include/groonga/token.h
@@ -0,0 +1,136 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#ifndef GROONGA_TOKEN_H
+#define GROONGA_TOKEN_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * grn_tokenize_mode describes propose for tokenization.
+ *
+ * `GRN_TOKENIZE_GET`: Tokenize for search.
+ *
+ * `GRN_TOKENIZE_ADD`: Tokenize for adding token to index.
+ *
+ * `GRN_TOKENIZE_DELETE`: Tokenize for deleting token from index.
+ *
+ * @since 4.0.8
+ */
+typedef enum {
+ GRN_TOKENIZE_GET = 0,
+ GRN_TOKENIZE_ADD,
+ GRN_TOKENIZE_DELETE
+} grn_tokenize_mode;
+
+/*
+ grn_token_mode describes propose for tokenization.
+
+ `GRN_TOKEN_GET`: Tokenization for search.
+
+ `GRN_TOKEN_ADD`: Tokenization for adding token to index.
+
+ `GRN_TOKEN_DEL`: Tokenization for deleting token from index.
+
+ @since 4.0.7
+ @deprecated since 4.0.8. Use grn_tokenize_mode instead.
+ */
+typedef grn_tokenize_mode grn_token_mode;
+
+#define GRN_TOKEN_GET GRN_TOKENIZE_GET
+#define GRN_TOKEN_ADD GRN_TOKENIZE_ADD
+#define GRN_TOKEN_DEL GRN_TOKENIZE_DELETE
+
+/*
+ * grn_token_status is a flag set for tokenizer status codes.
+ * If a document or query contains no tokens, push an empty string with
+ * GRN_TOKEN_LAST as a token.
+ *
+ * @since 4.0.8
+ */
+typedef unsigned int grn_token_status;
+
+/*
+ * GRN_TOKEN_CONTINUE means that the next token is not the last one.
+ *
+ * @since 4.0.8
+ */
+#define GRN_TOKEN_CONTINUE (0)
+/*
+ * GRN_TOKEN_LAST means that the next token is the last one.
+ *
+ * @since 4.0.8
+ */
+#define GRN_TOKEN_LAST (0x01L<<0)
+/*
+ * GRN_TOKEN_OVERLAP means that ...
+ *
+ * @since 4.0.8
+ */
+#define GRN_TOKEN_OVERLAP (0x01L<<1)
+/*
+ * GRN_TOKEN_UNMATURED means that ...
+ *
+ * @since 4.0.8
+ */
+#define GRN_TOKEN_UNMATURED (0x01L<<2)
+/*
+ * GRN_TOKEN_REACH_END means that ...
+ *
+ * @since 4.0.8
+ */
+#define GRN_TOKEN_REACH_END (0x01L<<3)
+/*
+ * GRN_TOKEN_SKIP means that the token is skipped
+ *
+ * @since 4.0.8
+ */
+#define GRN_TOKEN_SKIP (0x01L<<4)
+/*
+ * GRN_TOKEN_SKIP_WITH_POSITION means that the token and postion is skipped
+ *
+ * @since 4.0.8
+ */
+#define GRN_TOKEN_SKIP_WITH_POSITION (0x01L<<5)
+/*
+ * GRN_TOKEN_FORCE_PREIX that the token is used common prefix search
+ *
+ * @since 4.0.8
+ */
+#define GRN_TOKEN_FORCE_PREFIX (0x01L<<6)
+
+typedef struct _grn_token grn_token;
+
+GRN_PLUGIN_EXPORT grn_obj *grn_token_get_data(grn_ctx *ctx,
+ grn_token *token);
+GRN_PLUGIN_EXPORT grn_rc grn_token_set_data(grn_ctx *ctx,
+ grn_token *token,
+ const char *str_ptr,
+ int str_length);
+GRN_PLUGIN_EXPORT grn_token_status grn_token_get_status(grn_ctx *ctx,
+ grn_token *token);
+GRN_PLUGIN_EXPORT grn_rc grn_token_set_status(grn_ctx *ctx,
+ grn_token *token,
+ grn_token_status status);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* GROONGA_TOKEN_H */
diff --git a/storage/mroonga/vendor/groonga/include/groonga/token_filter.h b/storage/mroonga/vendor/groonga/include/groonga/token_filter.h
index 2ae553b8630..9c5a3567b3b 100644
--- a/storage/mroonga/vendor/groonga/include/groonga/token_filter.h
+++ b/storage/mroonga/vendor/groonga/include/groonga/token_filter.h
@@ -15,10 +15,8 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef GRN_PLUGIN_TOKEN_FILTER_H
-#define GRN_PLUGIN_TOKEN_FILTER_H
-
-#include <stddef.h>
+#ifndef GROONGA_TOKEN_FILTER_H
+#define GROONGA_TOKEN_FILTER_H
#include <groonga/tokenizer.h>
@@ -28,7 +26,7 @@ extern "C" {
typedef void *grn_token_filter_init_func(grn_ctx *ctx,
grn_obj *table,
- grn_token_mode mode);
+ grn_tokenize_mode mode);
typedef void grn_token_filter_filter_func(grn_ctx *ctx,
grn_token *current_token,
@@ -68,4 +66,4 @@ GRN_PLUGIN_EXPORT grn_rc grn_token_filter_register(grn_ctx *ctx,
} /* extern "C" */
#endif /* __cplusplus */
-#endif /* GRN_PLUGIN_TOKEN_FILTER_H */
+#endif /* GROONGA_TOKEN_FILTER_H */
diff --git a/storage/mroonga/vendor/groonga/include/groonga/tokenizer.h b/storage/mroonga/vendor/groonga/include/groonga/tokenizer.h
index 9792e018b31..8ad7f6757f4 100644
--- a/storage/mroonga/vendor/groonga/include/groonga/tokenizer.h
+++ b/storage/mroonga/vendor/groonga/include/groonga/tokenizer.h
@@ -15,12 +15,11 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef GRN_PLUGIN_TOKENIZER_H
-#define GRN_PLUGIN_TOKENIZER_H
-
-#include <stddef.h>
+#ifndef GROONGA_TOKENIZER_H
+#define GROONGA_TOKENIZER_H
#include <groonga/plugin.h>
+#include <groonga/token.h>
#ifdef __cplusplus
extern "C" {
@@ -30,23 +29,6 @@ extern "C" {
#define GRN_TOKENIZER_TOKENIZED_DELIMITER_UTF8_LEN 3
/*
- grn_token_mode describes propose for tokenization.
-
- `GRN_TOKEN_GET`: Tokenization for search.
-
- `GRN_TOKEN_ADD`: Tokenization for adding token to index.
-
- `GRN_TOKEN_DEL`: Tokenization for deleting token from index.
-
- @since 4.0.7
- */
-typedef enum {
- GRN_TOKEN_GET = 0,
- GRN_TOKEN_ADD,
- GRN_TOKEN_DEL
-} grn_token_mode;
-
-/*
grn_tokenizer_charlen() returns the length (#bytes) of the first character
in the string specified by `str_ptr' and `str_length'. If the starting bytes
are invalid as a character, grn_tokenizer_charlen() returns 0. See
@@ -101,7 +83,9 @@ struct _grn_tokenizer_query {
grn_encoding encoding;
unsigned int flags;
grn_bool have_tokenized_delimiter;
+ /* Deprecated since 4.0.8. Use tokenize_mode instead. */
grn_token_mode token_mode;
+ grn_tokenize_mode tokenize_mode;
};
/*
@@ -166,23 +150,59 @@ GRN_PLUGIN_EXPORT void grn_tokenizer_token_fin(grn_ctx *ctx, grn_tokenizer_token
* grn_tokenizer_status is a flag set for tokenizer status codes.
* If a document or query contains no tokens, push an empty string with
* GRN_TOKENIZER_TOKEN_LAST as a token.
+ *
+ * @deprecated since 4.0.8. Use grn_token_status instead.
+ */
+typedef grn_token_status grn_tokenizer_status;
+
+/*
+ * GRN_TOKENIZER_TOKEN_CONTINUE means that the next token is not the last one.
+ *
+ * @deprecated since 4.0.8. Use GRN_TOKEN_CONTINUE instead.
+ */
+#define GRN_TOKENIZER_TOKEN_CONTINUE GRN_TOKEN_CONTINUE
+/*
+ * GRN_TOKENIZER_TOKEN_LAST means that the next token is the last one.
+ *
+ * @deprecated since 4.0.8. Use GRN_TOKEN_LAST instead.
+ */
+#define GRN_TOKENIZER_TOKEN_LAST GRN_TOKEN_LAST
+/*
+ * GRN_TOKENIZER_TOKEN_OVERLAP means that ...
+ *
+ * @deprecated since 4.0.8. Use GRN_TOKEN_OVERLAP instead.
+ */
+#define GRN_TOKENIZER_TOKEN_OVERLAP GRN_TOKEN_OVERLAP
+/*
+ * GRN_TOKENIZER_TOKEN_UNMATURED means that ...
+ *
+ * @deprecated since 4.0.8. Use GRN_TOKEN_UNMATURED instead.
+ */
+#define GRN_TOKENIZER_TOKEN_UNMATURED GRN_TOKEN_UNMATURED
+/*
+ * GRN_TOKENIZER_TOKEN_REACH_END means that ...
+ *
+ * @deprecated since 4.0.8. Use GRN_TOKEN_REACH_END instead.
+ */
+#define GRN_TOKENIZER_TOKEN_REACH_END GRN_TOKEN_REACH_END
+/*
+ * GRN_TOKENIZER_TOKEN_SKIP means that the token is skipped
+ *
+ * @deprecated since 4.0.8. Use GRN_TOKEN_SKIP instead.
*/
-typedef unsigned int grn_tokenizer_status;
-
-/* GRN_TOKENIZER_TOKEN_CONTINUE means that the next token is not the last one. */
-#define GRN_TOKENIZER_TOKEN_CONTINUE (0)
-/* GRN_TOKENIZER_TOKEN_LAST means that the next token is the last one. */
-#define GRN_TOKENIZER_TOKEN_LAST (0x01L<<0)
-/* GRN_TOKENIZER_TOKEN_OVERLAP means that ... */
-#define GRN_TOKENIZER_TOKEN_OVERLAP (0x01L<<1)
-/* GRN_TOKENIZER_TOKEN_UNMATURED means that ... */
-#define GRN_TOKENIZER_TOKEN_UNMATURED (0x01L<<2)
-/* GRN_TOKENIZER_TOKEN_REACH_END means that ... */
-#define GRN_TOKENIZER_TOKEN_REACH_END (0x01L<<3)
-/* GRN_TOKENIZER_TOKEN_SKIP means that the token is skipped */
-#define GRN_TOKENIZER_TOKEN_SKIP (0x01L<<4)
-/* GRN_TOKENIZER_TOKEN_SKIP_WITH_POSITION means that the token and postion is skipped */
-#define GRN_TOKENIZER_TOKEN_SKIP_WITH_POSITION (0x01L<<5)
+#define GRN_TOKENIZER_TOKEN_SKIP GRN_TOKEN_SKIP
+/*
+ * GRN_TOKENIZER_TOKEN_SKIP_WITH_POSITION means that the token and postion is skipped
+ *
+ * @deprecated since 4.0.8. Use GRN_TOKEN_SKIP_WITH_POSITION instead.
+ */
+#define GRN_TOKENIZER_TOKEN_SKIP_WITH_POSITION GRN_TOKEN_SKIP_WITH_POSITION
+/*
+ * GRN_TOKENIZER_TOKEN_FORCE_PREIX that the token is used common prefix search
+ *
+ * @deprecated since 4.0.8. Use GRN_TOKEN_FORCE_PREIX instead.
+ */
+#define GRN_TOKENIZER_TOKEN_FORCE_PREFIX GRN_TOKEN_FORCE_PREFIX
/*
* GRN_TOKENIZER_CONTINUE and GRN_TOKENIZER_LAST are deprecated. They
@@ -193,32 +213,17 @@ typedef unsigned int grn_tokenizer_status;
#define GRN_TOKENIZER_CONTINUE GRN_TOKENIZER_TOKEN_CONTINUE
#define GRN_TOKENIZER_LAST GRN_TOKENIZER_TOKEN_LAST
-typedef struct _grn_token grn_token;
-
-GRN_PLUGIN_EXPORT grn_obj *grn_token_get_data(grn_ctx *ctx,
- grn_token *token);
-GRN_PLUGIN_EXPORT grn_rc grn_token_set_data(grn_ctx *ctx,
- grn_token *token,
- const char *str_ptr,
- int str_length);
-GRN_PLUGIN_EXPORT grn_tokenizer_status grn_token_get_status(grn_ctx *ctx,
- grn_token *token);
-GRN_PLUGIN_EXPORT grn_rc grn_token_set_status(grn_ctx *ctx,
- grn_token *token,
- grn_tokenizer_status status);
-
-
/*
grn_tokenizer_token_push() pushes the next token into `token'. Note that
grn_tokenizer_token_push() does not make a copy of the given string. This
means that you have to maintain a memory space allocated to the string.
Also note that the grn_tokenizer_token object must be maintained until the
- request for the next token or finalization comes. See grn_tokenizer_status in
+ request for the next token or finalization comes. See grn_token_status in
this header for more details of `status'.
*/
GRN_PLUGIN_EXPORT void grn_tokenizer_token_push(grn_ctx *ctx, grn_tokenizer_token *token,
const char *str_ptr, unsigned int str_length,
- grn_tokenizer_status status);
+ grn_token_status status);
/*
grn_tokenizer_tokenized_delimiter_next() extracts the next token
@@ -254,4 +259,4 @@ GRN_PLUGIN_EXPORT grn_rc grn_tokenizer_register(grn_ctx *ctx, const char *plugin
} /* extern "C" */
#endif /* __cplusplus */
-#endif /* GRN_PLUGIN_TOKENIZER_H */
+#endif /* GROONGA_TOKENIZER_H */
diff --git a/storage/mroonga/vendor/groonga/lib/util.h b/storage/mroonga/vendor/groonga/include/groonga/util.h
index b4dbb000aed..446cb88f8c3 100644
--- a/storage/mroonga/vendor/groonga/lib/util.h
+++ b/storage/mroonga/vendor/groonga/include/groonga/util.h
@@ -1,9 +1,10 @@
-/* -*- c-basic-offset: 2 -*- */
-/* Copyright(C) 2010-2011 Brazil
+/*
+ Copyright(C) 2010-2014 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
- License version 2.1 as published by the Free Software Foundation.
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -14,35 +15,26 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef GRN_UTIL_H
-#define GRN_UTIL_H
+#ifndef GROONGA_UTIL_H
+#define GROONGA_UTIL_H
-#ifndef GROONGA_IN_H
-#include "groonga_in.h"
-#endif /* GROONGA_IN_H */
-
-#ifndef GRN_CTX_H
-#include "ctx.h"
-#endif /* GRN_CTX_H */
-
-#ifdef __cplusplus
+#ifdef __cplusplus
extern "C" {
#endif
-GRN_API grn_rc grn_normalize_offset_and_limit(grn_ctx *ctx, int size, int *offset, int *limit);
-
GRN_API grn_obj *grn_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *obj);
+GRN_API grn_obj *grn_inspect_indented(grn_ctx *ctx, grn_obj *buffer,
+ grn_obj *obj, const char *indent);
GRN_API grn_obj *grn_inspect_name(grn_ctx *ctx, grn_obj *buffer, grn_obj *obj);
GRN_API grn_obj *grn_inspect_encoding(grn_ctx *ctx, grn_obj *buffer, grn_encoding encoding);
GRN_API grn_obj *grn_inspect_type(grn_ctx *ctx, grn_obj *buffer, unsigned char type);
-void grn_p(grn_ctx *ctx, grn_obj *obj);
-void grn_p_geo_point(grn_ctx *ctx, grn_geo_point *point);
-GRN_API const char *grn_win32_base_dir(void);
-GRN_API char *grn_path_separator_to_system(char *dest, char *groonga_path);
+GRN_API void grn_p(grn_ctx *ctx, grn_obj *obj);
+GRN_API void grn_p_geo_point(grn_ctx *ctx, grn_geo_point *point);
+GRN_API void grn_p_ii_values(grn_ctx *ctx, grn_obj *obj);
#ifdef __cplusplus
}
#endif
-#endif /* GRN_UTIL_H */
+#endif /* GROONGA_UTIL_H */
diff --git a/storage/mroonga/vendor/groonga/lib/CMakeLists.txt b/storage/mroonga/vendor/groonga/lib/CMakeLists.txt
index d19c88e4311..2103436545f 100644
--- a/storage/mroonga/vendor/groonga/lib/CMakeLists.txt
+++ b/storage/mroonga/vendor/groonga/lib/CMakeLists.txt
@@ -19,7 +19,10 @@ add_definitions(
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/dat
- ${MRUBY_INCLUDE_DIRS})
+ ${MRUBY_INCLUDE_DIRS}
+ ${LIBLZ4_INCLUDE_DIRS})
+link_directories(
+ ${LIBLZ4_LIBRARY_DIRS})
read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/sources.am LIBGROONGA_SOURCES)
read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/dat/sources.am LIBGRNDAT_SOURCES)
@@ -36,54 +39,46 @@ set_source_files_properties(dat.cpp ${LIBGRNDAT_SOURCES}
PROPERTIES
COMPILE_FLAGS "${GRN_CXX_COMPILE_FLAGS}")
-if(MRN_GROONGA_BUNDLED)
- add_library(libgroonga STATIC
- ${LIBGROONGA_SOURCES}
- ${LIBGRNDAT_SOURCES}
- ${LIBGRNMRB_SOURCES}
- ${MRUBY_LIBS})
+set(GRN_ALL_SOURCES
+ ${LIBGROONGA_SOURCES}
+ ${LIBGRNDAT_SOURCES}
+ ${LIBGRNMRB_SOURCES}
+ ${MRUBY_LIBS})
+if(GRN_EMBED)
+ add_library(libgroonga STATIC ${GRN_ALL_SOURCES})
else()
- add_library(libgroonga SHARED
- ${LIBGROONGA_SOURCES}
- ${LIBGRNDAT_SOURCES}
- ${LIBGRNMRB_SOURCES}
- ${MRUBY_LIBS})
+ add_library(libgroonga SHARED ${GRN_ALL_SOURCES})
endif()
set_target_properties(libgroonga PROPERTIES OUTPUT_NAME "groonga")
-if(NOT MRN_GROONGA_BUNDLED)
- target_link_libraries(libgroonga
+
+set(GRN_ALL_LIBRARIES
${EXECINFO_LIBS}
${RT_LIBS}
${PTHREAD_LIBS}
${Z_LIBS}
- ${LZO2_LIBS}
+ ${LIBLZ4_LIBRARIES}
${DL_LIBS}
+ ${M_LIBS}
${WS2_32_LIBS})
+if(GRN_EMBED)
+ target_link_libraries(libgroonga
+ ${GRN_ALL_LIBRARIES}
+ ${STDCPP_LIBS})
+else()
+ target_link_libraries(libgroonga
+ ${GRN_ALL_LIBRARIES})
install(TARGETS libgroonga
ARCHIVE DESTINATION "${LIB_DIR}"
LIBRARY DESTINATION "${LIB_DIR}"
RUNTIME DESTINATION "${BIN_DIR}")
-else()
- target_link_libraries(libgroonga
- ${EXECINFO_LIBS}
- ${RT_LIBS}
- ${PTHREAD_LIBS}
- ${Z_LIBS}
- ${LZO2_LIBS}
- ${DL_LIBS}
- ${M_LIBS}
- ${STDCPP_LIBS}
- ${WS2_32_LIBS})
endif()
-if(GRN_WITH_MRUBY)
+if(GRN_WITH_MRUBY AND NOT GRN_EMBED)
read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/mrb/scripts/sources.am
RUBY_SCRIPTS)
string(REGEX REPLACE "([^;]+)" "mrb/scripts/\\1"
RUBY_SCRIPTS "${RUBY_SCRIPTS}")
- if(NOT MRN_GROONGA_BUNDLED)
- install(
- FILES ${RUBY_SCRIPTS}
- DESTINATION "${GRN_RELATIVE_RUBY_SCRIPTS_DIR}")
- endif()
+ install(
+ FILES ${RUBY_SCRIPTS}
+ DESTINATION "${GRN_RELATIVE_RUBY_SCRIPTS_DIR}")
endif()
diff --git a/storage/mroonga/vendor/groonga/lib/Makefile.am b/storage/mroonga/vendor/groonga/lib/Makefile.am
index 047c41a25da..8f4e76ea212 100644
--- a/storage/mroonga/vendor/groonga/lib/Makefile.am
+++ b/storage/mroonga/vendor/groonga/lib/Makefile.am
@@ -10,8 +10,17 @@ AM_CFLAGS = \
$(COVERAGE_CFLAGS) \
$(GRN_CFLAGS) \
$(MESSAGE_PACK_CFLAGS) \
- $(MRUBY_CFLAGS)
-DEFAULT_INCLUDES = -I$(top_builddir) -I$(top_srcdir)/include
+ $(LIBLZ4_CFLAGS)
+
+BUNDLED_LIBRARIES_CFLAGS = \
+ $(MRUBY_CFLAGS) \
+ $(ONIGMO_CFLAGS)
+
+DEFAULT_INCLUDES = \
+ -I$(top_builddir) \
+ -I$(top_srcdir)/include \
+ $(BUNDLED_LIBRARIES_CFLAGS)
+
DEFS += -D_REENTRANT $(GRN_DEFS) -DGRN_DAT_EXPORT
include sources.am
@@ -24,12 +33,20 @@ libgroonga_la_LDFLAGS = \
libgroonga_la_LIBADD = \
dat/libgrndat.la \
mrb/libgrnmrb.la \
- $(MESSAGE_PACK_LIBS) \
- $(MRUBY_LIBS)
+ $(MESSAGE_PACK_LIBS)
+
+if WITH_MRUBY
+libgroonga_la_LIBADD += \
+ ../vendor/mruby/libmruby.la
+endif
+
+libgroonga_la_LIBADD += \
+ $(ONIGMO_LIBS) \
+ $(LIBLZ4_LIBS)
if WITH_LEMON
BUILT_SOURCES = \
- ecmascript.c
+ grn_ecmascript.c
SUFFIXES = .lemon .c
@@ -38,9 +55,9 @@ SUFFIXES = .lemon .c
endif
EXTRA_DIST = \
- ecmascript.c \
- ecmascript.h \
- ecmascript.lemon \
+ grn_ecmascript.c \
+ grn_ecmascript.h \
+ grn_ecmascript.lemon \
CMakeLists.txt
CLEANFILES = *.gcno *.gcda
diff --git a/storage/mroonga/vendor/groonga/lib/com.c b/storage/mroonga/vendor/groonga/lib/com.c
index 172ad91ed1e..a17d3a931de 100644
--- a/storage/mroonga/vendor/groonga/lib/com.c
+++ b/storage/mroonga/vendor/groonga/lib/com.c
@@ -15,11 +15,11 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "groonga_in.h"
+#include "grn.h"
#include <stdio.h>
#include <string.h>
-#include "ctx_impl.h"
+#include "grn_ctx_impl.h"
#ifdef WIN32
# include <ws2tcpip.h>
@@ -38,8 +38,8 @@
# endif /* HAVE_SIGNAL_H */
#endif /* WIN32 */
-#include "ctx.h"
-#include "com.h"
+#include "grn_ctx.h"
+#include "grn_com.h"
#ifndef PF_INET
#define PF_INET AF_INET
@@ -193,7 +193,7 @@ grn_msg_send(grn_ctx *ctx, grn_obj *msg, int flags)
{
ssize_t ret;
ret = send(peer->fd, GRN_BULK_HEAD(msg), GRN_BULK_VSIZE(msg), MSG_NOSIGNAL);
- if (ret == -1) { SERR("send"); }
+ if (ret == -1) { SOERR("send"); }
if (ctx->rc != GRN_OPERATION_WOULD_BLOCK) {
grn_com_queue_enque(ctx, m->old, (grn_com_queue_entry *)msg);
return ctx->rc;
@@ -251,7 +251,7 @@ grn_com_init(void)
WSADATA wd;
if (WSAStartup(MAKEWORD(2, 0), &wd) != 0) {
grn_ctx *ctx = &grn_gctx;
- SERR("WSAStartup");
+ SOERR("WSAStartup");
}
#else /* WIN32 */
#ifndef USE_MSG_NOSIGNAL
@@ -281,7 +281,7 @@ grn_com_event_init(grn_ctx *ctx, grn_com_event *ev, int max_nevents, int data_si
COND_INIT(ev->cond);
GRN_COM_QUEUE_INIT(&ev->recv_old);
#ifndef USE_SELECT
-#ifdef USE_EPOLL
+# ifdef USE_EPOLL
if ((ev->events = GRN_MALLOC(sizeof(struct epoll_event) * max_nevents))) {
if ((ev->epfd = epoll_create(max_nevents)) != -1) {
goto exit;
@@ -290,8 +290,8 @@ grn_com_event_init(grn_ctx *ctx, grn_com_event *ev, int max_nevents, int data_si
}
GRN_FREE(ev->events);
}
-#else /* USE_EPOLL */
-#ifdef USE_KQUEUE
+# else /* USE_EPOLL */
+# ifdef USE_KQUEUE
if ((ev->events = GRN_MALLOC(sizeof(struct kevent) * max_nevents))) {
if ((ev->kqfd = kqueue()) != -1) {
goto exit;
@@ -300,17 +300,17 @@ grn_com_event_init(grn_ctx *ctx, grn_com_event *ev, int max_nevents, int data_si
}
GRN_FREE(ev->events);
}
-#else /* USE_KQUEUE */
+# else /* USE_KQUEUE */
if ((ev->events = GRN_MALLOC(sizeof(struct pollfd) * max_nevents))) {
goto exit;
}
-#endif /* USE_KQUEUE*/
-#endif /* USE_EPOLL */
+# endif /* USE_KQUEUE*/
+# endif /* USE_EPOLL */
grn_hash_close(ctx, ev->hash);
ev->hash = NULL;
ev->events = NULL;
#else /* USE_SELECT */
-
+ goto exit;
#endif /* USE_SELECT */
}
exit :
@@ -327,12 +327,12 @@ grn_com_event_fin(grn_ctx *ctx, grn_com_event *ev)
if (ev->hash) { grn_hash_close(ctx, ev->hash); }
#ifndef USE_SELECT
if (ev->events) { GRN_FREE(ev->events); }
-#ifdef USE_EPOLL
+# ifdef USE_EPOLL
GRN_CLOSE(ev->epfd);
-#endif /* USE_EPOLL */
-#ifdef USE_KQUEUE
+# endif /* USE_EPOLL */
+# ifdef USE_KQUEUE
GRN_CLOSE(ev->kqfd);
-#endif /* USE_KQUEUE*/
+# endif /* USE_KQUEUE*/
#endif /* USE_SELECT */
return GRN_SUCCESS;
}
@@ -387,7 +387,10 @@ grn_com_event_mod(grn_ctx *ctx, grn_com_event *ev, grn_sock fd, int events, grn_
if (!ev) { return GRN_INVALID_ARGUMENT; }
if (grn_hash_get(ctx, ev->hash, &fd, sizeof(grn_sock), (void **)&c)) {
if (c->fd != fd) {
- GRN_LOG(ctx, GRN_LOG_ERROR, "grn_com_event_mod fd unmatch %d != %d", c->fd, fd);
+ GRN_LOG(ctx, GRN_LOG_ERROR,
+ "grn_com_event_mod fd unmatch "
+ "%" GRN_FMT_SOCKET " != %" GRN_FMT_SOCKET,
+ c->fd, fd);
return GRN_OBJECT_CORRUPT;
}
if (com) { *com = c; }
@@ -449,7 +452,9 @@ grn_com_event_del(grn_ctx *ctx, grn_com_event *ev, grn_sock fd)
#endif /* USE_KQUEUE */
return grn_hash_delete_by_id(ctx, ev->hash, id, NULL);
} else {
- GRN_LOG(ctx, GRN_LOG_ERROR, "%04x| fd(%d) not found in ev(%p)", getpid(), fd, ev);
+ GRN_LOG(ctx, GRN_LOG_ERROR,
+ "%04x| fd(%" GRN_FMT_SOCKET ") not found in ev(%p)",
+ getpid(), fd, ev);
return GRN_INVALID_ARGUMENT;
}
}
@@ -469,7 +474,7 @@ grn_com_event_start_accept(grn_ctx *ctx, grn_com_event *ev)
if (listen(com->fd, LISTEN_BACKLOG) == 0) {
com->accepting = GRN_TRUE;
} else {
- SERR("listen - start accept");
+ SOERR("listen - start accept");
}
}
GRN_API_RETURN(ctx->rc);
@@ -487,7 +492,7 @@ grn_com_event_stop_accept(grn_ctx *ctx, grn_com_event *ev)
if (listen(com->fd, 0) == 0) {
com->accepting = GRN_FALSE;
} else {
- SERR("listen - disable accept");
+ SOERR("listen - disable accept");
}
}
GRN_API_RETURN(ctx->rc);
@@ -505,7 +510,7 @@ grn_com_receiver(grn_ctx *ctx, grn_com *com)
if (errno == EMFILE) {
grn_com_event_stop_accept(ctx, ev);
} else {
- SERR("accept");
+ SOERR("accept");
}
return;
}
@@ -562,7 +567,7 @@ grn_com_event_poll(grn_ctx *ctx, grn_com_event *ev, int timeout)
});
nevents = select(nfds + 1, &rfds, &wfds, NULL, (timeout >= 0) ? &tv : NULL);
if (nevents < 0) {
- SERR("select");
+ SOERR("select");
if (ctx->rc == GRN_INTERRUPTED_FUNCTION_CALL) { ERRCLR(ctx); }
return ctx->rc;
}
@@ -571,7 +576,7 @@ grn_com_event_poll(grn_ctx *ctx, grn_com_event *ev, int timeout)
if (FD_ISSET(*pfd, &rfds)) { grn_com_receiver(ctx, com); }
});
#else /* USE_SELECT */
-#ifdef USE_EPOLL
+# ifdef USE_EPOLL
struct epoll_event *ep;
ctx->errlvl = GRN_OK;
ctx->rc = GRN_SUCCESS;
@@ -579,8 +584,8 @@ grn_com_event_poll(grn_ctx *ctx, grn_com_event *ev, int timeout)
if (nevents < 0) {
SERR("epoll_wait");
}
-#else /* USE_EPOLL */
-#ifdef USE_KQUEUE
+# else /* USE_EPOLL */
+# ifdef USE_KQUEUE
struct kevent *ep;
struct timespec tv;
if (timeout >= 0) {
@@ -591,7 +596,7 @@ grn_com_event_poll(grn_ctx *ctx, grn_com_event *ev, int timeout)
if (nevents < 0) {
SERR("kevent");
}
-#else /* USE_KQUEUE */
+# else /* USE_KQUEUE */
uint32_t dummy;
int nfd = 0, *pfd;
struct pollfd *ep = ev->events;
@@ -609,8 +614,8 @@ grn_com_event_poll(grn_ctx *ctx, grn_com_event *ev, int timeout)
if (nevents < 0) {
SERR("poll");
}
-#endif /* USE_KQUEUE */
-#endif /* USE_EPOLL */
+# endif /* USE_KQUEUE */
+# endif /* USE_EPOLL */
if (ctx->rc != GRN_SUCCESS) {
if (ctx->rc == GRN_INTERRUPTED_FUNCTION_CALL) {
ERRCLR(ctx);
@@ -620,7 +625,7 @@ grn_com_event_poll(grn_ctx *ctx, grn_com_event *ev, int timeout)
if (timeout < 0 && !nevents) { GRN_LOG(ctx, GRN_LOG_NOTICE, "poll returns 0 events"); }
for (ep = ev->events; nevents; ep++) {
int efd;
-#ifdef USE_EPOLL
+# ifdef USE_EPOLL
efd = ep->data.fd;
nevents--;
// todo : com = ep->data.ptr;
@@ -631,12 +636,12 @@ grn_com_event_poll(grn_ctx *ctx, grn_com_event *ev, int timeout)
e.data.fd = efd;
e.events = ep->events;
if (epoll_ctl(ev->epfd, EPOLL_CTL_DEL, efd, &e) == -1) { SERR("epoll_ctl"); }
- if (grn_sock_close(efd) == -1) { SERR("close"); }
+ if (grn_sock_close(efd) == -1) { SOERR("close"); }
continue;
}
if ((ep->events & GRN_COM_POLLIN)) { grn_com_receiver(ctx, com); }
-#else /* USE_EPOLL */
-#ifdef USE_KQUEUE
+# else /* USE_EPOLL */
+# ifdef USE_KQUEUE
efd = ep->ident;
nevents--;
// todo : com = ep->udata;
@@ -645,22 +650,22 @@ grn_com_event_poll(grn_ctx *ctx, grn_com_event *ev, int timeout)
GRN_LOG(ctx, GRN_LOG_ERROR, "fd(%d) not found in ev->set", efd);
EV_SET(&e, efd, ep->filter, EV_DELETE, 0, 0, NULL);
if (kevent(ev->kqfd, &e, 1, NULL, 0, NULL) == -1) { SERR("kevent"); }
- if (grn_sock_close(efd) == -1) { SERR("close"); }
+ if (grn_sock_close(efd) == -1) { SOERR("close"); }
continue;
}
if ((ep->filter == GRN_COM_POLLIN)) { grn_com_receiver(ctx, com); }
-#else
+# else
efd = ep->fd;
if (!(ep->events & ep->revents)) { continue; }
nevents--;
if (!grn_hash_get(ctx, ev->hash, &efd, sizeof(grn_sock), (void *)&com)) {
GRN_LOG(ctx, GRN_LOG_ERROR, "fd(%d) not found in ev->hash", efd);
- if (grn_sock_close(efd) == -1) { SERR("close"); }
+ if (grn_sock_close(efd) == -1) { SOERR("close"); }
continue;
}
if ((ep->revents & GRN_COM_POLLIN)) { grn_com_receiver(ctx, com); }
-#endif /* USE_KQUEUE */
-#endif /* USE_EPOLL */
+# endif /* USE_KQUEUE */
+# endif /* USE_EPOLL */
}
#endif /* USE_SELECT */
/* todo :
@@ -682,7 +687,7 @@ grn_com_send_http(grn_ctx *ctx, grn_com *cs, const char *path, uint32_t path_len
GRN_TEXT_PUTS(ctx, &buf, " HTTP/1.0\r\n\r\n");
// todo : refine
if ((ret = send(cs->fd, GRN_BULK_HEAD(&buf), GRN_BULK_VSIZE(&buf), MSG_NOSIGNAL|flags)) == -1) {
- SERR("send");
+ SOERR("send");
}
if (ret != GRN_BULK_VSIZE(&buf)) {
GRN_LOG(ctx, GRN_LOG_NOTICE, "send %d != %d", (int)ret, (int)GRN_BULK_VSIZE(&buf));
@@ -710,7 +715,7 @@ grn_com_send(grn_ctx *ctx, grn_com *cs,
wsabufs[1].buf = (char *)body;
wsabufs[1].len = size;
if (WSASend(cs->fd, wsabufs, 2, &n_sent, 0, NULL, NULL) == SOCKET_ERROR) {
- SERR("WSASend");
+ SOERR("WSASend");
}
ret = n_sent;
#else /* WIN32 */
@@ -728,18 +733,19 @@ grn_com_send(grn_ctx *ctx, grn_com *cs,
msg_iov[1].iov_base = (char *)body;
msg_iov[1].iov_len = size;
if ((ret = sendmsg(cs->fd, &msg, MSG_NOSIGNAL|flags)) == -1) {
- SERR("sendmsg");
+ SOERR("sendmsg");
rc = ctx->rc;
}
#endif /* WIN32 */
} else {
if ((ret = send(cs->fd, (const void *)header, whole_size, MSG_NOSIGNAL|flags)) == -1) {
- SERR("send");
+ SOERR("send");
rc = ctx->rc;
}
}
if (ret != whole_size) {
- GRN_LOG(ctx, GRN_LOG_ERROR, "sendmsg(%d): %" GRN_FMT_LLD " < %" GRN_FMT_LLU,
+ GRN_LOG(ctx, GRN_LOG_ERROR,
+ "sendmsg(%" GRN_FMT_SOCKET "): %" GRN_FMT_LLD " < %" GRN_FMT_LLU,
cs->fd, (long long int)ret, (unsigned long long int)whole_size);
rc = ctx->rc;
}
@@ -781,7 +787,7 @@ grn_com_recv_text(grn_ctx *ctx, grn_com *com,
for (;;) {
if (grn_bulk_reserve(ctx, buf, BUFSIZE)) { return ctx->rc; }
if ((ret = recv(com->fd, GRN_BULK_CURR(buf), BUFSIZE, 0)) < 0) {
- SERR("recv text");
+ SOERR("recv text");
if (ctx->rc == GRN_OPERATION_WOULD_BLOCK ||
ctx->rc == GRN_INTERRUPTED_FUNCTION_CALL) {
ERRCLR(ctx);
@@ -813,7 +819,7 @@ exit :
GRN_BULK_REWIND(buf);
grn_bulk_reserve(ctx, buf, BUFSIZE);
if ((ret = recv(com->fd, GRN_BULK_CURR(buf), BUFSIZE, 0)) < 0) {
- SERR("recv text body");
+ SOERR("recv text body");
} else {
GRN_BULK_CURR(buf) += ret;
}
@@ -831,8 +837,8 @@ grn_com_recv(grn_ctx *ctx, grn_com *com, grn_com_header *header, grn_obj *buf)
size_t rest = sizeof(grn_com_header);
do {
if ((ret = recv(com->fd, p, rest, 0)) < 0) {
- SERR("recv size");
- GRN_LOG(ctx, GRN_LOG_ERROR, "recv error (%d)", com->fd);
+ SOERR("recv size");
+ GRN_LOG(ctx, GRN_LOG_ERROR, "recv error (%" GRN_FMT_SOCKET ")", com->fd);
if (ctx->rc == GRN_OPERATION_WOULD_BLOCK ||
ctx->rc == GRN_INTERRUPTED_FUNCTION_CALL) {
ERRCLR(ctx);
@@ -852,7 +858,14 @@ grn_com_recv(grn_ctx *ctx, grn_com *com, grn_com_header *header, grn_obj *buf)
}
}
} while (rest);
- GRN_LOG(ctx, GRN_LOG_INFO, "recv (%d,%x,%d,%02x,%02x,%04x)", ntohl(header->size), header->flags, header->proto, header->qtype, header->level, header->status);
+ GRN_LOG(ctx, GRN_LOG_INFO,
+ "recv (%u,%x,%d,%02x,%02x,%04x)",
+ (uint32_t)ntohl(header->size),
+ header->flags,
+ header->proto,
+ header->qtype,
+ header->level,
+ header->status);
{
uint8_t proto = header->proto;
size_t value_size = ntohl(header->size);
@@ -868,7 +881,7 @@ grn_com_recv(grn_ctx *ctx, grn_com *com, grn_com_header *header, grn_obj *buf)
retry = 0;
for (rest = value_size; rest;) {
if ((ret = recv(com->fd, GRN_BULK_CURR(buf), rest, MSG_WAITALL)) < 0) {
- SERR("recv body");
+ SOERR("recv body");
if (ctx->rc == GRN_OPERATION_WOULD_BLOCK ||
ctx->rc == GRN_INTERRUPTED_FUNCTION_CALL) {
ERRCLR(ctx);
@@ -926,7 +939,7 @@ grn_com_copen(grn_ctx *ctx, grn_com_event *ev, const char *dest, int port)
#endif
#ifdef EAI_SYSTEM
case EAI_SYSTEM:
- SERR("getaddrinfo");
+ SOERR("getaddrinfo");
break;
#endif
default:
@@ -943,12 +956,13 @@ grn_com_copen(grn_ctx *ctx, grn_com_event *ev, const char *dest, int port)
fd = socket(addrinfo_ptr->ai_family, addrinfo_ptr->ai_socktype,
addrinfo_ptr->ai_protocol);
if (fd == -1) {
- SERR("socket");
- } else if (setsockopt(fd, 6, TCP_NODELAY, &value, sizeof(value))) {
- SERR("setsockopt");
+ SOERR("socket");
+ } else if (setsockopt(fd, 6, TCP_NODELAY,
+ (const char *)&value, sizeof(value))) {
+ SOERR("setsockopt");
grn_sock_close(fd);
} else if (connect(fd, addrinfo_ptr->ai_addr, addrinfo_ptr->ai_addrlen)) {
- SERR("connect");
+ SOERR("connect");
grn_sock_close(fd);
} else {
break;
@@ -981,9 +995,9 @@ void
grn_com_close_(grn_ctx *ctx, grn_com *com)
{
grn_sock fd = com->fd;
- if (shutdown(fd, SHUT_RDWR) == -1) { /* SERR("shutdown"); */ }
+ if (shutdown(fd, SHUT_RDWR) == -1) { /* SOERR("shutdown"); */ }
if (grn_sock_close(fd) == -1) {
- SERR("close");
+ SOERR("close");
} else {
com->closed = 1;
}
@@ -1040,7 +1054,7 @@ grn_com_sopen(grn_ctx *ctx, grn_com_event *ev,
#endif
#ifdef EAI_SYSTEM
case EAI_SYSTEM:
- SERR("getaddrinfo");
+ SOERR("getaddrinfo");
break;
#endif
default:
@@ -1052,7 +1066,7 @@ grn_com_sopen(grn_ctx *ctx, grn_com_event *ev,
goto exit;
}
if ((lfd = socket(bind_address_info->ai_family, SOCK_STREAM, 0)) == -1) {
- SERR("socket");
+ SOERR("socket");
goto exit;
}
memcpy(&ev->curr_edge_id.addr, he->h_addr, he->h_length);
@@ -1061,20 +1075,20 @@ grn_com_sopen(grn_ctx *ctx, grn_com_event *ev,
{
int v = 1;
if (setsockopt(lfd, SOL_TCP, TCP_NODELAY, (void *) &v, sizeof(int)) == -1) {
- SERR("setsockopt");
+ SOERR("setsockopt");
goto exit;
}
if (setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, (void *) &v, sizeof(int)) == -1) {
- SERR("setsockopt");
+ SOERR("setsockopt");
goto exit;
}
}
if (bind(lfd, bind_address_info->ai_addr, bind_address_info->ai_addrlen) < 0) {
- SERR("bind");
+ SOERR("bind");
goto exit;
}
if (listen(lfd, LISTEN_BACKLOG) < 0) {
- SERR("listen");
+ SOERR("listen");
goto exit;
}
if (ev) {
diff --git a/storage/mroonga/vendor/groonga/lib/command.c b/storage/mroonga/vendor/groonga/lib/command.c
new file mode 100644
index 00000000000..b0f75229744
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/command.c
@@ -0,0 +1,194 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2015 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <string.h>
+
+#include "grn.h"
+#include "grn_db.h"
+#include "grn_ctx_impl.h"
+
+struct _grn_command_input {
+ grn_obj *command;
+ grn_hash *arguments;
+};
+
+grn_command_input *
+grn_command_input_open(grn_ctx *ctx, grn_obj *command)
+{
+ grn_command_input *input = NULL;
+
+ GRN_API_ENTER;
+ input = GRN_MALLOC(sizeof(grn_command_input));
+ if (!input) {
+ ERR(GRN_NO_MEMORY_AVAILABLE,
+ "[command-input] failed to allocate grn_command_input");
+ goto exit;
+ }
+
+ input->command = command;
+ /* TODO: Allocate by self. */
+ {
+ uint32_t n;
+ input->arguments = grn_expr_get_vars(ctx, input->command, &n);
+ }
+
+exit :
+ GRN_API_RETURN(input);
+}
+
+grn_rc
+grn_command_input_close(grn_ctx *ctx, grn_command_input *input)
+{
+ GRN_API_ENTER;
+
+ /* TODO: Free input->arguments by self. */
+ grn_expr_clear_vars(ctx, input->command);
+ GRN_FREE(input);
+
+ GRN_API_RETURN(ctx->rc);
+}
+
+grn_obj *
+grn_command_input_add(grn_ctx *ctx,
+ grn_command_input *input,
+ const char *name,
+ int name_size,
+ grn_bool *added)
+{
+ grn_obj *argument = NULL;
+ /* TODO: Use grn_bool */
+ int internal_added = GRN_FALSE;
+
+ GRN_API_ENTER;
+
+ if (name_size == -1) {
+ name_size = strlen(name);
+ }
+ if (input->arguments) {
+ grn_hash_add(ctx, input->arguments, name, name_size, (void **)&argument,
+ &internal_added);
+ if (internal_added) {
+ GRN_TEXT_INIT(argument, 0);
+ }
+ }
+ if (added) {
+ *added = internal_added;
+ }
+
+ GRN_API_RETURN(argument);
+}
+
+grn_obj *
+grn_command_input_get(grn_ctx *ctx,
+ grn_command_input *input,
+ const char *name,
+ int name_size)
+{
+ grn_obj *argument = NULL;
+
+ GRN_API_ENTER;
+
+ if (name_size == -1) {
+ name_size = strlen(name);
+ }
+ if (input->arguments) {
+ grn_hash_get(ctx, input->arguments, name, name_size, (void **)&argument);
+ }
+
+ GRN_API_RETURN(argument);
+}
+
+grn_obj *
+grn_command_input_at(grn_ctx *ctx,
+ grn_command_input *input,
+ unsigned int offset)
+{
+ grn_obj *argument = NULL;
+
+ GRN_API_ENTER;
+ if (input->arguments) {
+ uint32_t size;
+ argument = (grn_obj *)grn_hash_get_value_(ctx, input->arguments,
+ offset + 1, &size);
+ }
+ GRN_API_RETURN(argument);
+}
+
+grn_rc
+grn_command_register(grn_ctx *ctx,
+ const char *command_name,
+ int command_name_size,
+ grn_command_run_func *run,
+ grn_expr_var *vars,
+ unsigned int n_vars,
+ void *user_data)
+{
+ GRN_API_ENTER;
+
+ if (command_name_size == -1) {
+ command_name_size = strlen(command_name);
+ }
+
+ {
+ grn_obj *command_object;
+ command_object = grn_proc_create(ctx,
+ command_name,
+ command_name_size,
+ GRN_PROC_COMMAND,
+ NULL, NULL, NULL, n_vars, vars);
+ if (!command_object) {
+ GRN_PLUGIN_ERROR(ctx, GRN_COMMAND_ERROR,
+ "[command][%.*s] failed to grn_proc_create()",
+ command_name_size, command_name);
+ GRN_API_RETURN(ctx->rc);
+ }
+
+ {
+ grn_proc *command = (grn_proc *)command_object;
+ command->callbacks.command.run = run;
+ command->user_data = user_data;
+ }
+ }
+
+ GRN_API_RETURN(GRN_SUCCESS);
+}
+
+grn_rc
+grn_command_run(grn_ctx *ctx,
+ grn_obj *command,
+ grn_command_input *input)
+{
+ grn_proc *proc;
+
+ GRN_API_ENTER;
+
+ proc = (grn_proc *)command;
+ if (proc->callbacks.command.run) {
+ proc->callbacks.command.run(ctx, command, input, proc->user_data);
+ } else {
+ /* TODO: REMOVE ME. For backward compatibility. */
+ uint32_t stack_curr = ctx->impl->stack_curr;
+ grn_proc_call(ctx, command, 0, command);
+ if (ctx->impl->stack_curr > stack_curr) {
+ grn_ctx_pop(ctx);
+ }
+ }
+
+ GRN_API_RETURN(ctx->rc);
+}
+
diff --git a/storage/mroonga/vendor/groonga/lib/ctx.c b/storage/mroonga/vendor/groonga/lib/ctx.c
index a419081635f..5408832dfcc 100644
--- a/storage/mroonga/vendor/groonga/lib/ctx.c
+++ b/storage/mroonga/vendor/groonga/lib/ctx.c
@@ -1,6 +1,6 @@
/* -*- c-basic-offset: 2 -*- */
/*
- Copyright(C) 2009-2014 Brazil
+ Copyright(C) 2009-2015 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -16,16 +16,17 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "groonga_in.h"
+#include "grn.h"
#include <string.h>
-#include "token.h"
-#include "ctx_impl.h"
-#include "pat.h"
-#include "plugin_in.h"
-#include "snip.h"
-#include "output.h"
-#include "normalizer_in.h"
-#include "ctx_impl_mrb.h"
+#include "grn_request_canceler.h"
+#include "grn_tokenizers.h"
+#include "grn_ctx_impl.h"
+#include "grn_pat.h"
+#include "grn_plugin.h"
+#include "grn_snip.h"
+#include "grn_output.h"
+#include "grn_normalizer.h"
+#include "grn_ctx_impl_mrb.h"
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
@@ -132,15 +133,25 @@ grn_rc
grn_timeval2str(grn_ctx *ctx, grn_timeval *tv, char *buf)
{
struct tm *ltm;
-#ifdef HAVE_LOCALTIME_R
+ const char *function_name;
+#ifdef HAVE__LOCALTIME64_S
struct tm tm;
time_t t = tv->tv_sec;
+ function_name = "localtime_s";
+ ltm = (localtime_s(&tm, &t) == 0) ? &tm : NULL;
+#else /* HAVE__LOCALTIME64_S */
+# ifdef HAVE_LOCALTIME_R
+ struct tm tm;
+ time_t t = tv->tv_sec;
+ function_name = "localtime_r";
ltm = localtime_r(&t, &tm);
-#else /* HAVE_LOCALTIME_R */
+# else /* HAVE_LOCALTIME_R */
time_t tvsec = (time_t) tv->tv_sec;
+ function_name = "localtime";
ltm = localtime(&tvsec);
-#endif /* HAVE_LOCALTIME_R */
- if (!ltm) { SERR("localtime"); }
+# endif /* HAVE_LOCALTIME_R */
+#endif /* HAVE__LOCALTIME64_S */
+ if (!ltm) { SERR(function_name); }
snprintf(buf, GRN_TIMEVAL_STR_SIZE - 1, GRN_TIMEVAL_STR_FORMAT,
ltm->tm_year + 1900, ltm->tm_mon + 1, ltm->tm_mday,
ltm->tm_hour, ltm->tm_min, ltm->tm_sec,
@@ -241,7 +252,7 @@ grn_alloc_info_set_backtrace(char *buffer, size_t size)
}
inline static void
-grn_alloc_info_add(void *address)
+grn_alloc_info_add(void *address, const char *file, int line, const char *func)
{
grn_ctx *ctx;
grn_alloc_info *new_alloc_info;
@@ -254,6 +265,17 @@ grn_alloc_info_add(void *address)
new_alloc_info->freed = GRN_FALSE;
grn_alloc_info_set_backtrace(new_alloc_info->alloc_backtrace,
sizeof(new_alloc_info->alloc_backtrace));
+ if (file) {
+ new_alloc_info->file = strdup(file);
+ } else {
+ new_alloc_info->file = NULL;
+ }
+ new_alloc_info->line = line;
+ if (func) {
+ new_alloc_info->func = strdup(func);
+ } else {
+ new_alloc_info->func = NULL;
+ }
new_alloc_info->next = ctx->impl->alloc_info;
ctx->impl->alloc_info = new_alloc_info;
}
@@ -291,8 +313,13 @@ grn_alloc_info_dump(grn_ctx *ctx)
if (alloc_info->freed) {
printf("address[%d][freed]: %p\n", i, alloc_info->address);
} else {
- printf("address[%d][not-freed]: %p:\n%s",
- i, alloc_info->address, alloc_info->alloc_backtrace);
+ printf("address[%d][not-freed]: %p: %s:%d: %s()\n%s",
+ i,
+ alloc_info->address,
+ alloc_info->file ? alloc_info->file : "(unknown)",
+ alloc_info->line,
+ alloc_info->func ? alloc_info->func : "(unknown)",
+ alloc_info->alloc_backtrace);
}
i++;
}
@@ -340,13 +367,15 @@ grn_alloc_info_free(grn_ctx *ctx)
grn_alloc_info *current_alloc_info = alloc_info;
alloc_info = alloc_info->next;
current_alloc_info->next = NULL;
+ free(current_alloc_info->file);
+ free(current_alloc_info->func);
free(current_alloc_info);
}
ctx->impl->alloc_info = NULL;
}
#else /* USE_MEMORY_DEBUG */
-# define grn_alloc_info_add(address)
+# define grn_alloc_info_add(address, file, line, func)
# define grn_alloc_info_change(old_address, new_address)
# define grn_alloc_info_check(address)
# define grn_alloc_info_dump(ctx)
@@ -372,17 +401,17 @@ int grn_fmalloc_line = 0;
static void
grn_ctx_impl_init_malloc(grn_ctx *ctx)
{
-# ifdef USE_FAIL_MALLOC
+# ifdef USE_FAIL_MALLOC
ctx->impl->malloc_func = grn_malloc_fail;
ctx->impl->calloc_func = grn_calloc_fail;
ctx->impl->realloc_func = grn_realloc_fail;
ctx->impl->strdup_func = grn_strdup_fail;
-# else
+# else
ctx->impl->malloc_func = grn_malloc_default;
ctx->impl->calloc_func = grn_calloc_default;
ctx->impl->realloc_func = grn_realloc_default;
ctx->impl->strdup_func = grn_strdup_default;
-# endif
+# endif
}
#endif
@@ -423,7 +452,7 @@ grn_ctx_loader_clear(grn_ctx *ctx)
#define IMPL_SIZE ((sizeof(struct _grn_ctx_impl) + (grn_pagesize - 1)) & ~(grn_pagesize - 1))
#ifdef GRN_WITH_MESSAGE_PACK
-static inline int
+static int
grn_msgpack_buffer_write(void *data, const char *buf, unsigned int len)
{
grn_ctx *ctx = (grn_ctx *)data;
@@ -434,7 +463,6 @@ grn_msgpack_buffer_write(void *data, const char *buf, unsigned int len)
static void
grn_ctx_impl_init(grn_ctx *ctx)
{
-
grn_io_mapinfo mi;
if (!(ctx->impl = grn_io_anon_map(ctx, &mi, IMPL_SIZE))) {
ctx->impl = NULL;
@@ -559,8 +587,8 @@ grn_ctx_impl_set_current_error_message(grn_ctx *ctx)
strcpy(ctx->impl->previous_errbuf, ctx->errbuf);
}
-grn_rc
-grn_ctx_init(grn_ctx *ctx, int flags)
+static grn_rc
+grn_ctx_init_internal(grn_ctx *ctx, int flags)
{
if (!ctx) { return GRN_INVALID_ARGUMENT; }
// if (ctx->stat != GRN_CTX_FIN) { return GRN_INVALID_ARGUMENT; }
@@ -591,6 +619,20 @@ grn_ctx_init(grn_ctx *ctx, int flags)
return ctx->rc;
}
+grn_rc
+grn_ctx_init(grn_ctx *ctx, int flags)
+{
+ grn_rc rc;
+
+ rc = grn_ctx_init_internal(ctx, flags);
+ if (rc == GRN_SUCCESS) {
+ grn_ctx_impl_init(ctx);
+ rc = ctx->rc;
+ }
+
+ return rc;
+}
+
grn_ctx *
grn_ctx_open(int flags)
{
@@ -706,7 +748,6 @@ grn_ctx_set_finalizer(grn_ctx *ctx, grn_proc_func *finalizer)
{
if (!ctx) { return GRN_INVALID_ARGUMENT; }
if (!ctx->impl) {
- grn_ctx_impl_init(ctx);
if (ERRP(ctx, GRN_ERROR)) { return ctx->rc; }
}
ctx->impl->finalizer = finalizer;
@@ -1227,7 +1268,7 @@ grn_init(void)
grn_gtick = 0;
ctx->next = ctx;
ctx->prev = ctx;
- grn_ctx_init(ctx, 0);
+ grn_ctx_init_internal(ctx, 0);
ctx->encoding = grn_encoding_parse(GRN_DEFAULT_ENCODING);
grn_timeval_now(ctx, &grn_starttime);
#ifdef WIN32
@@ -1282,8 +1323,8 @@ grn_init(void)
GRN_LOG(ctx, GRN_LOG_ALERT, "grn_normalizer_init failed (%d)", rc);
return rc;
}
- if ((rc = grn_token_init())) {
- GRN_LOG(ctx, GRN_LOG_ALERT, "grn_token_init failed (%d)", rc);
+ if ((rc = grn_tokenizers_init())) {
+ GRN_LOG(ctx, GRN_LOG_ALERT, "grn_tokenizers_init failed (%d)", rc);
return rc;
}
/*
@@ -1293,6 +1334,13 @@ grn_init(void)
}
*/
grn_cache_init();
+ if (!grn_request_canceler_init()) {
+ rc = ctx->rc;
+ grn_cache_fin();
+ GRN_LOG(ctx, GRN_LOG_ALERT,
+ "failed to initialize request canceler (%d)", rc);
+ return rc;
+ }
GRN_LOG(ctx, GRN_LOG_NOTICE, "grn_init");
check_overcommit_memory(ctx);
check_grn_ja_skip_same_value_put(ctx);
@@ -1379,8 +1427,9 @@ grn_fin(void)
}
}
query_logger_fin(ctx);
+ grn_request_canceler_fin();
grn_cache_fin();
- grn_token_fin();
+ grn_tokenizers_fin();
grn_normalizer_fin();
grn_plugins_fin();
grn_io_fin();
@@ -1396,7 +1445,6 @@ grn_rc
grn_ctx_connect(grn_ctx *ctx, const char *host, int port, int flags)
{
GRN_API_ENTER;
- if (!ctx->impl) { grn_ctx_impl_init(ctx); }
if (!ctx->impl) { goto exit; }
{
grn_com *com = grn_com_copen(ctx, NULL, host, port);
@@ -1428,16 +1476,6 @@ grn_ctx_get_command_version(grn_ctx *ctx)
}
}
-const char *
-grn_ctx_get_mime_type(grn_ctx *ctx)
-{
- if (ctx->impl) {
- return ctx->impl->mime_type;
- } else {
- return NULL;
- }
-}
-
grn_rc
grn_ctx_set_command_version(grn_ctx *ctx, grn_command_version version)
{
@@ -1456,6 +1494,40 @@ grn_ctx_set_command_version(grn_ctx *ctx, grn_command_version version)
}
}
+grn_content_type
+grn_ctx_get_output_type(grn_ctx *ctx)
+{
+ if (ctx->impl) {
+ return ctx->impl->output_type;
+ } else {
+ return GRN_CONTENT_NONE;
+ }
+}
+
+grn_rc
+grn_ctx_set_output_type(grn_ctx *ctx, grn_content_type type)
+{
+ grn_rc rc = GRN_SUCCESS;
+
+ if (ctx->impl) {
+ ctx->impl->output_type = type;
+ } else {
+ rc = GRN_INVALID_ARGUMENT;
+ }
+
+ return rc;
+}
+
+const char *
+grn_ctx_get_mime_type(grn_ctx *ctx)
+{
+ if (ctx->impl) {
+ return ctx->impl->mime_type;
+ } else {
+ return NULL;
+ }
+}
+
long long int
grn_ctx_get_match_escalation_threshold(grn_ctx *ctx)
{
@@ -1613,9 +1685,11 @@ get_command_version(grn_ctx *ctx, const char *p, const char *pe)
#define INDEX_HTML "index.html"
#define OUTPUT_TYPE "output_type"
#define COMMAND_VERSION "command_version"
+#define REQUEST_ID "request_id"
#define EXPR_MISSING "expr_missing"
#define OUTPUT_TYPE_LEN (sizeof(OUTPUT_TYPE) - 1)
#define COMMAND_VERSION_LEN (sizeof(COMMAND_VERSION) - 1)
+#define REQUEST_ID_LEN (sizeof(REQUEST_ID) - 1)
#define HTTP_QUERY_PAIR_DELIMITER "="
#define HTTP_QUERY_PAIRS_DELIMITERS "&;"
@@ -1631,8 +1705,10 @@ grn_obj *
grn_ctx_qe_exec_uri(grn_ctx *ctx, const char *path, uint32_t path_len)
{
grn_obj buf, *expr, *val;
+ grn_obj request_id;
const char *p = path, *e = path + path_len, *v, *key_end, *filename_end;
GRN_TEXT_INIT(&buf, 0);
+ GRN_TEXT_INIT(&request_id, 0);
p = grn_text_urldec(ctx, &buf, p, e, '?');
if (!GRN_TEXT_LEN(&buf)) { GRN_TEXT_SETS(ctx, &buf, INDEX_HTML); }
v = GRN_TEXT_VALUE(&buf);
@@ -1659,6 +1735,12 @@ grn_ctx_qe_exec_uri(grn_ctx *ctx, const char *path, uint32_t path_len)
p = grn_text_cgidec(ctx, &buf, p, e, HTTP_QUERY_PAIRS_DELIMITERS);
get_command_version(ctx, GRN_TEXT_VALUE(&buf), GRN_BULK_CURR(&buf));
if (ctx->rc) { goto exit; }
+ } else if (l == REQUEST_ID_LEN &&
+ !memcmp(v, REQUEST_ID, REQUEST_ID_LEN)) {
+ GRN_BULK_REWIND(&request_id);
+ p = grn_text_cgidec(ctx, &request_id, p, e,
+ HTTP_QUERY_PAIRS_DELIMITERS);
+ if (ctx->rc) { goto exit; }
} else {
if (!(val = grn_expr_get_or_add_var(ctx, expr, v, l))) {
val = &buf;
@@ -1667,8 +1749,18 @@ grn_ctx_qe_exec_uri(grn_ctx *ctx, const char *path, uint32_t path_len)
p = grn_text_cgidec(ctx, val, p, e, HTTP_QUERY_PAIRS_DELIMITERS);
}
}
+ if (GRN_TEXT_LEN(&request_id) > 0) {
+ grn_request_canceler_register(ctx,
+ GRN_TEXT_VALUE(&request_id),
+ GRN_TEXT_LEN(&request_id));
+ }
ctx->impl->curr_expr = expr;
grn_expr_exec(ctx, expr, 0);
+ if (GRN_TEXT_LEN(&request_id) > 0) {
+ grn_request_canceler_unregister(ctx,
+ GRN_TEXT_VALUE(&request_id),
+ GRN_TEXT_LEN(&request_id));
+ }
} else {
ERR(GRN_INVALID_ARGUMENT, "invalid command name: %.*s",
command_name_size, command_name);
@@ -1693,8 +1785,10 @@ grn_ctx_qe_exec(grn_ctx *ctx, const char *str, uint32_t str_len)
char tok_type;
int offset = 0;
grn_obj buf, *expr = NULL, *val = NULL;
+ grn_obj request_id;
const char *p = str, *e = str + str_len, *v;
GRN_TEXT_INIT(&buf, 0);
+ GRN_TEXT_INIT(&request_id, 0);
p = grn_text_unesc_tok(ctx, &buf, p, e, &tok_type);
expr = grn_ctx_get(ctx, GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf));
while (p < e) {
@@ -1720,6 +1814,11 @@ grn_ctx_qe_exec(grn_ctx *ctx, const char *str, uint32_t str_len)
p = grn_text_unesc_tok(ctx, &buf, p, e, &tok_type);
get_command_version(ctx, GRN_TEXT_VALUE(&buf), GRN_BULK_CURR(&buf));
if (ctx->rc) { goto exit; }
+ } else if (l == REQUEST_ID_LEN &&
+ !memcmp(v, REQUEST_ID, REQUEST_ID_LEN)) {
+ GRN_BULK_REWIND(&request_id);
+ p = grn_text_unesc_tok(ctx, &request_id, p, e, &tok_type);
+ if (ctx->rc) { goto exit; }
} else if (expr && (val = grn_expr_get_or_add_var(ctx, expr, v, l))) {
grn_obj_reinit(ctx, val, GRN_DB_TEXT, 0);
p = grn_text_unesc_tok(ctx, val, p, e, &tok_type);
@@ -1740,6 +1839,11 @@ grn_ctx_qe_exec(grn_ctx *ctx, const char *str, uint32_t str_len)
break;
}
}
+ if (GRN_TEXT_LEN(&request_id) > 0) {
+ grn_request_canceler_register(ctx,
+ GRN_TEXT_VALUE(&request_id),
+ GRN_TEXT_LEN(&request_id));
+ }
ctx->impl->curr_expr = expr;
if (expr && command_proc_p(expr)) {
grn_expr_exec(ctx, expr, 0);
@@ -1751,7 +1855,13 @@ grn_ctx_qe_exec(grn_ctx *ctx, const char *str, uint32_t str_len)
(int)GRN_TEXT_LEN(&buf), GRN_TEXT_VALUE(&buf));
}
}
+ if (GRN_TEXT_LEN(&request_id) > 0) {
+ grn_request_canceler_unregister(ctx,
+ GRN_TEXT_VALUE(&request_id),
+ GRN_TEXT_LEN(&request_id));
+ }
exit :
+ GRN_OBJ_FIN(ctx, &request_id);
GRN_OBJ_FIN(ctx, &buf);
return expr;
}
@@ -1991,7 +2101,7 @@ grn_cache_open(grn_ctx *ctx)
goto exit;
}
- cache->next = (grn_cache_entry*)cache;
+ cache->next = (grn_cache_entry *)cache;
cache->prev = (grn_cache_entry *)cache;
cache->hash = grn_hash_create(&grn_gctx, NULL, GRN_TABLE_MAX_KEY_SIZE,
sizeof(grn_cache_entry), GRN_OBJ_KEY_VAR_SIZE);
@@ -2208,7 +2318,6 @@ grn_ctx_alloc(grn_ctx *ctx, size_t size, int flags,
void *res = NULL;
if (!ctx) { return res; }
if (!ctx->impl) {
- grn_ctx_impl_init(ctx);
if (ERRP(ctx, GRN_ERROR)) { return res; }
}
CRITICAL_SECTION_ENTER(ctx->impl->lock);
@@ -2220,7 +2329,7 @@ grn_ctx_alloc(grn_ctx *ctx, size_t size, int flags,
if (size > GRN_CTX_SEGMENT_SIZE) {
uint64_t npages = (size + (grn_pagesize - 1)) / grn_pagesize;
if (npages >= (1LL<<32)) {
- MERR("too long request size=%zu", size);
+ MERR("too long request size=%" GRN_FMT_SIZE, size);
goto exit;
}
for (i = 0, mi = ctx->impl->segs;; i++, mi++) {
@@ -2395,7 +2504,6 @@ grn_ctx_use(grn_ctx *ctx, grn_obj *db)
if (db && !DB_P(db)) {
ctx->rc = GRN_INVALID_ARGUMENT;
} else {
- if (!ctx->impl) { grn_ctx_impl_init(ctx); }
if (!ctx->rc) {
ctx->impl->db = db;
if (db) {
@@ -2416,7 +2524,6 @@ grn_ctx_alloc_lifo(grn_ctx *ctx, size_t size,
{
if (!ctx) { return NULL; }
if (!ctx->impl) {
- grn_ctx_impl_init(ctx);
if (ERRP(ctx, GRN_ERROR)) { return NULL; }
}
{
@@ -2425,7 +2532,7 @@ grn_ctx_alloc_lifo(grn_ctx *ctx, size_t size,
if (size > GRN_CTX_SEGMENT_SIZE) {
uint64_t npages = (size + (grn_pagesize - 1)) / grn_pagesize;
if (npages >= (1LL<<32)) {
- MERR("too long request size=%zu", size);
+ MERR("too long request size=%" GRN_FMT_SIZE, size);
return NULL;
}
for (;;) {
@@ -2611,14 +2718,14 @@ grn_malloc_default(grn_ctx *ctx, size_t size, const char* file, int line, const
void *res = malloc(size);
if (res) {
GRN_ADD_ALLOC_COUNT(1);
- grn_alloc_info_add(res);
+ grn_alloc_info_add(res, file, line, func);
} else {
if (!(res = malloc(size))) {
- MERR("malloc fail (%zu)=%p (%s:%d) <%d>",
+ MERR("malloc fail (%" GRN_FMT_SIZE ")=%p (%s:%d) <%d>",
size, res, file, line, alloc_count);
} else {
GRN_ADD_ALLOC_COUNT(1);
- grn_alloc_info_add(res);
+ grn_alloc_info_add(res, file, line, func);
}
}
return res;
@@ -2633,7 +2740,7 @@ grn_calloc_default(grn_ctx *ctx, size_t size, const char* file, int line, const
void *res = calloc(size, 1);
if (res) {
GRN_ADD_ALLOC_COUNT(1);
- grn_alloc_info_add(res);
+ grn_alloc_info_add(res, file, line, func);
} else {
if (!(res = calloc(size, 1))) {
MERR("calloc fail (%" GRN_FMT_LLU ")=%p (%s:%d) <%" GRN_FMT_LLU ">",
@@ -2641,7 +2748,7 @@ grn_calloc_default(grn_ctx *ctx, size_t size, const char* file, int line, const
(unsigned long long int)alloc_count);
} else {
GRN_ADD_ALLOC_COUNT(1);
- grn_alloc_info_add(res);
+ grn_alloc_info_add(res, file, line, func);
}
}
return res;
@@ -2671,7 +2778,8 @@ grn_realloc_default(grn_ctx *ctx, void *ptr, size_t size, const char* file, int
if (size) {
if (!(res = realloc(ptr, size))) {
if (!(res = realloc(ptr, size))) {
- MERR("realloc fail (%p,%zu)=%p (%s:%d) <%d>", ptr, size, res, file, line, alloc_count);
+ MERR("realloc fail (%p,%" GRN_FMT_SIZE ")=%p (%s:%d) <%d>",
+ ptr, size, res, file, line, alloc_count);
return NULL;
}
}
@@ -2679,7 +2787,7 @@ grn_realloc_default(grn_ctx *ctx, void *ptr, size_t size, const char* file, int
grn_alloc_info_change(ptr, res);
} else {
GRN_ADD_ALLOC_COUNT(1);
- grn_alloc_info_add(res);
+ grn_alloc_info_add(res, file, line, func);
}
} else {
if (!ptr) { return NULL; }
@@ -2705,9 +2813,13 @@ grn_strdup_default(grn_ctx *ctx, const char *s, const char* file, int line, cons
char *res = strdup(s);
if (res) {
GRN_ADD_ALLOC_COUNT(1);
+ grn_alloc_info_add(res, file, line, func);
} else {
if (!(res = strdup(s))) {
MERR("strdup(%p)=%p (%s:%d) <%d>", s, res, file, line, alloc_count);
+ } else {
+ GRN_ADD_ALLOC_COUNT(1);
+ grn_alloc_info_add(res, file, line, func);
}
}
return res;
@@ -2758,7 +2870,8 @@ grn_realloc_fail(grn_ctx *ctx, void *ptr, size_t size, const char* file, int lin
if (grn_fail_malloc_check(size, file, line, func)) {
return grn_realloc_default(ctx, ptr, size, file, line, func);
} else {
- MERR("fail_realloc (%p,%zu) (%s:%d@%s) <%d>", ptr, size, file, line, func, alloc_count);
+ MERR("fail_realloc (%p,%" GRN_FMT_SIZE ") (%s:%d@%s) <%d>",
+ ptr, size, file, line, func, alloc_count);
return NULL;
}
}
@@ -2922,6 +3035,18 @@ grn_set_term_handler(void)
}
void
+grn_ctx_output_flush(grn_ctx *ctx, int flags)
+{
+ if (flags & GRN_CTX_QUIET) {
+ return;
+ }
+ if (!ctx->impl->output) {
+ return;
+ }
+ ctx->impl->output(ctx, 0, ctx->impl->data.ptr);
+}
+
+void
grn_ctx_output_array_open(grn_ctx *ctx, const char *name, int nelements)
{
grn_output_array_open(ctx, ctx->impl->outbuf, ctx->impl->output_type,
@@ -2990,3 +3115,25 @@ grn_ctx_output_obj(grn_ctx *ctx, grn_obj *value, grn_obj_format *format)
grn_output_obj(ctx, ctx->impl->outbuf, ctx->impl->output_type,
value, format);
}
+
+void
+grn_ctx_output_table_columns(grn_ctx *ctx, grn_obj *table,
+ grn_obj_format *format)
+{
+ grn_output_table_columns(ctx,
+ ctx->impl->outbuf,
+ ctx->impl->output_type,
+ table,
+ format);
+}
+
+void
+grn_ctx_output_table_records(grn_ctx *ctx, grn_obj *table,
+ grn_obj_format *format)
+{
+ grn_output_table_records(ctx,
+ ctx->impl->outbuf,
+ ctx->impl->output_type,
+ table,
+ format);
+}
diff --git a/storage/mroonga/vendor/groonga/lib/ctx_impl_mrb.c b/storage/mroonga/vendor/groonga/lib/ctx_impl_mrb.c
index 21531e4a837..05692eee13e 100644
--- a/storage/mroonga/vendor/groonga/lib/ctx_impl_mrb.c
+++ b/storage/mroonga/vendor/groonga/lib/ctx_impl_mrb.c
@@ -1,6 +1,6 @@
/* -*- c-basic-offset: 2 -*- */
/*
- Copyright(C) 2013-2014 Brazil
+ Copyright(C) 2013-2015 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -16,27 +16,67 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "ctx_impl_mrb.h"
-#include "ctx_impl.h"
-
-#include "mrb.h"
-#include "mrb/mrb_error.h"
-#include "mrb/mrb_id.h"
-#include "mrb/mrb_operator.h"
-#include "mrb/mrb_ctx.h"
-#include "mrb/mrb_logger.h"
-#include "mrb/mrb_void.h"
-#include "mrb/mrb_bulk.h"
-#include "mrb/mrb_obj.h"
-#include "mrb/mrb_column.h"
-#include "mrb/mrb_fixed_size_column.h"
-#include "mrb/mrb_variable_size_column.h"
-#include "mrb/mrb_index_column.h"
-#include "mrb/mrb_expr.h"
-#include "mrb/mrb_accessor.h"
-#include "mrb/mrb_procedure.h"
+#include "grn_ctx_impl.h"
#ifdef GRN_WITH_MRUBY
+# include <string.h>
+
+# include "grn_ctx_impl_mrb.h"
+
+# include "grn_mrb.h"
+# include "mrb/mrb_converter.h"
+# include "mrb/mrb_error.h"
+# include "mrb/mrb_id.h"
+# include "mrb/mrb_operator.h"
+# include "mrb/mrb_ctx.h"
+# include "mrb/mrb_logger.h"
+# include "mrb/mrb_void.h"
+# include "mrb/mrb_bulk.h"
+# include "mrb/mrb_object.h"
+# include "mrb/mrb_database.h"
+# include "mrb/mrb_table.h"
+# include "mrb/mrb_array.h"
+# include "mrb/mrb_hash_table.h"
+# include "mrb/mrb_patricia_trie.h"
+# include "mrb/mrb_double_array_trie.h"
+# include "mrb/mrb_column.h"
+# include "mrb/mrb_fixed_size_column.h"
+# include "mrb/mrb_variable_size_column.h"
+# include "mrb/mrb_index_column.h"
+# include "mrb/mrb_index_cursor.h"
+# include "mrb/mrb_type.h"
+# include "mrb/mrb_expr.h"
+# include "mrb/mrb_accessor.h"
+# include "mrb/mrb_procedure.h"
+# include "mrb/mrb_command.h"
+# include "mrb/mrb_command_input.h"
+# include "mrb/mrb_table_cursor.h"
+# include "mrb/mrb_table_cursor_flags.h"
+# include "mrb/mrb_writer.h"
+
+# include <mruby/array.h>
+# include <mruby/variable.h>
+#endif /* GRN_WITH_MRUBY */
+
+#ifdef GRN_WITH_MRUBY
+static mrb_value
+mrb_kernel_load(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ char *path;
+
+ mrb_get_args(mrb, "z", &path);
+
+ grn_mrb_load(ctx, path);
+ if (mrb->exc) {
+ mrb_exc_raise(mrb, mrb_obj_value(mrb->exc));
+ }
+
+ grn_mrb_ctx_check(mrb);
+
+ return mrb_true_value();
+}
+
static void
grn_ctx_impl_mrb_init_bindings(grn_ctx *ctx)
{
@@ -45,8 +85,29 @@ grn_ctx_impl_mrb_init_bindings(grn_ctx *ctx)
mrb->ud = ctx;
ctx->impl->mrb.module = mrb_define_module(mrb, "Groonga");
- grn_mrb_load(ctx, "backtrace_entry.rb");
+ mrb_define_class(mrb, "LoadError", mrb_class_get(mrb, "ScriptError"));
+ mrb_define_method(mrb, mrb->kernel_module,
+ "load", mrb_kernel_load, MRB_ARGS_REQ(1));
+
+ {
+ mrb_value load_path;
+ const char *plugins_dir;
+ const char *system_ruby_scripts_dir;
+
+ load_path = mrb_ary_new(mrb);
+ plugins_dir = grn_plugin_get_system_plugins_dir();
+ mrb_ary_push(mrb, load_path,
+ mrb_str_new_cstr(mrb, plugins_dir));
+ system_ruby_scripts_dir = grn_mrb_get_system_ruby_scripts_dir(ctx);
+ mrb_ary_push(mrb, load_path,
+ mrb_str_new_cstr(mrb, system_ruby_scripts_dir));
+ mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$LOAD_PATH"), load_path);
+ }
+
+ grn_mrb_load(ctx, "require.rb");
+ grn_mrb_load(ctx, "initialize/pre.rb");
+ grn_mrb_converter_init(ctx);
grn_mrb_error_init(ctx);
grn_mrb_id_init(ctx);
grn_mrb_operator_init(ctx);
@@ -54,20 +115,29 @@ grn_ctx_impl_mrb_init_bindings(grn_ctx *ctx)
grn_mrb_logger_init(ctx);
grn_mrb_void_init(ctx);
grn_mrb_bulk_init(ctx);
- grn_mrb_obj_init(ctx);
+ grn_mrb_object_init(ctx);
+ grn_mrb_database_init(ctx);
+ grn_mrb_table_init(ctx);
+ grn_mrb_array_init(ctx);
+ grn_mrb_hash_table_init(ctx);
+ grn_mrb_patricia_trie_init(ctx);
+ grn_mrb_double_array_trie_init(ctx);
grn_mrb_column_init(ctx);
grn_mrb_fixed_size_column_init(ctx);
grn_mrb_variable_size_column_init(ctx);
grn_mrb_index_column_init(ctx);
+ grn_mrb_index_cursor_init(ctx);
+ grn_mrb_type_init(ctx);
grn_mrb_expr_init(ctx);
grn_mrb_accessor_init(ctx);
grn_mrb_procedure_init(ctx);
-}
+ grn_mrb_command_init(ctx);
+ grn_mrb_command_input_init(ctx);
+ grn_mrb_table_cursor_init(ctx);
+ grn_mrb_table_cursor_flags_init(ctx);
+ grn_mrb_writer_init(ctx);
-static void
-grn_ctx_impl_mrb_init_eval(grn_ctx *ctx)
-{
- grn_mrb_load(ctx, "eval_context.rb");
+ grn_mrb_load(ctx, "initialize/post.rb");
}
void
@@ -77,11 +147,30 @@ grn_ctx_impl_mrb_init(grn_ctx *ctx)
grn_mruby_enabled = getenv("GRN_MRUBY_ENABLED");
if (grn_mruby_enabled && strcmp(grn_mruby_enabled, "no") == 0) {
ctx->impl->mrb.state = NULL;
+ ctx->impl->mrb.base_directory[0] = '\0';
ctx->impl->mrb.module = NULL;
+ ctx->impl->mrb.object_class = NULL;
+ ctx->impl->mrb.checked_procs = NULL;
+ ctx->impl->mrb.registered_plugins = NULL;
+ ctx->impl->mrb.builtin.time_class = NULL;
} else {
- ctx->impl->mrb.state = mrb_open();
+ mrb_state *mrb;
+
+ mrb = mrb_open();
+ ctx->impl->mrb.state = mrb;
+ ctx->impl->mrb.base_directory[0] = '\0';
grn_ctx_impl_mrb_init_bindings(ctx);
- grn_ctx_impl_mrb_init_eval(ctx);
+ /* TODO: Implement better error handling on init. */
+ if (ctx->impl->mrb.state->exc) {
+ mrb_print_error(mrb);
+ }
+ ctx->impl->mrb.checked_procs =
+ grn_hash_create(ctx, NULL, sizeof(grn_id), 0, GRN_HASH_TINY);
+ ctx->impl->mrb.registered_plugins =
+ grn_hash_create(ctx, NULL, sizeof(grn_id), 0, GRN_HASH_TINY);
+ GRN_VOID_INIT(&(ctx->impl->mrb.buffer.from));
+ GRN_VOID_INIT(&(ctx->impl->mrb.buffer.to));
+ ctx->impl->mrb.builtin.time_class = mrb_class_get(mrb, "Time");
}
}
@@ -91,9 +180,13 @@ grn_ctx_impl_mrb_fin(grn_ctx *ctx)
if (ctx->impl->mrb.state) {
mrb_close(ctx->impl->mrb.state);
ctx->impl->mrb.state = NULL;
+ grn_hash_close(ctx, ctx->impl->mrb.checked_procs);
+ grn_hash_close(ctx, ctx->impl->mrb.registered_plugins);
+ GRN_OBJ_FIN(ctx, &(ctx->impl->mrb.buffer.from));
+ GRN_OBJ_FIN(ctx, &(ctx->impl->mrb.buffer.to));
}
}
-#else
+#else /* GRN_WITH_MRUBY */
void
grn_ctx_impl_mrb_init(grn_ctx *ctx)
{
@@ -103,4 +196,4 @@ void
grn_ctx_impl_mrb_fin(grn_ctx *ctx)
{
}
-#endif
+#endif /* GRN_WITH_MRUBY */
diff --git a/storage/mroonga/vendor/groonga/lib/dat.cpp b/storage/mroonga/vendor/groonga/lib/dat.cpp
index 8588857cd5d..4a3db12d67d 100644
--- a/storage/mroonga/vendor/groonga/lib/dat.cpp
+++ b/storage/mroonga/vendor/groonga/lib/dat.cpp
@@ -14,16 +14,16 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "groonga_in.h"
+#include "grn.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <cstring>
#include <new>
-#include "str.h"
-#include "io.h"
-#include "dat.h"
-#include "util.h"
-#include "normalizer_in.h"
+#include "grn_str.h"
+#include "grn_io.h"
+#include "grn_dat.h"
+#include "grn_util.h"
+#include "grn_normalizer.h"
#include "dat/trie.hpp"
#include "dat/cursor-factory.hpp"
@@ -678,12 +678,18 @@ grn_dat_scan(grn_ctx *ctx, grn_dat *dat, const char *str,
{
if (!grn_dat_open_trie_if_needed(ctx, dat) || !str ||
!(dat->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) || !scan_hits) {
+ if (str_rest) {
+ *str_rest = str;
+ }
return -1;
}
grn::dat::Trie * const trie = static_cast<grn::dat::Trie *>(dat->trie);
if (!trie) {
- return -1;
+ if (str_rest) {
+ *str_rest = str + str_size;
+ }
+ return 0;
}
if (!max_num_scan_hits || !str_size) {
@@ -701,7 +707,9 @@ grn_dat_scan(grn_ctx *ctx, grn_dat *dat, const char *str,
dat->normalizer,
flags);
if (!normalized_string) {
- *str_rest = str;
+ if (str_rest) {
+ *str_rest = str;
+ }
return -1;
}
grn_string_get_normalized(ctx, normalized_string, &str, &str_size, NULL);
@@ -778,6 +786,9 @@ grn_dat_scan(grn_ctx *ctx, grn_dat *dat, const char *str,
} catch (const grn::dat::Exception &ex) {
ERR(grn_dat_translate_error_code(ex.code()),
"grn::dat::lcp_search failed");
+ if (str_rest) {
+ *str_rest = str;
+ }
return -1;
}
return static_cast<int>(num_scan_hits);
diff --git a/storage/mroonga/vendor/groonga/lib/dat/Makefile.am b/storage/mroonga/vendor/groonga/lib/dat/Makefile.am
index 6bad7730de4..0a58629cc77 100644
--- a/storage/mroonga/vendor/groonga/lib/dat/Makefile.am
+++ b/storage/mroonga/vendor/groonga/lib/dat/Makefile.am
@@ -2,8 +2,7 @@ DEFS += -D_REENTRANT $(GRN_DEFS) -DGRN_DAT_EXPORT
DEFAULT_INCLUDES = \
-I$(top_builddir) \
- -I$(top_srcdir)/include \
- -I$(top_srcdir)/lib
+ -I$(top_srcdir)/include
noinst_LTLIBRARIES = libgrndat.la
diff --git a/storage/mroonga/vendor/groonga/lib/dat/dat.hpp b/storage/mroonga/vendor/groonga/lib/dat/dat.hpp
index a2b225a9cf4..d2b2264752b 100644
--- a/storage/mroonga/vendor/groonga/lib/dat/dat.hpp
+++ b/storage/mroonga/vendor/groonga/lib/dat/dat.hpp
@@ -175,13 +175,6 @@ class Exception : public std::exception {
what_(ex.what_) {}
virtual ~Exception() throw() {}
- virtual Exception &operator=(const Exception &ex) throw() {
- file_ = ex.file_;
- line_ = ex.line_;
- what_ = ex.what_;
- return *this;
- }
-
virtual ErrorCode code() const throw() = 0;
virtual const char *file() const throw() {
return file_;
@@ -210,11 +203,6 @@ class Error : public Exception {
: Exception(ex) {}
virtual ~Error() throw() {}
- virtual Error &operator=(const Error &ex) throw() {
- *static_cast<Exception *>(this) = ex;
- return *this;
- }
-
virtual ErrorCode code() const throw() {
return T;
}
diff --git a/storage/mroonga/vendor/groonga/lib/dat/file-impl.cpp b/storage/mroonga/vendor/groonga/lib/dat/file-impl.cpp
index 6382ae965a9..3643a806292 100644
--- a/storage/mroonga/vendor/groonga/lib/dat/file-impl.cpp
+++ b/storage/mroonga/vendor/groonga/lib/dat/file-impl.cpp
@@ -36,6 +36,12 @@
#include <algorithm>
#include <limits>
+#ifdef WIN32
+# define GRN_IO_FILE_CREATE_MODE (GENERIC_READ | GENERIC_WRITE)
+#else /* WIN32 */
+# define GRN_IO_FILE_CREATE_MODE 0644
+#endif /* WIN32 */
+
namespace grn {
namespace dat {
@@ -119,7 +125,7 @@ void FileImpl::swap(FileImpl *rhs) {
void FileImpl::create_(const char *path, UInt64 size) {
if ((path != NULL) && (path[0] != '\0')) {
- file_ = ::CreateFileA(path, GENERIC_READ | GENERIC_WRITE,
+ file_ = ::CreateFileA(path, GRN_IO_FILE_CREATE_MODE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
GRN_DAT_THROW_IF(IO_ERROR, file_ == INVALID_HANDLE_VALUE);
@@ -162,7 +168,7 @@ void FileImpl::open_(const char *path) {
GRN_DAT_THROW_IF(IO_ERROR,
static_cast<UInt64>(st.st_size) > std::numeric_limits< ::size_t>::max());
- file_ = ::CreateFileA(path, GENERIC_READ | GENERIC_WRITE,
+ file_ = ::CreateFileA(path, GRN_IO_FILE_CREATE_MODE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
GRN_DAT_THROW_IF(IO_ERROR, file_ == NULL);
@@ -192,7 +198,7 @@ void FileImpl::create_(const char *path, UInt64 size) {
size > static_cast<UInt64>(std::numeric_limits< ::off_t>::max()));
if ((path != NULL) && (path[0] != '\0')) {
- fd_ = ::open(path, O_RDWR | O_CREAT | O_TRUNC, 0666);
+ fd_ = ::open(path, O_RDWR | O_CREAT | O_TRUNC, GRN_IO_FILE_CREATE_MODE);
GRN_DAT_THROW_IF(IO_ERROR, fd_ == -1);
const ::off_t file_size = static_cast< ::off_t>(size);
diff --git a/storage/mroonga/vendor/groonga/lib/db.c b/storage/mroonga/vendor/groonga/lib/db.c
index f948dc7353a..b9cea065a6a 100644
--- a/storage/mroonga/vendor/groonga/lib/db.c
+++ b/storage/mroonga/vendor/groonga/lib/db.c
@@ -1,5 +1,5 @@
/* -*- c-basic-offset: 2 -*- */
-/* Copyright(C) 2009-2014 Brazil
+/* Copyright(C) 2009-2015 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -14,21 +14,23 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "groonga_in.h"
-#include "db.h"
-#include "hash.h"
-#include "pat.h"
-#include "dat.h"
-#include "ii.h"
-#include "ctx_impl.h"
-#include "token.h"
-#include "proc.h"
-#include "plugin_in.h"
-#include "geo.h"
-#include "snip.h"
-#include "string_in.h"
-#include "normalizer_in.h"
-#include "util.h"
+#include "grn.h"
+#include "grn_db.h"
+#include "grn_hash.h"
+#include "grn_pat.h"
+#include "grn_dat.h"
+#include "grn_ii.h"
+#include "grn_ctx_impl.h"
+#include "grn_token_cursor.h"
+#include "grn_tokenizers.h"
+#include "grn_proc.h"
+#include "grn_plugin.h"
+#include "grn_geo.h"
+#include "grn_scorers.h"
+#include "grn_snip.h"
+#include "grn_string.h"
+#include "grn_normalizer.h"
+#include "grn_util.h"
#include <string.h>
#include <float.h>
@@ -46,6 +48,9 @@ typedef struct {
((table)->header.impl_flags & GRN_TABLE_GROUPED)
#define GRN_TABLE_GROUPED_ON(table)\
((table)->header.impl_flags |= GRN_TABLE_GROUPED)
+#define GRN_TABLE_IS_MULTI_KEYS_GROUPED(table)\
+ (GRN_TABLE_IS_GROUPED(table) &&\
+ table->header.domain == GRN_ID_NIL)
#define WITH_NORMALIZE(table,key,key_size,block) do {\
if ((table)->normalizer && key && key_size > 0) {\
@@ -67,7 +72,7 @@ inline static grn_id
grn_table_add_v_inline(grn_ctx *ctx, grn_obj *table, const void *key, int key_size,
void **value, int *added);
inline static void
-grn_table_add_subrec_inline(grn_obj *table, grn_rset_recinfo *ri, int score,
+grn_table_add_subrec_inline(grn_obj *table, grn_rset_recinfo *ri, double score,
grn_rset_posinfo *pi, int dir);
inline static grn_id
grn_table_cursor_next_inline(grn_ctx *ctx, grn_table_cursor *tc);
@@ -78,6 +83,10 @@ static void grn_obj_ensure_bulk(grn_ctx *ctx, grn_obj *obj);
static void grn_obj_ensure_vector(grn_ctx *ctx, grn_obj *obj);
inline static void
+grn_obj_get_range_info(grn_ctx *ctx, grn_obj *obj,
+ grn_id *range_id, grn_obj_flags *range_flags);
+
+inline static void
gen_pathname(const char *path, char *buffer, int fno)
{
size_t len = strlen(path);
@@ -252,6 +261,7 @@ grn_db_open(grn_ctx *ctx, const char *path)
#endif
grn_db_init_builtin_tokenizers(ctx);
grn_db_init_builtin_normalizers(ctx);
+ grn_db_init_builtin_scorers(ctx);
grn_db_init_builtin_query(ctx);
GRN_API_RETURN((grn_obj *)s);
}
@@ -582,12 +592,17 @@ grn_proc_create(grn_ctx *ctx, const char *name, int name_size, grn_proc_type typ
if (!added) {
db_value *vp;
if ((vp = grn_tiny_array_at(&s->values, id)) && (res = (grn_proc *)vp->ptr)) {
+ /* TODO: Do more robust check. */
if (res->funcs[PROC_INIT] ||
res->funcs[PROC_NEXT] ||
res->funcs[PROC_FIN]) {
ERR(GRN_INVALID_ARGUMENT, "already used name");
GRN_API_RETURN(NULL);
}
+ if (range != GRN_ID_NIL) {
+ grn_plugin_close(ctx, range);
+ }
+ GRN_API_RETURN((grn_obj *)res);
} else {
added = 1;
}
@@ -609,6 +624,7 @@ grn_proc_create(grn_ctx *ctx, const char *name, int name_size, grn_proc_type typ
res->funcs[PROC_NEXT] = next;
res->funcs[PROC_FIN] = fin;
res->selector = NULL;
+ memset(&(res->callbacks), 0, sizeof(res->callbacks));
GRN_TEXT_INIT(&res->name_buf, 0);
res->vars = NULL;
res->nvars = 0;
@@ -633,6 +649,7 @@ grn_proc_create(grn_ctx *ctx, const char *name, int name_size, grn_proc_type typ
static void
calc_rec_size(grn_obj_flags flags, uint32_t max_n_subrecs, uint32_t range_size,
+ uint32_t additional_value_size,
uint8_t *subrec_size, uint8_t *subrec_offset,
uint32_t *key_size, uint32_t *value_size)
{
@@ -676,6 +693,7 @@ calc_rec_size(grn_obj_flags flags, uint32_t max_n_subrecs, uint32_t range_size,
} else {
*value_size = range_size;
}
+ *value_size += additional_value_size;
}
static void _grn_obj_remove(grn_ctx *ctx, grn_obj *obj);
@@ -728,7 +746,9 @@ static grn_obj *
grn_table_create_with_max_n_subrecs(grn_ctx *ctx, const char *name,
unsigned int name_size, const char *path,
grn_obj_flags flags, grn_obj *key_type,
- grn_obj *value_type, uint32_t max_n_subrecs)
+ grn_obj *value_type,
+ uint32_t max_n_subrecs,
+ uint32_t additional_value_size)
{
grn_id id;
grn_id domain = GRN_ID_NIL, range = GRN_ID_NIL;
@@ -862,8 +882,8 @@ grn_table_create_with_max_n_subrecs(grn_ctx *ctx, const char *name,
return NULL;
}
}
- calc_rec_size(flags, max_n_subrecs, range_size, &subrec_size,
- &subrec_offset, &key_size, &value_size);
+ calc_rec_size(flags, max_n_subrecs, range_size, additional_value_size,
+ &subrec_size, &subrec_offset, &key_size, &value_size);
switch (flags & GRN_OBJ_TABLE_TYPE_MASK) {
case GRN_OBJ_TABLE_HASH_KEY :
res = (grn_obj *)grn_hash_create(ctx, path, key_size, value_size, flags);
@@ -886,6 +906,7 @@ grn_table_create_with_max_n_subrecs(grn_ctx *ctx, const char *name,
DB_OBJ(res)->max_n_subrecs = max_n_subrecs;
DB_OBJ(res)->subrec_size = subrec_size;
DB_OBJ(res)->subrec_offset = subrec_offset;
+ DB_OBJ(res)->flags.group = 0;
if (grn_db_obj_init(ctx, db, id, DB_OBJ(res))) {
_grn_obj_remove(ctx, res);
res = NULL;
@@ -904,7 +925,8 @@ grn_table_create(grn_ctx *ctx, const char *name, unsigned int name_size,
grn_obj *res;
GRN_API_ENTER;
res = grn_table_create_with_max_n_subrecs(ctx, name, name_size, path,
- flags, key_type, value_type, 0);
+ flags, key_type, value_type,
+ 0, 0);
GRN_API_RETURN(res);
}
@@ -915,15 +937,27 @@ grn_table_create_for_group(grn_ctx *ctx, const char *name,
unsigned int max_n_subrecs)
{
grn_obj *res = NULL;
- grn_obj *key_type;
GRN_API_ENTER;
- key_type = grn_ctx_at(ctx, grn_obj_get_range(ctx, group_key));
- if (key_type) {
+ if (group_key) {
+ grn_obj *key_type;
+ key_type = grn_ctx_at(ctx, grn_obj_get_range(ctx, group_key));
+ if (key_type) {
+ res = grn_table_create_with_max_n_subrecs(ctx, name, name_size, path,
+ GRN_TABLE_HASH_KEY|
+ GRN_OBJ_WITH_SUBREC|
+ GRN_OBJ_UNIT_USERDEF_DOCUMENT,
+ key_type, value_type,
+ max_n_subrecs, 0);
+ grn_obj_unlink(ctx, key_type);
+ }
+ } else {
res = grn_table_create_with_max_n_subrecs(ctx, name, name_size, path,
GRN_TABLE_HASH_KEY|
+ GRN_OBJ_KEY_VAR_SIZE|
GRN_OBJ_WITH_SUBREC|
GRN_OBJ_UNIT_USERDEF_DOCUMENT,
- key_type, value_type, max_n_subrecs);
+ NULL, value_type,
+ max_n_subrecs, 0);
}
GRN_API_RETURN(res);
}
@@ -957,7 +991,7 @@ grn_table_get_subrecs(grn_ctx *ctx, grn_obj *table, grn_id id,
}
for (; count < limit; count++) {
if (scorebuf) {
- scorebuf[count] = *((int *)psubrec);
+ scorebuf[count] = *((double *)psubrec);
}
psubrec += GRN_RSET_SCORE_SIZE;
if (subrecbuf) {
@@ -1681,6 +1715,22 @@ delete_reference_records(grn_ctx *ctx, grn_obj *table, grn_id id)
return ctx->rc;
}
+static grn_rc
+grn_table_delete_prepare(grn_ctx *ctx, grn_obj *table,
+ grn_id id, const void *key, unsigned int key_size)
+{
+ grn_rc rc;
+
+ rc = delete_reference_records(ctx, table, id);
+ if (rc != GRN_SUCCESS) {
+ return rc;
+ }
+ call_delete_hook(ctx, table, id, key, key_size);
+ clear_column_values(ctx, table, id);
+
+ return rc;
+}
+
grn_rc
grn_table_delete(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key_size)
{
@@ -1690,12 +1740,10 @@ grn_table_delete(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key
if (table) {
if (key && key_size) { rid = grn_table_get(ctx, table, key, key_size); }
if (rid) {
- rc = delete_reference_records(ctx, table, rid);
+ rc = grn_table_delete_prepare(ctx, table, rid, key, key_size);
if (rc != GRN_SUCCESS) {
goto exit;
}
- call_delete_hook(ctx, table, rid, key, key_size);
- clear_column_values(ctx, table, rid);
switch (table->header.type) {
case GRN_DB :
/* todo : delete tables and columns from db */
@@ -1740,10 +1788,12 @@ grn_table_delete(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key
});
break;
}
- grn_obj_touch(ctx, table, NULL);
+ if (rc == GRN_SUCCESS) {
+ grn_obj_touch(ctx, table, NULL);
+ }
}
}
-exit:
+exit :
GRN_API_RETURN(rc);
}
@@ -1753,16 +1803,17 @@ _grn_table_delete_by_id(grn_ctx *ctx, grn_obj *table, grn_id id,
{
grn_rc rc = GRN_INVALID_ARGUMENT;
if (table) {
- const void *key;
- unsigned int key_size;
if (id) {
- rc = delete_reference_records(ctx, table, id);
+ const void *key = NULL;
+ unsigned int key_size = 0;
+
+ if (table->header.type != GRN_TABLE_NO_KEY) {
+ key = _grn_table_key(ctx, table, id, &key_size);
+ }
+ rc = grn_table_delete_prepare(ctx, table, id, key, key_size);
if (rc != GRN_SUCCESS) {
goto exit;
}
- if ((key = _grn_table_key(ctx, table, id, &key_size))) {
- call_delete_hook(ctx, table, id, key, key_size);
- }
// todo : support optarg
switch (table->header.type) {
case GRN_TABLE_PAT_KEY :
@@ -1778,12 +1829,9 @@ _grn_table_delete_by_id(grn_ctx *ctx, grn_obj *table, grn_id id,
rc = grn_array_delete_by_id(ctx, (grn_array *)table, id, optarg);
break;
}
- if (rc == GRN_SUCCESS) {
- clear_column_values(ctx, table, id);
- }
}
}
-exit:
+exit :
return rc;
}
@@ -1801,7 +1849,9 @@ grn_table_delete_by_id(grn_ctx *ctx, grn_obj *table, grn_id id)
} else {
rc = _grn_table_delete_by_id(ctx, table, id, NULL);
}
- grn_obj_touch(ctx, table, NULL);
+ if (rc == GRN_SUCCESS) {
+ grn_obj_touch(ctx, table, NULL);
+ }
GRN_API_RETURN(rc);
}
@@ -1839,6 +1889,9 @@ grn_column_truncate(grn_ctx *ctx, grn_obj *column)
rc = grn_ra_truncate(ctx, (grn_ra *)column);
break;
}
+ if (rc == GRN_SUCCESS) {
+ grn_obj_touch(ctx, column, NULL);
+ }
}
exit :
GRN_API_RETURN(rc);
@@ -1905,7 +1958,9 @@ grn_table_truncate(grn_ctx *ctx, grn_obj *table)
grn_obj_set_info(ctx, table, GRN_INFO_NORMALIZER, normalizer);
grn_obj_set_info(ctx, table, GRN_INFO_TOKEN_FILTERS, &token_filters);
GRN_OBJ_FIN(ctx, &token_filters);
- grn_obj_touch(ctx, table, NULL);
+ if (rc == GRN_SUCCESS) {
+ grn_obj_touch(ctx, table, NULL);
+ }
}
exit :
GRN_API_RETURN(rc);
@@ -1948,7 +2003,7 @@ grn_table_get_info(grn_ctx *ctx, grn_obj *table, grn_obj_flags *flags,
case GRN_TABLE_NO_KEY :
if (flags) { *flags = 0; }
if (encoding) { *encoding = GRN_ENC_NONE; }
- if (tokenizer) { *tokenizer = grn_token_uvector; }
+ if (tokenizer) { *tokenizer = grn_tokenizer_uvector; }
if (normalizer) { *normalizer = NULL; }
if (token_filters) { *token_filters = NULL; }
rc = GRN_SUCCESS;
@@ -1991,10 +2046,10 @@ grn_table_size(grn_ctx *ctx, grn_obj *table)
}
inline static void
-subrecs_push(byte *subrecs, int size, int n_subrecs, int score, void *body, int dir)
+subrecs_push(byte *subrecs, int size, int n_subrecs, double score, void *body, int dir)
{
byte *v;
- int *c2;
+ double *c2;
int n = n_subrecs - 1, n2;
while (n) {
n2 = (n - 1) >> 1;
@@ -2004,15 +2059,16 @@ subrecs_push(byte *subrecs, int size, int n_subrecs, int score, void *body, int
n = n2;
}
v = subrecs + n * (GRN_RSET_SCORE_SIZE + size);
- *((int *)v) = score;
+ *((double *)v) = score;
memcpy(v + GRN_RSET_SCORE_SIZE, body, size);
}
inline static void
-subrecs_replace_min(byte *subrecs, int size, int n_subrecs, int score, void *body, int dir)
+subrecs_replace_min(byte *subrecs, int size, int n_subrecs, double score, void *body, int dir)
{
byte *v;
- int n = 0, n1, n2, *c1, *c2;
+ int n = 0, n1, n2;
+ double *c1, *c2;
for (;;) {
n1 = n * 2 + 1;
n2 = n1 + 1;
@@ -2043,7 +2099,7 @@ subrecs_replace_min(byte *subrecs, int size, int n_subrecs, int score, void *bod
}
inline static void
-grn_table_add_subrec_inline(grn_obj *table, grn_rset_recinfo *ri, int score,
+grn_table_add_subrec_inline(grn_obj *table, grn_rset_recinfo *ri, double score,
grn_rset_posinfo *pi, int dir)
{
if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) {
@@ -2056,7 +2112,7 @@ grn_table_add_subrec_inline(grn_obj *table, grn_rset_recinfo *ri, int score,
if (pi) {
byte *body = (byte *)pi + DB_OBJ(table)->subrec_offset;
if (limit < n_subrecs) {
- if (GRN_RSET_SUBRECS_CMP(score, *ri->subrecs, dir) > 0) {
+ if (GRN_RSET_SUBRECS_CMP(score, *((double *)(ri->subrecs)), dir) > 0) {
subrecs_replace_min((byte *)ri->subrecs, subrec_size, limit, score, body, dir);
}
} else {
@@ -2068,7 +2124,7 @@ grn_table_add_subrec_inline(grn_obj *table, grn_rset_recinfo *ri, int score,
}
void
-grn_table_add_subrec(grn_obj *table, grn_rset_recinfo *ri, int score,
+grn_table_add_subrec(grn_obj *table, grn_rset_recinfo *ri, double score,
grn_rset_posinfo *pi, int dir)
{
grn_table_add_subrec_inline(table, ri, score, pi, dir);
@@ -2389,24 +2445,58 @@ grn_table_cursor_delete(grn_ctx *ctx, grn_table_cursor *tc)
if (!tc) {
ERR(GRN_INVALID_ARGUMENT, "tc is null");
} else {
+ grn_id id;
+ grn_obj *table;
+ const void *key = NULL;
+ unsigned int key_size = 0;
switch (tc->header.type) {
case GRN_CURSOR_TABLE_PAT_KEY :
- rc = grn_pat_cursor_delete(ctx, (grn_pat_cursor *)tc, NULL);
+ {
+ grn_pat_cursor *pc = (grn_pat_cursor *)tc;
+ id = pc->curr_rec;
+ table = (grn_obj *)(pc->pat);
+ key = _grn_pat_key(ctx, pc->pat, id, &key_size);
+ rc = grn_table_delete_prepare(ctx, table, id, key, key_size);
+ if (rc != GRN_SUCCESS) {
+ goto exit;
+ }
+ rc = grn_pat_cursor_delete(ctx, pc, NULL);
+ }
break;
case GRN_CURSOR_TABLE_DAT_KEY :
rc = GRN_OPERATION_NOT_SUPPORTED;
break;
case GRN_CURSOR_TABLE_HASH_KEY :
- rc = grn_hash_cursor_delete(ctx, (grn_hash_cursor *)tc, NULL);
+ {
+ grn_hash_cursor *hc = (grn_hash_cursor *)tc;
+ id = hc->curr_rec;
+ table = (grn_obj *)(hc->hash);
+ key = _grn_hash_key(ctx, hc->hash, id, &key_size);
+ rc = grn_table_delete_prepare(ctx, table, id, key, key_size);
+ if (rc != GRN_SUCCESS) {
+ goto exit;
+ }
+ rc = grn_hash_cursor_delete(ctx, hc, NULL);
+ }
break;
case GRN_CURSOR_TABLE_NO_KEY :
- rc = grn_array_cursor_delete(ctx, (grn_array_cursor *)tc, NULL);
+ {
+ grn_array_cursor *ac = (grn_array_cursor *)tc;
+ id = ac->curr_rec;
+ table = (grn_obj *)(ac->array);
+ rc = grn_table_delete_prepare(ctx, table, id, key, key_size);
+ if (rc != GRN_SUCCESS) {
+ goto exit;
+ }
+ rc = grn_array_cursor_delete(ctx, ac, NULL);
+ }
break;
default :
ERR(GRN_INVALID_ARGUMENT, "invalid type %d", tc->header.type);
break;
}
}
+exit :
GRN_API_RETURN(rc);
}
@@ -2975,9 +3065,42 @@ grn_obj_search(grn_ctx *ctx, grn_obj *obj, grn_obj *query,
#define GRN_TABLE_GROUP_FILTER_PREFIX 0
#define GRN_TABLE_GROUP_FILTER_SUFFIX (1L<<2)
-static int
-accelerated_table_group(grn_ctx *ctx, grn_obj *table, grn_obj *key, grn_obj *res)
+inline static void
+grn_table_group_add_subrec(grn_ctx *ctx,
+ grn_obj *table,
+ grn_rset_recinfo *ri, double score,
+ grn_rset_posinfo *pi, int dir,
+ grn_obj *calc_target,
+ grn_obj *value_buffer)
{
+ grn_table_group_flags flags;
+
+ if (!(DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC)) {
+ return;
+ }
+
+ grn_table_add_subrec_inline(table, ri, score, pi, dir);
+
+ flags = DB_OBJ(table)->flags.group;
+
+ if (!(flags & (GRN_TABLE_GROUP_CALC_MAX |
+ GRN_TABLE_GROUP_CALC_MIN |
+ GRN_TABLE_GROUP_CALC_SUM |
+ GRN_TABLE_GROUP_CALC_AVG))) {
+ return;
+ }
+
+ GRN_BULK_REWIND(value_buffer);
+ grn_obj_get_value(ctx, calc_target, pi->rid, value_buffer);
+ grn_rset_recinfo_update_calc_values(ctx, ri, table, value_buffer);
+}
+
+static grn_bool
+accelerated_table_group(grn_ctx *ctx, grn_obj *table, grn_obj *key,
+ grn_table_group_result *result)
+{
+ grn_obj *res = result->table;
+ grn_obj *calc_target = result->calc_target;
if (key->header.type == GRN_ACCESSOR) {
grn_accessor *a = (grn_accessor *)key;
if (a->action == GRN_ACCESSOR_GET_KEY &&
@@ -2987,6 +3110,9 @@ accelerated_table_group(grn_ctx *ctx, grn_obj *table, grn_obj *key, grn_obj *res
int idp = GRN_OBJ_TABLEP(range);
grn_table_cursor *tc;
if ((tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0))) {
+ grn_bool processed = GRN_TRUE;
+ grn_obj value_buffer;
+ GRN_VOID_INIT(&value_buffer);
switch (a->next->obj->header.type) {
case GRN_COLUMN_FIX_SIZE :
{
@@ -3011,8 +3137,11 @@ accelerated_table_group(grn_ctx *ctx, grn_obj *table, grn_obj *key, grn_obj *res
}
if ((!idp || *((grn_id *)v)) &&
grn_table_add_v_inline(ctx, res, v, element_size, &value, NULL)) {
- grn_table_add_subrec_inline(res, value, ri ? ri->score : 0,
- (grn_rset_posinfo *)&id, 0);
+ grn_table_group_add_subrec(ctx, res, value,
+ ri ? ri->score : 0,
+ (grn_rset_posinfo *)&id, 0,
+ calc_target,
+ &value_buffer);
}
}
GRN_RA_CACHE_FIN(ra, &cache);
@@ -3037,8 +3166,11 @@ accelerated_table_group(grn_ctx *ctx, grn_obj *table, grn_obj *key, grn_obj *res
while (len) {
if ((*v != GRN_ID_NIL) &&
grn_table_add_v_inline(ctx, res, v, sizeof(grn_id), &value, NULL)) {
- grn_table_add_subrec_inline(res, value, ri ? ri->score : 0,
- (grn_rset_posinfo *)&id, 0);
+ grn_table_group_add_subrec(ctx, res, value,
+ ri ? ri->score : 0,
+ (grn_rset_posinfo *)&id, 0,
+ calc_target,
+ &value_buffer);
}
v++;
len -= sizeof(grn_id);
@@ -3047,18 +3179,109 @@ accelerated_table_group(grn_ctx *ctx, grn_obj *table, grn_obj *key, grn_obj *res
}
}
} else {
- return 0;
+ processed = GRN_FALSE;
}
break;
default :
- return 0;
+ processed = GRN_FALSE;
+ break;
}
+ GRN_OBJ_FIN(ctx, &value_buffer);
grn_table_cursor_close(ctx, tc);
- return 1;
+ return processed;
}
}
}
- return 0;
+ return GRN_FALSE;
+}
+
+static void
+grn_table_group_single_key_records(grn_ctx *ctx, grn_obj *table,
+ grn_obj *key, grn_table_group_result *result)
+{
+ grn_obj bulk;
+ grn_obj value_buffer;
+ grn_table_cursor *tc;
+ grn_obj *res = result->table;
+ grn_obj *calc_target = result->calc_target;
+
+ GRN_TEXT_INIT(&bulk, 0);
+ GRN_VOID_INIT(&value_buffer);
+ if ((tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0))) {
+ grn_id id;
+ grn_obj *range = grn_ctx_at(ctx, grn_obj_get_range(ctx, key));
+ int idp = GRN_OBJ_TABLEP(range);
+ while ((id = grn_table_cursor_next_inline(ctx, tc))) {
+ void *value;
+ grn_rset_recinfo *ri = NULL;
+ GRN_BULK_REWIND(&bulk);
+ if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) {
+ grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri);
+ }
+ grn_obj_get_value(ctx, key, id, &bulk);
+ switch (bulk.header.type) {
+ case GRN_UVECTOR :
+ {
+ // todo : support objects except grn_id
+ grn_id *v = (grn_id *)GRN_BULK_HEAD(&bulk);
+ grn_id *ve = (grn_id *)GRN_BULK_CURR(&bulk);
+ while (v < ve) {
+ if ((*v != GRN_ID_NIL) &&
+ grn_table_add_v_inline(ctx, res,
+ v, sizeof(grn_id), &value, NULL)) {
+ grn_table_group_add_subrec(ctx, res, value,
+ ri ? ri->score : 0,
+ (grn_rset_posinfo *)&id, 0,
+ calc_target,
+ &value_buffer);
+ }
+ v++;
+ }
+ }
+ break;
+ case GRN_VECTOR :
+ {
+ unsigned int i, n_elements;
+ n_elements = grn_vector_size(ctx, &bulk);
+ for (i = 0; i < n_elements; i++) {
+ const char *content;
+ unsigned int content_length;
+ content_length = grn_vector_get_element(ctx, &bulk, i,
+ &content, NULL, NULL);
+ if (grn_table_add_v_inline(ctx, res,
+ content, content_length,
+ &value, NULL)) {
+ grn_table_group_add_subrec(ctx, res, value,
+ ri ? ri->score : 0,
+ (grn_rset_posinfo *)&id, 0,
+ calc_target,
+ &value_buffer);
+ }
+ }
+ }
+ break;
+ case GRN_BULK :
+ {
+ if ((!idp || *((grn_id *)GRN_BULK_HEAD(&bulk))) &&
+ grn_table_add_v_inline(ctx, res,
+ GRN_BULK_HEAD(&bulk), GRN_BULK_VSIZE(&bulk),
+ &value, NULL)) {
+ grn_table_group_add_subrec(ctx, res, value,
+ ri ? ri->score : 0,
+ (grn_rset_posinfo *)&id, 0,
+ calc_target,
+ &value_buffer);
+ }
+ }
+ break;
+ default :
+ ERR(GRN_INVALID_ARGUMENT, "invalid column");
+ break;
+ }
+ }
+ grn_table_cursor_close(ctx, tc);
+ }
+ grn_obj_close(ctx, &bulk);
}
grn_rc
@@ -3164,6 +3387,263 @@ grn_table_group_with_range_gap(grn_ctx *ctx, grn_obj *table,
return 0;
}
+static inline void
+grn_table_group_multi_keys_add_record(grn_ctx *ctx,
+ grn_table_sort_key *keys,
+ int n_keys,
+ grn_table_group_result *results,
+ int n_results,
+ grn_id id,
+ grn_rset_recinfo *ri,
+ grn_obj *vector,
+ grn_obj *bulk)
+{
+ int r;
+ grn_table_group_result *rp;
+
+ for (r = 0, rp = results; r < n_results; r++, rp++) {
+ void *value;
+ int i;
+ int end;
+
+ if (rp->key_end > n_keys) {
+ end = n_keys;
+ } else {
+ end = rp->key_end + 1;
+ }
+ GRN_BULK_REWIND(bulk);
+ grn_text_benc(ctx, bulk, end - rp->key_begin);
+ for (i = rp->key_begin; i < end; i++) {
+ grn_section section = vector->u.v.sections[i];
+ grn_text_benc(ctx, bulk, section.length);
+ }
+ {
+ grn_obj *body = vector->u.v.body;
+ if (body) {
+ GRN_TEXT_PUT(ctx, bulk, GRN_BULK_HEAD(body), GRN_BULK_VSIZE(body));
+ }
+ }
+ for (i = rp->key_begin; i < end; i++) {
+ grn_section section = vector->u.v.sections[i];
+ grn_text_benc(ctx, bulk, section.weight);
+ grn_text_benc(ctx, bulk, section.domain);
+ }
+
+ // todo : cut off GRN_ID_NIL
+ if (grn_table_add_v_inline(ctx, rp->table,
+ GRN_BULK_HEAD(bulk), GRN_BULK_VSIZE(bulk),
+ &value, NULL)) {
+ grn_table_group_add_subrec(ctx, rp->table, value,
+ ri ? ri->score : 0,
+ (grn_rset_posinfo *)&id, 0,
+ rp->calc_target,
+ bulk);
+ }
+ }
+}
+
+static void
+grn_table_group_multi_keys_scalar_records(grn_ctx *ctx,
+ grn_obj *table,
+ grn_table_sort_key *keys,
+ int n_keys,
+ grn_table_group_result *results,
+ int n_results)
+{
+ grn_id id;
+ grn_table_cursor *tc;
+ grn_obj bulk;
+ grn_obj vector;
+
+ tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0);
+ if (!tc) {
+ return;
+ }
+
+ GRN_TEXT_INIT(&bulk, 0);
+ GRN_OBJ_INIT(&vector, GRN_VECTOR, 0, GRN_DB_VOID);
+ while ((id = grn_table_cursor_next_inline(ctx, tc))) {
+ int k;
+ grn_table_sort_key *kp;
+ grn_rset_recinfo *ri = NULL;
+
+ if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) {
+ grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri);
+ }
+
+ GRN_BULK_REWIND(&vector);
+ for (k = 0, kp = keys; k < n_keys; k++, kp++) {
+ GRN_BULK_REWIND(&bulk);
+ grn_obj_get_value(ctx, kp->key, id, &bulk);
+ grn_vector_add_element(ctx, &vector,
+ GRN_BULK_HEAD(&bulk), GRN_BULK_VSIZE(&bulk),
+ 0,
+ bulk.header.domain);
+ }
+
+ grn_table_group_multi_keys_add_record(ctx, keys, n_keys, results, n_results,
+ id, ri, &vector, &bulk);
+ }
+ GRN_OBJ_FIN(ctx, &vector);
+ GRN_OBJ_FIN(ctx, &bulk);
+ grn_table_cursor_close(ctx, tc);
+}
+
+static inline void
+grn_table_group_multi_keys_vector_record(grn_ctx *ctx,
+ grn_table_sort_key *keys,
+ grn_obj *key_buffers,
+ int nth_key,
+ int n_keys,
+ grn_table_group_result *results,
+ int n_results,
+ grn_id id,
+ grn_rset_recinfo *ri,
+ grn_obj *vector,
+ grn_obj *bulk)
+{
+ int k;
+ grn_table_sort_key *kp;
+
+ for (k = nth_key, kp = &(keys[nth_key]); k < n_keys; k++, kp++) {
+ grn_obj *key_buffer = &(key_buffers[k]);
+ switch (key_buffer->header.type) {
+ case GRN_UVECTOR :
+ {
+ unsigned int n_vector_elements;
+ grn_id domain;
+ grn_id *ids;
+ unsigned int i, n_ids;
+
+ n_vector_elements = grn_vector_size(ctx, vector);
+ domain = key_buffer->header.domain;
+ ids = (grn_id *)GRN_BULK_HEAD(key_buffer);
+ n_ids = GRN_BULK_VSIZE(key_buffer) / sizeof(grn_id);
+ for (i = 0; i < n_ids; i++) {
+ grn_id element_id = ids[i];
+ grn_vector_add_element(ctx, vector,
+ (const char *)(&element_id), sizeof(grn_id),
+ 0,
+ domain);
+ grn_table_group_multi_keys_vector_record(ctx,
+ keys, key_buffers,
+ k + 1, n_keys,
+ results, n_results,
+ id, ri, vector, bulk);
+ while (grn_vector_size(ctx, vector) != n_vector_elements) {
+ const char *content;
+ grn_vector_pop_element(ctx, vector, &content, NULL, NULL);
+ }
+ }
+ return;
+ }
+ break;
+ case GRN_VECTOR :
+ {
+ unsigned int n_vector_elements;
+ unsigned int i, n_key_elements;
+
+ n_vector_elements = grn_vector_size(ctx, vector);
+ n_key_elements = grn_vector_size(ctx, key_buffer);
+ for (i = 0; i < n_key_elements; i++) {
+ const char *content;
+ unsigned int content_length;
+ grn_id domain;
+ content_length = grn_vector_get_element(ctx, key_buffer, i,
+ &content, NULL, &domain);
+ grn_vector_add_element(ctx, vector,
+ content, content_length,
+ 0,
+ domain);
+ grn_table_group_multi_keys_vector_record(ctx,
+ keys, key_buffers,
+ k + 1, n_keys,
+ results, n_results,
+ id, ri, vector, bulk);
+ while (grn_vector_size(ctx, vector) != n_vector_elements) {
+ grn_vector_pop_element(ctx, vector, &content, NULL, NULL);
+ }
+ }
+ return;
+ }
+ break;
+ default :
+ grn_vector_add_element(ctx, vector,
+ GRN_BULK_HEAD(key_buffer),
+ GRN_BULK_VSIZE(key_buffer),
+ 0,
+ key_buffer->header.domain);
+ }
+ }
+
+ if (k == n_keys) {
+ grn_table_group_multi_keys_add_record(ctx,
+ keys, n_keys,
+ results, n_results,
+ id, ri, vector, bulk);
+ }
+}
+
+static void
+grn_table_group_multi_keys_vector_records(grn_ctx *ctx,
+ grn_obj *table,
+ grn_table_sort_key *keys,
+ int n_keys,
+ grn_table_group_result *results,
+ int n_results)
+{
+ grn_id id;
+ grn_table_cursor *tc;
+ grn_obj bulk;
+ grn_obj vector;
+ grn_obj *key_buffers;
+ int k;
+
+ tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0);
+ if (!tc) {
+ return;
+ }
+
+ key_buffers = GRN_MALLOCN(grn_obj, n_keys);
+ if (!key_buffers) {
+ grn_table_cursor_close(ctx, tc);
+ return;
+ }
+
+ GRN_TEXT_INIT(&bulk, 0);
+ GRN_OBJ_INIT(&vector, GRN_VECTOR, 0, GRN_DB_VOID);
+ for (k = 0; k < n_keys; k++) {
+ GRN_VOID_INIT(&(key_buffers[k]));
+ }
+ while ((id = grn_table_cursor_next_inline(ctx, tc))) {
+ grn_table_sort_key *kp;
+ grn_rset_recinfo *ri = NULL;
+
+ if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) {
+ grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri);
+ }
+
+ for (k = 0, kp = keys; k < n_keys; k++, kp++) {
+ grn_obj *key_buffer = &(key_buffers[k]);
+ GRN_BULK_REWIND(key_buffer);
+ grn_obj_get_value(ctx, kp->key, id, key_buffer);
+ }
+
+ GRN_BULK_REWIND(&vector);
+ grn_table_group_multi_keys_vector_record(ctx,
+ keys, key_buffers, 0, n_keys,
+ results, n_results,
+ id, ri, &vector, &bulk);
+ }
+ for (k = 0; k < n_keys; k++) {
+ GRN_OBJ_FIN(ctx, &(key_buffers[k]));
+ }
+ GRN_FREE(key_buffers);
+ GRN_OBJ_FIN(ctx, &vector);
+ GRN_OBJ_FIN(ctx, &bulk);
+ grn_table_cursor_close(ctx, tc);
+}
+
grn_rc
grn_table_group(grn_ctx *ctx, grn_obj *table,
grn_table_sort_key *keys, int n_keys,
@@ -3177,9 +3657,6 @@ grn_table_group(grn_ctx *ctx, grn_obj *table,
GRN_API_ENTER;
{
int k, r;
- void *key;
- grn_obj bulk;
- grn_table_cursor *tc;
grn_table_sort_key *kp;
grn_table_group_result *rp;
for (k = 0, kp = keys; k < n_keys; k++, kp++) {
@@ -3190,94 +3667,59 @@ grn_table_group(grn_ctx *ctx, grn_obj *table,
}
for (r = 0, rp = results; r < n_results; r++, rp++) {
if (!rp->table) {
- ERR(GRN_INVALID_ARGUMENT, "table missing in (%d)", r);
- goto exit;
+ grn_obj_flags flags;
+ grn_obj *key_type = NULL;
+ uint32_t additional_value_size;
+
+ flags = GRN_TABLE_HASH_KEY|
+ GRN_OBJ_WITH_SUBREC|
+ GRN_OBJ_UNIT_USERDEF_DOCUMENT;
+ if (n_keys == 1) {
+ key_type = grn_ctx_at(ctx, grn_obj_get_range(ctx, keys[0].key));
+ } else {
+ flags |= GRN_OBJ_KEY_VAR_SIZE;
+ }
+ additional_value_size = grn_rset_recinfo_calc_values_size(ctx,
+ rp->flags);
+ rp->table = grn_table_create_with_max_n_subrecs(ctx, NULL, 0, NULL,
+ flags,
+ key_type, table,
+ rp->max_n_subrecs,
+ additional_value_size);
+ if (key_type) {
+ grn_obj_unlink(ctx, key_type);
+ }
+ if (!rp->table) {
+ goto exit;
+ }
+ DB_OBJ(rp->table)->flags.group = rp->flags;
}
}
- GRN_TEXT_INIT(&bulk, 0);
if (n_keys == 1 && n_results == 1) {
- if (!accelerated_table_group(ctx, table, keys->key, results->table)) {
- if ((tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0))) {
- grn_id id;
- grn_obj *range = grn_ctx_at(ctx, grn_obj_get_range(ctx, keys->key));
- int idp = GRN_OBJ_TABLEP(range);
- while ((id = grn_table_cursor_next_inline(ctx, tc))) {
- void *value;
- grn_rset_recinfo *ri = NULL;
- GRN_BULK_REWIND(&bulk);
- if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) {
- grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri);
- }
- grn_obj_get_value(ctx, keys->key, id, &bulk);
- switch (bulk.header.type) {
- case GRN_UVECTOR :
- {
- // todo : support objects except grn_id
- grn_id *v = (grn_id *)GRN_BULK_HEAD(&bulk);
- grn_id *ve = (grn_id *)GRN_BULK_CURR(&bulk);
- while (v < ve) {
- if ((*v != GRN_ID_NIL) &&
- grn_table_add_v_inline(ctx, results->table, v, sizeof(grn_id), &value, NULL)) {
- grn_table_add_subrec_inline(results->table, value, ri ? ri->score : 0,
- (grn_rset_posinfo *)&id, 0);
- }
- v++;
- }
- }
- break;
- case GRN_VECTOR :
- ERR(GRN_OPERATION_NOT_SUPPORTED, "sorry.. not implemented yet");
- /* todo */
- break;
- case GRN_BULK :
- {
- if ((!idp || *((grn_id *)GRN_BULK_HEAD(&bulk))) &&
- grn_table_add_v_inline(ctx, results->table,
- GRN_BULK_HEAD(&bulk), GRN_BULK_VSIZE(&bulk), &value, NULL)) {
- grn_table_add_subrec_inline(results->table, value, ri ? ri->score : 0,
- (grn_rset_posinfo *)&id, 0);
- }
- }
- break;
- default :
- ERR(GRN_INVALID_ARGUMENT, "invalid column");
- break;
- }
- }
- grn_table_cursor_close(ctx, tc);
- }
+ if (!accelerated_table_group(ctx, table, keys->key, results)) {
+ grn_table_group_single_key_records(ctx, table, keys->key, results);
}
} else {
- if ((tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0))) {
- grn_id id;
- while ((id = grn_table_cursor_next_inline(ctx, tc))) {
- grn_rset_recinfo *ri = NULL;
- GRN_BULK_REWIND(&bulk);
- if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) {
- grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri);
- }
- for (k = 0, kp = keys; k < n_keys; k++, kp++) {
- kp->offset = GRN_BULK_VSIZE(&bulk);
- grn_obj_get_value(ctx, kp->key, id, &bulk);
- }
- for (r = 0, rp = results; r < n_results; r++, rp++) {
- void *value;
- int begin = keys[rp->key_begin].offset;
- int end = rp->key_end >= n_keys
- ? GRN_BULK_VSIZE(&bulk)
- : keys[rp->key_end].offset;
- key = GRN_BULK_HEAD(&bulk) + begin;
- // todo : cut off GRN_ID_NIL
- if (grn_table_add_v_inline(ctx, rp->table, key, end - begin, &value, NULL)) {
- grn_table_add_subrec_inline(rp->table, value, ri ? ri->score : 0,
- (grn_rset_posinfo *)&id, 0);
- }
- }
+ grn_bool have_vector = GRN_FALSE;
+ for (k = 0, kp = keys; k < n_keys; k++, kp++) {
+ grn_id range_id;
+ grn_obj_flags range_flags = 0;
+ grn_obj_get_range_info(ctx, kp->key, &range_id, &range_flags);
+ if (range_flags == GRN_OBJ_VECTOR) {
+ have_vector = GRN_TRUE;
+ break;
}
- grn_table_cursor_close(ctx, tc);
+ }
+ if (have_vector) {
+ grn_table_group_multi_keys_vector_records(ctx, table,
+ keys, n_keys,
+ results, n_results);
+ } else {
+ grn_table_group_multi_keys_scalar_records(ctx, table,
+ keys, n_keys,
+ results, n_results);
}
}
- grn_obj_close(ctx, &bulk);
for (r = 0, rp = results; r < n_results; r++, rp++) {
GRN_TABLE_GROUPED_ON(rp->table);
}
@@ -3674,8 +4116,9 @@ grn_column_create(grn_ctx *ctx, grn_obj *table,
if (grn_db_obj_init(ctx, db, id, DB_OBJ(res))) {
_grn_obj_remove(ctx, res);
res = NULL;
+ } else {
+ grn_obj_touch(ctx, res, NULL);
}
- grn_obj_touch(ctx, res, NULL);
}
exit :
if (!res && id) { grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); }
@@ -3816,17 +4259,67 @@ grn_vector_delimit(grn_ctx *ctx, grn_obj *vector)
*/
static unsigned int
-grn_uvector_size_internal(grn_ctx *ctx, grn_obj *uvector)
+grn_uvector_element_size_internal(grn_ctx *ctx, grn_obj *uvector)
{
- unsigned int size;
+ unsigned int element_size;
if (IS_WEIGHT_UVECTOR(uvector)) {
- size = GRN_BULK_VSIZE(uvector) / sizeof(weight_uvector_entry);
+ element_size = sizeof(weight_uvector_entry);
} else {
- size = GRN_BULK_VSIZE(uvector) / sizeof(grn_id);
+ switch (uvector->header.domain) {
+ case GRN_DB_BOOL :
+ element_size = sizeof(grn_bool);
+ break;
+ case GRN_DB_INT8 :
+ element_size = sizeof(int8_t);
+ break;
+ case GRN_DB_UINT8 :
+ element_size = sizeof(uint8_t);
+ break;
+ case GRN_DB_INT16 :
+ element_size = sizeof(int16_t);
+ break;
+ case GRN_DB_UINT16 :
+ element_size = sizeof(uint16_t);
+ break;
+ case GRN_DB_INT32 :
+ element_size = sizeof(int32_t);
+ break;
+ case GRN_DB_UINT32 :
+ element_size = sizeof(uint32_t);
+ break;
+ case GRN_DB_INT64 :
+ element_size = sizeof(int64_t);
+ break;
+ case GRN_DB_UINT64 :
+ element_size = sizeof(uint64_t);
+ break;
+ case GRN_DB_FLOAT :
+ element_size = sizeof(double);
+ break;
+ case GRN_DB_TIME :
+ element_size = sizeof(int64_t);
+ break;
+ case GRN_DB_TOKYO_GEO_POINT :
+ case GRN_DB_WGS84_GEO_POINT :
+ element_size = sizeof(grn_geo_point);
+ break;
+ default :
+ element_size = sizeof(grn_id);
+ break;
+ }
}
- return size;
+ return element_size;
+}
+
+static unsigned int
+grn_uvector_size_internal(grn_ctx *ctx, grn_obj *uvector)
+{
+ unsigned int element_size;
+
+ element_size = grn_uvector_element_size_internal(ctx, uvector);
+ return GRN_BULK_VSIZE(uvector) / element_size;
}
unsigned int
@@ -4098,6 +4591,30 @@ grn_uvector_size(grn_ctx *ctx, grn_obj *uvector)
GRN_API_RETURN(size);
}
+unsigned int
+grn_uvector_element_size(grn_ctx *ctx, grn_obj *uvector)
+{
+ unsigned int element_size;
+
+ if (!uvector) {
+ ERR(GRN_INVALID_ARGUMENT, "uvector must not be NULL");
+ return 0;
+ }
+
+ if (uvector->header.type != GRN_UVECTOR) {
+ grn_obj type_name;
+ GRN_TEXT_INIT(&type_name, 0);
+ grn_inspect_type(ctx, &type_name, uvector->header.type);
+ ERR(GRN_INVALID_ARGUMENT, "must be GRN_UVECTOR: %.*s",
+ (int)GRN_TEXT_LEN(&type_name), GRN_TEXT_VALUE(&type_name));
+ GRN_OBJ_FIN(ctx, &type_name);
+ return 0;
+ }
+
+ GRN_API_ENTER;
+ element_size = grn_uvector_element_size_internal(ctx, uvector);
+ GRN_API_RETURN(element_size);
+}
grn_rc
grn_uvector_add_element(grn_ctx *ctx, grn_obj *uvector,
@@ -4184,6 +4701,68 @@ accessor_new(grn_ctx *ctx)
return res;
}
+inline static grn_bool
+grn_obj_get_accessor_rset_value(grn_ctx *ctx, grn_obj *obj,
+ grn_accessor **res, uint8_t action)
+{
+ grn_bool succeeded = GRN_FALSE;
+ grn_accessor **rp;
+
+ for (rp = res; GRN_TRUE; rp = &(*rp)->next) {
+ *rp = accessor_new(ctx);
+ (*rp)->obj = obj;
+
+ switch (action) {
+ case GRN_ACCESSOR_GET_SCORE :
+ if (DB_OBJ(obj)->header.flags & GRN_OBJ_WITH_SUBREC) {
+ (*rp)->action = action;
+ succeeded = GRN_TRUE;
+ goto exit;
+ }
+ break;
+ case GRN_ACCESSOR_GET_MAX :
+ case GRN_ACCESSOR_GET_MIN :
+ case GRN_ACCESSOR_GET_SUM :
+ case GRN_ACCESSOR_GET_AVG :
+ case GRN_ACCESSOR_GET_NSUBRECS :
+ if (GRN_TABLE_IS_GROUPED(obj)) {
+ (*rp)->action = action;
+ succeeded = GRN_TRUE;
+ goto exit;
+ }
+ break;
+ }
+
+ switch (obj->header.type) {
+ case GRN_TABLE_PAT_KEY :
+ case GRN_TABLE_DAT_KEY :
+ case GRN_TABLE_HASH_KEY :
+ (*rp)->action = GRN_ACCESSOR_GET_KEY;
+ break;
+ case GRN_TABLE_NO_KEY :
+ if (!obj->header.domain) {
+ goto exit;
+ }
+ (*rp)->action = GRN_ACCESSOR_GET_VALUE;
+ break;
+ default :
+ /* lookup failed */
+ goto exit;
+ }
+ if (!(obj = grn_ctx_at(ctx, obj->header.domain))) {
+ goto exit;
+ }
+ }
+
+exit :
+ if (!succeeded) {
+ grn_obj_close(ctx, (grn_obj *)*res);
+ *res = NULL;
+ }
+
+ return succeeded;
+}
+
static grn_obj *
grn_obj_get_accessor(grn_ctx *ctx, grn_obj *obj, const char *name, unsigned int name_size)
{
@@ -4203,6 +4782,10 @@ grn_obj_get_accessor(grn_ctx *ctx, grn_obj *obj, const char *name, unsigned int
case GRN_ACCESSOR_GET_VALUE :
case GRN_ACCESSOR_GET_SCORE :
case GRN_ACCESSOR_GET_NSUBRECS :
+ case GRN_ACCESSOR_GET_MAX :
+ case GRN_ACCESSOR_GET_MIN :
+ case GRN_ACCESSOR_GET_SUM :
+ case GRN_ACCESSOR_GET_AVG :
obj = grn_ctx_at(ctx, DB_OBJ(res->obj)->range);
break;
case GRN_ACCESSOR_GET_COLUMN_VALUE :
@@ -4240,6 +4823,11 @@ grn_obj_get_accessor(grn_ctx *ctx, grn_obj *obj, const char *name, unsigned int
for (rp = &res; !done; rp = &(*rp)->next) {
*rp = accessor_new(ctx);
(*rp)->obj = obj;
+ if (GRN_TABLE_IS_MULTI_KEYS_GROUPED(obj)) {
+ (*rp)->action = GRN_ACCESSOR_GET_KEY;
+ done++;
+ break;
+ }
if (!(obj = grn_ctx_at(ctx, obj->header.domain))) {
grn_obj_close(ctx, (grn_obj *)res);
res = NULL;
@@ -4366,42 +4954,23 @@ grn_obj_get_accessor(grn_ctx *ctx, grn_obj *obj, const char *name, unsigned int
}
}
break;
- case 's' : /* score */
- if (len != GRN_COLUMN_NAME_SCORE_LEN ||
- memcmp(name, GRN_COLUMN_NAME_SCORE, GRN_COLUMN_NAME_SCORE_LEN)) {
- goto exit;
- }
- for (rp = &res; !done; rp = &(*rp)->next) {
- *rp = accessor_new(ctx);
- (*rp)->obj = obj;
- if (DB_OBJ(obj)->header.flags & GRN_OBJ_WITH_SUBREC) {
- (*rp)->action = GRN_ACCESSOR_GET_SCORE;
- done++;
- } else {
- switch (obj->header.type) {
- case GRN_TABLE_PAT_KEY :
- case GRN_TABLE_DAT_KEY :
- case GRN_TABLE_HASH_KEY :
- (*rp)->action = GRN_ACCESSOR_GET_KEY;
- break;
- case GRN_TABLE_NO_KEY :
- if (obj->header.domain) {
- (*rp)->action = GRN_ACCESSOR_GET_VALUE;
- break;
- }
- /* fallthru */
- default :
- /* lookup failed */
- grn_obj_close(ctx, (grn_obj *)res);
- res = NULL;
- goto exit;
- }
- if (!(obj = grn_ctx_at(ctx, obj->header.domain))) {
- grn_obj_close(ctx, (grn_obj *)res);
- res = NULL;
- goto exit;
- }
+ case 's' : /* score, sum */
+ if (len == GRN_COLUMN_NAME_SCORE_LEN &&
+ memcmp(name, GRN_COLUMN_NAME_SCORE, GRN_COLUMN_NAME_SCORE_LEN) == 0) {
+ if (!grn_obj_get_accessor_rset_value(ctx, obj, &res,
+ GRN_ACCESSOR_GET_SCORE)) {
+ goto exit;
+ }
+ } else if (len == GRN_COLUMN_NAME_SUM_LEN &&
+ memcmp(name,
+ GRN_COLUMN_NAME_SUM,
+ GRN_COLUMN_NAME_SUM_LEN) == 0) {
+ if (!grn_obj_get_accessor_rset_value(ctx, obj, &res,
+ GRN_ACCESSOR_GET_SUM)) {
+ goto exit;
}
+ } else {
+ goto exit;
}
break;
case 'n' : /* nsubrecs */
@@ -4411,37 +4980,43 @@ grn_obj_get_accessor(grn_ctx *ctx, grn_obj *obj, const char *name, unsigned int
GRN_COLUMN_NAME_NSUBRECS_LEN)) {
goto exit;
}
- for (rp = &res; !done; rp = &(*rp)->next) {
- *rp = accessor_new(ctx);
- (*rp)->obj = obj;
- if (GRN_TABLE_IS_GROUPED(obj)) {
- (*rp)->action = GRN_ACCESSOR_GET_NSUBRECS;
- done++;
- } else {
- switch (obj->header.type) {
- case GRN_TABLE_PAT_KEY :
- case GRN_TABLE_DAT_KEY :
- case GRN_TABLE_HASH_KEY :
- (*rp)->action = GRN_ACCESSOR_GET_KEY;
- break;
- case GRN_TABLE_NO_KEY :
- if (obj->header.domain) {
- (*rp)->action = GRN_ACCESSOR_GET_VALUE;
- break;
- }
- /* fallthru */
- default :
- /* lookup failed */
- grn_obj_close(ctx, (grn_obj *)res);
- res = NULL;
- goto exit;
- }
- if (!(obj = grn_ctx_at(ctx, obj->header.domain))) {
- grn_obj_close(ctx, (grn_obj *)res);
- res = NULL;
- goto exit;
- }
+ if (!grn_obj_get_accessor_rset_value(ctx, obj, &res,
+ GRN_ACCESSOR_GET_NSUBRECS)) {
+ goto exit;
+ }
+ break;
+ case 'm' : /* max, min */
+ if (len == GRN_COLUMN_NAME_MAX_LEN &&
+ memcmp(name,
+ GRN_COLUMN_NAME_MAX,
+ GRN_COLUMN_NAME_MAX_LEN) == 0) {
+ if (!grn_obj_get_accessor_rset_value(ctx, obj, &res,
+ GRN_ACCESSOR_GET_MAX)) {
+ goto exit;
+ }
+ } else if (len == GRN_COLUMN_NAME_MIN_LEN &&
+ memcmp(name,
+ GRN_COLUMN_NAME_MIN,
+ GRN_COLUMN_NAME_MIN_LEN) == 0) {
+ if (!grn_obj_get_accessor_rset_value(ctx, obj, &res,
+ GRN_ACCESSOR_GET_MIN)) {
+ goto exit;
+ }
+ } else {
+ goto exit;
+ }
+ break;
+ case 'a' : /* avg */
+ if (len == GRN_COLUMN_NAME_AVG_LEN &&
+ memcmp(name,
+ GRN_COLUMN_NAME_AVG,
+ GRN_COLUMN_NAME_AVG_LEN) == 0) {
+ if (!grn_obj_get_accessor_rset_value(ctx, obj, &res,
+ GRN_ACCESSOR_GET_AVG)) {
+ goto exit;
}
+ } else {
+ goto exit;
}
break;
default :
@@ -4468,7 +5043,9 @@ grn_obj_get_accessor(grn_ctx *ctx, grn_obj *obj, const char *name, unsigned int
(*rp)->action = GRN_ACCESSOR_GET_COLUMN_VALUE;
break;
} else {
- if (!obj->header.domain) {
+ grn_id next_obj_id;
+ next_obj_id = obj->header.domain;
+ if (!next_obj_id) {
// ERR(GRN_INVALID_ARGUMENT, "no such column: <%s>", name);
if (!is_chained) {
grn_obj_close(ctx, (grn_obj *)res);
@@ -4478,7 +5055,8 @@ grn_obj_get_accessor(grn_ctx *ctx, grn_obj *obj, const char *name, unsigned int
}
*rp = accessor_new(ctx);
(*rp)->obj = obj;
- if (!(obj = grn_ctx_at(ctx, obj->header.domain))) {
+ obj = grn_ctx_at(ctx, next_obj_id);
+ if (!obj) {
grn_obj_close(ctx, (grn_obj *)res);
res = NULL;
goto exit;
@@ -4527,6 +5105,33 @@ grn_column_is_vector(grn_ctx *ctx, grn_obj *column)
return type == GRN_OBJ_COLUMN_VECTOR;
}
+inline static grn_bool
+grn_column_is_index(grn_ctx *ctx, grn_obj *column)
+{
+ grn_obj_flags type;
+
+ if (column->header.type == GRN_ACCESSOR) {
+ grn_accessor *a;
+ for (a = (grn_accessor *)column; a; a = a->next) {
+ if (a->next) {
+ continue;
+ }
+ if (a->action != GRN_ACCESSOR_GET_COLUMN_VALUE) {
+ return GRN_FALSE;
+ }
+
+ column = a->obj;
+ }
+ }
+
+ if (column->header.type != GRN_COLUMN_INDEX) {
+ return GRN_FALSE;
+ }
+
+ type = column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK;
+ return type == GRN_OBJ_COLUMN_INDEX;
+}
+
inline static void
grn_obj_get_range_info(grn_ctx *ctx, grn_obj *obj,
grn_id *range_id, grn_obj_flags *range_flags)
@@ -4549,16 +5154,21 @@ grn_obj_get_range_info(grn_ctx *ctx, grn_obj *obj,
}
break;
case GRN_ACCESSOR_GET_SCORE :
+ *range_id = GRN_DB_FLOAT;
+ break;
case GRN_ACCESSOR_GET_NSUBRECS :
*range_id = GRN_DB_INT32;
break;
+ case GRN_ACCESSOR_GET_MAX :
+ case GRN_ACCESSOR_GET_MIN :
+ case GRN_ACCESSOR_GET_SUM :
+ *range_id = GRN_DB_INT64;
+ break;
+ case GRN_ACCESSOR_GET_AVG :
+ *range_id = GRN_DB_FLOAT;
+ break;
case GRN_ACCESSOR_GET_COLUMN_VALUE :
- if (GRN_DB_OBJP(a->obj)) {
- *range_id = DB_OBJ(a->obj)->range;
- if (grn_column_is_vector(ctx, a->obj)) {
- *range_flags = GRN_OBJ_VECTOR;
- }
- }
+ grn_obj_get_range_info(ctx, a->obj, range_id, range_flags);
break;
case GRN_ACCESSOR_GET_KEY :
if (GRN_DB_OBJP(a->obj)) { *range_id = DB_OBJ(a->obj)->header.domain; }
@@ -4594,6 +5204,10 @@ grn_obj_is_persistent(grn_ctx *ctx, grn_obj *obj)
switch (a->action) {
case GRN_ACCESSOR_GET_SCORE :
case GRN_ACCESSOR_GET_NSUBRECS :
+ case GRN_ACCESSOR_GET_MAX :
+ case GRN_ACCESSOR_GET_MIN :
+ case GRN_ACCESSOR_GET_SUM :
+ case GRN_ACCESSOR_GET_AVG :
res = 0;
break;
case GRN_ACCESSOR_GET_ID :
@@ -5071,7 +5685,7 @@ grn_accessor_get_value_(grn_ctx *ctx, grn_accessor *a, grn_id id, uint32_t *size
case GRN_ACCESSOR_GET_SCORE :
if ((value = grn_obj_get_value_(ctx, a->obj, id, size))) {
value = (const char *)&((grn_rset_recinfo *)value)->score;
- *size = sizeof(int);
+ *size = sizeof(double);
}
break;
case GRN_ACCESSOR_GET_NSUBRECS :
@@ -5080,6 +5694,42 @@ grn_accessor_get_value_(grn_ctx *ctx, grn_accessor *a, grn_id id, uint32_t *size
*size = sizeof(int);
}
break;
+ case GRN_ACCESSOR_GET_MAX :
+ if ((value = grn_obj_get_value_(ctx, a->obj, id, size))) {
+ value =
+ (const char *)grn_rset_recinfo_get_max_(ctx,
+ (grn_rset_recinfo *)value,
+ a->obj);
+ *size = GRN_RSET_MAX_SIZE;
+ }
+ break;
+ case GRN_ACCESSOR_GET_MIN :
+ if ((value = grn_obj_get_value_(ctx, a->obj, id, size))) {
+ value =
+ (const char *)grn_rset_recinfo_get_min_(ctx,
+ (grn_rset_recinfo *)value,
+ a->obj);
+ *size = GRN_RSET_MIN_SIZE;
+ }
+ break;
+ case GRN_ACCESSOR_GET_SUM :
+ if ((value = grn_obj_get_value_(ctx, a->obj, id, size))) {
+ value =
+ (const char *)grn_rset_recinfo_get_sum_(ctx,
+ (grn_rset_recinfo *)value,
+ a->obj);
+ *size = GRN_RSET_SUM_SIZE;
+ }
+ break;
+ case GRN_ACCESSOR_GET_AVG :
+ if ((value = grn_obj_get_value_(ctx, a->obj, id, size))) {
+ value =
+ (const char *)grn_rset_recinfo_get_avg_(ctx,
+ (grn_rset_recinfo *)value,
+ a->obj);
+ *size = GRN_RSET_AVG_SIZE;
+ }
+ break;
case GRN_ACCESSOR_GET_COLUMN_VALUE :
/* todo : support vector */
value = grn_obj_get_value_(ctx, a->obj, id, size);
@@ -5120,13 +5770,35 @@ grn_accessor_get_value(grn_ctx *ctx, grn_accessor *a, grn_id id, grn_obj *value)
switch (a->action) {
case GRN_ACCESSOR_GET_ID :
GRN_UINT32_PUT(ctx, value, id);
+ value->header.domain = GRN_DB_UINT32;
vp = GRN_BULK_HEAD(value) + size0;
vs = GRN_BULK_VSIZE(value) - size0;
break;
case GRN_ACCESSOR_GET_KEY :
- grn_table_get_key2(ctx, a->obj, id, value);
- vp = GRN_BULK_HEAD(value) + size0;
- vs = GRN_BULK_VSIZE(value) - size0;
+ if (!a->next && GRN_TABLE_IS_MULTI_KEYS_GROUPED(a->obj)) {
+ grn_obj_ensure_vector(ctx, value);
+ if (id) {
+ grn_obj raw_vector;
+ GRN_TEXT_INIT(&raw_vector, 0);
+ grn_table_get_key2(ctx, a->obj, id, &raw_vector);
+ grn_vector_decode(ctx, value,
+ GRN_BULK_HEAD(&raw_vector),
+ GRN_BULK_VSIZE(&raw_vector));
+ GRN_OBJ_FIN(ctx, &raw_vector);
+ }
+ vp = NULL;
+ vs = 0;
+ } else {
+ if (id) {
+ grn_table_get_key2(ctx, a->obj, id, value);
+ vp = GRN_BULK_HEAD(value) + size0;
+ vs = GRN_BULK_VSIZE(value) - size0;
+ } else {
+ vp = NULL;
+ vs = 0;
+ }
+ value->header.domain = a->obj->header.domain;
+ }
break;
case GRN_ACCESSOR_GET_VALUE :
grn_obj_get_value(ctx, a->obj, id, value);
@@ -5134,17 +5806,66 @@ grn_accessor_get_value(grn_ctx *ctx, grn_accessor *a, grn_id id, grn_obj *value)
vs = GRN_BULK_VSIZE(value) - size0;
break;
case GRN_ACCESSOR_GET_SCORE :
- grn_obj_get_value(ctx, a->obj, id, value);
- {
+ if (id) {
grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs);
- GRN_INT32_PUT(ctx, value, ri->score);
+ GRN_FLOAT_PUT(ctx, value, ri->score);
+ } else {
+ GRN_FLOAT_PUT(ctx, value, 0.0);
}
+ value->header.domain = GRN_DB_FLOAT;
break;
case GRN_ACCESSOR_GET_NSUBRECS :
- {
+ if (id) {
grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs);
GRN_INT32_PUT(ctx, value, ri->n_subrecs);
+ } else {
+ GRN_INT32_PUT(ctx, value, 0);
+ }
+ value->header.domain = GRN_DB_INT32;
+ break;
+ case GRN_ACCESSOR_GET_MAX :
+ if (id) {
+ grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs);
+ int64_t max;
+ max = grn_rset_recinfo_get_max(ctx, ri, a->obj);
+ GRN_INT64_PUT(ctx, value, max);
+ } else {
+ GRN_INT64_PUT(ctx, value, 0);
+ }
+ value->header.domain = GRN_DB_INT64;
+ break;
+ case GRN_ACCESSOR_GET_MIN :
+ if (id) {
+ grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs);
+ int64_t min;
+ min = grn_rset_recinfo_get_min(ctx, ri, a->obj);
+ GRN_INT64_PUT(ctx, value, min);
+ } else {
+ GRN_INT64_PUT(ctx, value, 0);
+ }
+ value->header.domain = GRN_DB_INT64;
+ break;
+ case GRN_ACCESSOR_GET_SUM :
+ if (id) {
+ grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs);
+ int64_t sum;
+ sum = grn_rset_recinfo_get_sum(ctx, ri, a->obj);
+ GRN_INT64_PUT(ctx, value, sum);
+ } else {
+ GRN_INT64_PUT(ctx, value, 0);
+ }
+ value->header.domain = GRN_DB_INT64;
+ break;
+ case GRN_ACCESSOR_GET_AVG :
+ if (id) {
+ grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs);
+ double avg;
+ avg = grn_rset_recinfo_get_avg(ctx, ri, a->obj);
+ GRN_FLOAT_PUT(ctx, value, avg);
+ } else {
+ GRN_FLOAT_PUT(ctx, value, 0.0);
}
+ value->header.domain = GRN_DB_FLOAT;
break;
case GRN_ACCESSOR_GET_COLUMN_VALUE :
/* todo : support vector */
@@ -5165,7 +5886,11 @@ grn_accessor_get_value(grn_ctx *ctx, grn_accessor *a, grn_id id, grn_obj *value)
break;
}
if ((a = a->next)) {
- id = *((grn_id *)vp);
+ if (vs > 0) {
+ id = *((grn_id *)vp);
+ } else {
+ id = GRN_ID_NIL;
+ }
} else {
break;
}
@@ -5208,15 +5933,14 @@ grn_accessor_set_value(grn_ctx *ctx, grn_accessor *a, grn_id id,
} else {
uint32_t size;
if ((ri = (grn_rset_recinfo *) grn_obj_get_value_(ctx, a->obj, id, &size))) {
- vp = &ri->score;
// todo : flags support
- if (value->header.domain == GRN_DB_INT32) {
- memcpy(vp, GRN_BULK_HEAD(value), sizeof(int));
+ if (value->header.domain == GRN_DB_FLOAT) {
+ ri->score = GRN_FLOAT_VALUE(value);
} else {
grn_obj buf;
- GRN_INT32_INIT(&buf, 0);
+ GRN_FLOAT_INIT(&buf, 0);
grn_obj_cast(ctx, value, &buf, GRN_FALSE);
- memcpy(vp, GRN_BULK_HEAD(&buf), sizeof(int));
+ ri->score = GRN_FLOAT_VALUE(&buf);
GRN_OBJ_FIN(ctx, &buf);
}
}
@@ -5230,6 +5954,74 @@ grn_accessor_set_value(grn_ctx *ctx, grn_accessor *a, grn_id id,
vp = &ri->n_subrecs;
}
break;
+ case GRN_ACCESSOR_GET_MAX :
+ grn_obj_get_value(ctx, a->obj, id, &buf);
+ {
+ grn_rset_recinfo *ri = (grn_rset_recinfo *)GRN_BULK_HEAD(&buf);
+ if (value->header.type == GRN_DB_INT64) {
+ grn_rset_recinfo_set_max(ctx, ri, a->obj, GRN_INT64_VALUE(value));
+ } else {
+ grn_obj value_int64;
+ GRN_INT64_INIT(&value_int64, 0);
+ if (!grn_obj_cast(ctx, value, &value_int64, GRN_FALSE)) {
+ grn_rset_recinfo_set_max(ctx, ri, a->obj,
+ GRN_INT64_VALUE(&value_int64));
+ }
+ GRN_OBJ_FIN(ctx, &value_int64);
+ }
+ }
+ break;
+ case GRN_ACCESSOR_GET_MIN :
+ grn_obj_get_value(ctx, a->obj, id, &buf);
+ {
+ grn_rset_recinfo *ri = (grn_rset_recinfo *)GRN_BULK_HEAD(&buf);
+ if (value->header.type == GRN_DB_INT64) {
+ grn_rset_recinfo_set_min(ctx, ri, a->obj, GRN_INT64_VALUE(value));
+ } else {
+ grn_obj value_int64;
+ GRN_INT64_INIT(&value_int64, 0);
+ if (!grn_obj_cast(ctx, value, &value_int64, GRN_FALSE)) {
+ grn_rset_recinfo_set_min(ctx, ri, a->obj,
+ GRN_INT64_VALUE(&value_int64));
+ }
+ GRN_OBJ_FIN(ctx, &value_int64);
+ }
+ }
+ break;
+ case GRN_ACCESSOR_GET_SUM :
+ grn_obj_get_value(ctx, a->obj, id, &buf);
+ {
+ grn_rset_recinfo *ri = (grn_rset_recinfo *)GRN_BULK_HEAD(&buf);
+ if (value->header.type == GRN_DB_INT64) {
+ grn_rset_recinfo_set_sum(ctx, ri, a->obj, GRN_INT64_VALUE(value));
+ } else {
+ grn_obj value_int64;
+ GRN_INT64_INIT(&value_int64, 0);
+ if (!grn_obj_cast(ctx, value, &value_int64, GRN_FALSE)) {
+ grn_rset_recinfo_set_sum(ctx, ri, a->obj,
+ GRN_INT64_VALUE(&value_int64));
+ }
+ GRN_OBJ_FIN(ctx, &value_int64);
+ }
+ }
+ break;
+ case GRN_ACCESSOR_GET_AVG :
+ grn_obj_get_value(ctx, a->obj, id, &buf);
+ {
+ grn_rset_recinfo *ri = (grn_rset_recinfo *)GRN_BULK_HEAD(&buf);
+ if (value->header.type == GRN_DB_FLOAT) {
+ grn_rset_recinfo_set_avg(ctx, ri, a->obj, GRN_FLOAT_VALUE(value));
+ } else {
+ grn_obj value_float;
+ GRN_FLOAT_INIT(&value_float, 0);
+ if (!grn_obj_cast(ctx, value, &value_float, GRN_FALSE)) {
+ grn_rset_recinfo_set_avg(ctx, ri, a->obj,
+ GRN_FLOAT_VALUE(&value_float));
+ }
+ GRN_OBJ_FIN(ctx, &value_float);
+ }
+ }
+ break;
case GRN_ACCESSOR_GET_COLUMN_VALUE :
/* todo : support vector */
if (a->next) {
@@ -5671,7 +6463,7 @@ grn_obj_set_value_column_var_size_vector(grn_ctx *ctx, grn_obj *obj, grn_id id,
if (v && s &&
(token_cursor = grn_token_cursor_open(ctx, lexicon, v, s,
GRN_TOKEN_ADD, token_flags))) {
- while (token_cursor->status == GRN_TOKEN_DOING) {
+ while (token_cursor->status == GRN_TOKEN_CURSOR_DOING) {
grn_id tid = grn_token_cursor_next(ctx, token_cursor);
grn_uvector_add_element(ctx, &uvector, tid, 0);
}
@@ -5952,12 +6744,45 @@ grn_obj_get_value_(grn_ctx *ctx, grn_obj *obj, grn_id id, uint32_t *size)
}
static void
+grn_obj_get_value_expr(grn_ctx *ctx, grn_obj *expr, grn_id id, grn_obj *value)
+{
+ grn_expr *e = (grn_expr *)expr;
+ grn_expr_code *code;
+
+ if (e->codes_curr != 1) {
+ return;
+ }
+
+ code = e->codes;
+ if (code->op != GRN_OP_GET_VALUE) {
+ return;
+ }
+
+ if (!code->value) {
+ return;
+ }
+
+ switch (code->value->header.type) {
+ case GRN_COLUMN_VAR_SIZE :
+ case GRN_COLUMN_FIX_SIZE :
+ grn_obj_get_value(ctx, code->value, id, value);
+ break;
+ default :
+ break;
+ }
+}
+
+static void
grn_obj_get_value_column_index(grn_ctx *ctx, grn_obj *index_column,
grn_id id, grn_obj *value)
{
grn_ii *ii = (grn_ii *)index_column;
grn_obj_ensure_bulk(ctx, value);
- GRN_UINT32_SET(ctx, value, grn_ii_estimate_size(ctx, ii, id));
+ if (id) {
+ GRN_UINT32_SET(ctx, value, grn_ii_estimate_size(ctx, ii, id));
+ } else {
+ GRN_UINT32_SET(ctx, value, 0);
+ }
value->header.domain = GRN_DB_UINT32;
}
@@ -5970,15 +6795,19 @@ grn_obj_get_value_column_vector(grn_ctx *ctx, grn_obj *obj,
lexicon = grn_ctx_at(ctx, DB_OBJ(obj)->range);
if (lexicon && !GRN_OBJ_TABLEP(lexicon) &&
(lexicon->header.flags & GRN_OBJ_KEY_VAR_SIZE)) {
- grn_obj v_;
grn_obj_ensure_vector(ctx, value);
- GRN_TEXT_INIT(&v_, 0);
- grn_ja_get_value(ctx, (grn_ja *)obj, id, &v_);
- grn_vector_decode(ctx, value, GRN_TEXT_VALUE(&v_), GRN_TEXT_LEN(&v_));
- GRN_OBJ_FIN(ctx, &v_);
+ if (id) {
+ grn_obj v_;
+ GRN_TEXT_INIT(&v_, 0);
+ grn_ja_get_value(ctx, (grn_ja *)obj, id, &v_);
+ grn_vector_decode(ctx, value, GRN_TEXT_VALUE(&v_), GRN_TEXT_LEN(&v_));
+ GRN_OBJ_FIN(ctx, &v_);
+ }
} else {
grn_obj_ensure_bulk(ctx, value);
- grn_ja_get_value(ctx, (grn_ja *)obj, id, value);
+ if (id) {
+ grn_ja_get_value(ctx, (grn_ja *)obj, id, value);
+ }
value->header.type = GRN_UVECTOR;
if (obj->header.flags & GRN_OBJ_WITH_WEIGHT) {
value->header.flags |= GRN_OBJ_WITH_WEIGHT;
@@ -5994,7 +6823,6 @@ grn_obj *
grn_obj_get_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value)
{
GRN_API_ENTER;
- if (!id) { goto exit; }
if (!obj) {
ERR(GRN_INVALID_ARGUMENT, "grn_obj_get_value failed");
goto exit;
@@ -6022,20 +6850,24 @@ grn_obj_get_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value)
case GRN_ACCESSOR :
grn_obj_ensure_bulk(ctx, value);
value = grn_accessor_get_value(ctx, (grn_accessor *)obj, id, value);
- value->header.domain = grn_obj_get_range(ctx, obj);
+ break;
+ case GRN_EXPR :
+ grn_obj_get_value_expr(ctx, obj, id, value);
break;
case GRN_TABLE_PAT_KEY :
{
grn_pat *pat = (grn_pat *)obj;
uint32_t size = pat->value_size;
grn_obj_ensure_bulk(ctx, value);
- if (grn_bulk_space(ctx, value, size)) {
- MERR("grn_bulk_space failed");
- goto exit;
- }
- {
- char *curr = GRN_BULK_CURR(value);
- grn_pat_get_value(ctx, pat, id, curr - size);
+ if (id) {
+ if (grn_bulk_space(ctx, value, size)) {
+ MERR("grn_bulk_space failed");
+ goto exit;
+ }
+ {
+ char *curr = GRN_BULK_CURR(value);
+ grn_pat_get_value(ctx, pat, id, curr - size);
+ }
}
value->header.type = GRN_BULK;
value->header.domain = grn_obj_get_range(ctx, obj);
@@ -6046,19 +6878,34 @@ grn_obj_get_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value)
break;
case GRN_TABLE_HASH_KEY :
{
- grn_hash *hash = (grn_hash *)obj;
- uint32_t size = hash->value_size;
+ grn_bool processed = GRN_FALSE;
grn_obj_ensure_bulk(ctx, value);
- if (grn_bulk_space(ctx, value, size)) {
- MERR("grn_bulk_space failed");
- goto exit;
- }
- {
- char *curr = GRN_BULK_CURR(value);
- grn_hash_get_value(ctx, hash, id, curr - size);
- }
- value->header.type = GRN_BULK;
value->header.domain = grn_obj_get_range(ctx, obj);
+ if (id) {
+ if (GRN_TABLE_IS_MULTI_KEYS_GROUPED(obj)) {
+ grn_obj *domain;
+ domain = grn_ctx_at(ctx, value->header.domain);
+ if (GRN_OBJ_TABLEP(domain)) {
+ grn_id subrec_id;
+ if (grn_table_get_subrecs(ctx, obj, id, &subrec_id, NULL, 1) == 1) {
+ GRN_RECORD_SET(ctx, value, subrec_id);
+ processed = GRN_TRUE;
+ }
+ }
+ }
+ if (!processed) {
+ grn_hash *hash = (grn_hash *)obj;
+ uint32_t size = hash->value_size;
+ if (grn_bulk_space(ctx, value, size)) {
+ MERR("grn_bulk_space failed");
+ goto exit;
+ }
+ {
+ char *curr = GRN_BULK_CURR(value);
+ grn_hash_get_value(ctx, hash, id, curr - size);
+ }
+ }
+ }
}
break;
case GRN_TABLE_NO_KEY :
@@ -6066,13 +6913,15 @@ grn_obj_get_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value)
grn_array *array = (grn_array *)obj;
uint32_t size = array->value_size;
grn_obj_ensure_bulk(ctx, value);
- if (grn_bulk_space(ctx, value, size)) {
- MERR("grn_bulk_space failed");
- goto exit;
- }
- {
- char *curr = GRN_BULK_CURR(value);
- grn_array_get_value(ctx, array, id, curr - size);
+ if (id) {
+ if (grn_bulk_space(ctx, value, size)) {
+ MERR("grn_bulk_space failed");
+ goto exit;
+ }
+ {
+ char *curr = GRN_BULK_CURR(value);
+ grn_array_get_value(ctx, array, id, curr - size);
+ }
}
value->header.type = GRN_BULK;
value->header.domain = grn_obj_get_range(ctx, obj);
@@ -6085,7 +6934,9 @@ grn_obj_get_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value)
break;
case GRN_OBJ_COLUMN_SCALAR :
grn_obj_ensure_bulk(ctx, value);
- grn_ja_get_value(ctx, (grn_ja *)obj, id, value);
+ if (id) {
+ grn_ja_get_value(ctx, (grn_ja *)obj, id, value);
+ }
value->header.type = GRN_BULK;
break;
default :
@@ -6095,12 +6946,12 @@ grn_obj_get_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value)
value->header.domain = grn_obj_get_range(ctx, obj);
break;
case GRN_COLUMN_FIX_SIZE :
- {
+ grn_obj_ensure_bulk(ctx, value);
+ value->header.type = GRN_BULK;
+ value->header.domain = grn_obj_get_range(ctx, obj);
+ if (id) {
unsigned int element_size;
void *v = grn_ra_ref(ctx, (grn_ra *)obj, id);
- grn_obj_ensure_bulk(ctx, value);
- value->header.type = GRN_BULK;
- value->header.domain = grn_obj_get_range(ctx, obj);
if (v) {
element_size = ((grn_ra *)obj)->header->element_size;
grn_bulk_write(ctx, value, v, element_size);
@@ -6195,17 +7046,17 @@ grn_obj_get_info(grn_ctx *ctx, grn_obj *obj, grn_info_type type, grn_obj *valueb
GRN_BOOL_PUT(ctx, valuebuf, GRN_FALSE);
#endif
break;
- case GRN_INFO_SUPPORT_LZO :
+ case GRN_INFO_SUPPORT_LZ4 :
if (!valuebuf && !(valuebuf = grn_obj_open(ctx, GRN_BULK, 0, GRN_DB_BOOL))) {
ERR(GRN_INVALID_ARGUMENT,
- "failed to open value buffer for GRN_INFO_LZO_SUPPORT");
+ "failed to open value buffer for GRN_INFO_LZ4_SUPPORT");
goto exit;
}
-#ifdef GRN_WITH_LZO
+#ifdef GRN_WITH_LZ4
GRN_BOOL_PUT(ctx, valuebuf, GRN_TRUE);
-#else /* GRN_WITH_LZO */
+#else /* GRN_WITH_LZ4 */
GRN_BOOL_PUT(ctx, valuebuf, GRN_FALSE);
-#endif /* GRN_WITH_LZO */
+#endif /* GRN_WITH_LZ4 */
break;
default :
if (!obj) {
@@ -6810,7 +7661,7 @@ grn_obj_set_info_token_filters(grn_ctx *ctx,
grn_obj *token_filters)
{
grn_obj *current_token_filters;
- unsigned int i, n_token_filters;
+ unsigned int i, n_current_token_filters, n_token_filters;
grn_obj token_filter_names;
switch (table->header.type) {
@@ -6832,9 +7683,12 @@ grn_obj_set_info_token_filters(grn_ctx *ctx,
return ctx->rc;
}
+ n_current_token_filters =
+ GRN_BULK_VSIZE(current_token_filters) / sizeof(grn_obj *);
+ n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *);
+
GRN_TEXT_INIT(&token_filter_names, 0);
GRN_BULK_REWIND(current_token_filters);
- n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *);
for (i = 0; i < n_token_filters; i++) {
grn_obj *token_filter = GRN_PTR_VALUE_AT(token_filters, i);
char token_filter_name[GRN_TABLE_MAX_KEY_SIZE];
@@ -6842,6 +7696,9 @@ grn_obj_set_info_token_filters(grn_ctx *ctx,
GRN_PTR_PUT(ctx, current_token_filters, token_filter);
+ if (i > 0) {
+ GRN_TEXT_PUTC(ctx, &token_filter_names, ',');
+ }
token_filter_name_size = grn_obj_name(ctx,
token_filter,
token_filter_name,
@@ -6851,9 +7708,11 @@ grn_obj_set_info_token_filters(grn_ctx *ctx,
token_filter_name,
token_filter_name_size);
}
- GRN_LOG(ctx, GRN_LOG_NOTICE, "DDL:set_token_filters %.*s",
- (int)GRN_BULK_VSIZE(&token_filter_names),
- GRN_BULK_HEAD(&token_filter_names));
+ if (n_token_filters > 0 || n_token_filters != n_current_token_filters) {
+ GRN_LOG(ctx, GRN_LOG_NOTICE, "DDL:set_token_filters %.*s",
+ (int)GRN_BULK_VSIZE(&token_filter_names),
+ GRN_BULK_HEAD(&token_filter_names));
+ }
GRN_OBJ_FIN(ctx, &token_filter_names);
grn_obj_spec_save(ctx, DB_OBJ(table));
@@ -6946,21 +7805,6 @@ grn_obj_set_element_info(grn_ctx *ctx, grn_obj *obj, grn_id id,
GRN_API_RETURN(GRN_SUCCESS);
}
-grn_bool
-grn_obj_is_builtin(grn_ctx *ctx, grn_obj *obj)
-{
- grn_id id;
-
- if (!obj) { return GRN_FALSE; }
-
- id = grn_obj_id(ctx, obj);
- if (id == GRN_ID_NIL) {
- return GRN_FALSE;
- } else {
- return id < GRN_N_RESERVED_TYPES;
- }
-}
-
static void
grn_hook_free(grn_ctx *ctx, grn_hook *h)
{
@@ -7879,7 +8723,7 @@ grn_token_filters_unpack(grn_ctx *ctx,
unsigned int element_size;
unsigned int i, n_token_filter_ids;
- if (grn_vector_size(ctx, spec_vector) < SERIALIZED_SPEC_INDEX_TOKEN_FILTERS) {
+ if (grn_vector_size(ctx, spec_vector) <= SERIALIZED_SPEC_INDEX_TOKEN_FILTERS) {
return;
}
@@ -8070,6 +8914,9 @@ grn_ctx_at(grn_ctx *ctx, grn_id id)
}
}
res = vp->ptr;
+ if (res && res->header.type == GRN_PROC) {
+ grn_plugin_ensure_registered(ctx, res);
+ }
}
}
exit :
@@ -8399,10 +9246,14 @@ grn_obj_reinit_for(grn_ctx *ctx, grn_obj *obj, grn_obj *domain_obj)
return ctx->rc;
}
- grn_obj_get_range_info(ctx, domain_obj, &domain, &flags);
- if (GRN_OBJ_TABLEP(domain_obj) &&
- domain_obj->header.type != GRN_TABLE_NO_KEY) {
- domain = domain_obj->header.domain;
+ if (grn_column_is_index(ctx, domain_obj)) {
+ domain = GRN_DB_UINT32;
+ } else {
+ grn_obj_get_range_info(ctx, domain_obj, &domain, &flags);
+ if (GRN_OBJ_TABLEP(domain_obj) &&
+ domain_obj->header.type != GRN_TABLE_NO_KEY) {
+ domain = domain_obj->header.domain;
+ }
}
return grn_obj_reinit(ctx, obj, domain, flags);
}
@@ -8481,6 +9332,18 @@ grn_column_name(grn_ctx *ctx, grn_obj *obj, char *namebuf, int buf_size)
case GRN_ACCESSOR_GET_NSUBRECS :
name = GRN_COLUMN_NAME_NSUBRECS;
break;
+ case GRN_ACCESSOR_GET_MAX :
+ name = GRN_COLUMN_NAME_MAX;
+ break;
+ case GRN_ACCESSOR_GET_MIN :
+ name = GRN_COLUMN_NAME_MIN;
+ break;
+ case GRN_ACCESSOR_GET_SUM :
+ name = GRN_COLUMN_NAME_SUM;
+ break;
+ case GRN_ACCESSOR_GET_AVG :
+ name = GRN_COLUMN_NAME_AVG;
+ break;
case GRN_ACCESSOR_GET_COLUMN_VALUE :
case GRN_ACCESSOR_GET_DB_OBJ :
case GRN_ACCESSOR_LOOKUP :
@@ -8544,6 +9407,26 @@ grn_column_name_(grn_ctx *ctx, grn_obj *obj, grn_obj *buf)
GRN_COLUMN_NAME_NSUBRECS,
GRN_COLUMN_NAME_NSUBRECS_LEN);
break;
+ case GRN_ACCESSOR_GET_MAX :
+ GRN_TEXT_PUT(ctx, buf,
+ GRN_COLUMN_NAME_MAX,
+ GRN_COLUMN_NAME_MAX_LEN);
+ break;
+ case GRN_ACCESSOR_GET_MIN :
+ GRN_TEXT_PUT(ctx, buf,
+ GRN_COLUMN_NAME_MIN,
+ GRN_COLUMN_NAME_MIN_LEN);
+ break;
+ case GRN_ACCESSOR_GET_SUM :
+ GRN_TEXT_PUT(ctx, buf,
+ GRN_COLUMN_NAME_SUM,
+ GRN_COLUMN_NAME_SUM_LEN);
+ break;
+ case GRN_ACCESSOR_GET_AVG :
+ GRN_TEXT_PUT(ctx, buf,
+ GRN_COLUMN_NAME_AVG,
+ GRN_COLUMN_NAME_AVG_LEN);
+ break;
case GRN_ACCESSOR_GET_COLUMN_VALUE :
grn_column_name_(ctx, a->obj, buf);
if (a->next) { GRN_TEXT_PUTC(ctx, buf, '.'); }
@@ -8751,7 +9634,7 @@ typedef struct {
grn_id id;
uint32_t size;
const void *value;
-} sort_entry;
+} sort_reference_entry;
enum {
KEY_ID = 0,
@@ -8783,8 +9666,9 @@ enum {
} while (0)
inline static int
-compare_value(grn_ctx *ctx, sort_entry *a, sort_entry *b,
- grn_table_sort_key *keys, int n_keys)
+compare_reference(grn_ctx *ctx,
+ sort_reference_entry *a, sort_reference_entry *b,
+ grn_table_sort_key *keys, int n_keys)
{
int i;
uint8_t type;
@@ -8880,73 +9764,82 @@ compare_value(grn_ctx *ctx, sort_entry *a, sort_entry *b,
}
inline static void
-swap(sort_entry *a, sort_entry *b)
+swap_reference(sort_reference_entry *a, sort_reference_entry *b)
{
- sort_entry c_ = *a;
+ sort_reference_entry c_ = *a;
*a = *b;
*b = c_;
}
-inline static sort_entry *
-part(grn_ctx *ctx, sort_entry *b, sort_entry *e, grn_table_sort_key *keys, int n_keys)
+inline static sort_reference_entry *
+part_reference(grn_ctx *ctx,
+ sort_reference_entry *b, sort_reference_entry *e,
+ grn_table_sort_key *keys, int n_keys)
{
- sort_entry *c;
+ sort_reference_entry *c;
intptr_t d = e - b;
- if (compare_value(ctx, b, e, keys, n_keys)) {
- swap(b, e);
+ if (compare_reference(ctx, b, e, keys, n_keys)) {
+ swap_reference(b, e);
}
if (d < 2) { return NULL; }
c = b + (d >> 1);
- if (compare_value(ctx, b, c, keys, n_keys)) {
- swap(b, c);
+ if (compare_reference(ctx, b, c, keys, n_keys)) {
+ swap_reference(b, c);
} else {
- if (compare_value(ctx, c, e, keys, n_keys)) {
- swap(c, e);
+ if (compare_reference(ctx, c, e, keys, n_keys)) {
+ swap_reference(c, e);
}
}
if (d < 3) { return NULL; }
b++;
- swap(b, c);
+ swap_reference(b, c);
c = b;
for (;;) {
do {
b++;
- } while (compare_value(ctx, c, b, keys, n_keys));
+ } while (compare_reference(ctx, c, b, keys, n_keys));
do {
e--;
- } while (compare_value(ctx, e, c, keys, n_keys));
+ } while (compare_reference(ctx, e, c, keys, n_keys));
if (b >= e) { break; }
- swap(b, e);
+ swap_reference(b, e);
}
- swap(c, e);
+ swap_reference(c, e);
return e;
}
static void
-_sort(grn_ctx *ctx, sort_entry *head, sort_entry *tail, int from, int to,
- grn_table_sort_key *keys, int n_keys)
+sort_reference(grn_ctx *ctx,
+ sort_reference_entry *head, sort_reference_entry *tail,
+ int from, int to,
+ grn_table_sort_key *keys, int n_keys)
{
- sort_entry *c;
- if (head < tail && (c = part(ctx, head, tail, keys, n_keys))) {
+ sort_reference_entry *c;
+ if (head < tail && (c = part_reference(ctx, head, tail, keys, n_keys))) {
intptr_t m = c - head + 1;
- if (from < m - 1) { _sort(ctx, head, c - 1, from, to, keys, n_keys); }
- if (m < to) { _sort(ctx, c + 1, tail, from - m, to - m, keys, n_keys); }
+ if (from < m - 1) {
+ sort_reference(ctx, head, c - 1, from, to, keys, n_keys);
+ }
+ if (m < to) {
+ sort_reference(ctx, c + 1, tail, from - m, to - m, keys, n_keys);
+ }
}
}
-static sort_entry *
-pack(grn_ctx *ctx, grn_obj *table, sort_entry *head, sort_entry *tail,
- grn_table_sort_key *keys, int n_keys)
+static sort_reference_entry *
+pack_reference(grn_ctx *ctx, grn_obj *table,
+ sort_reference_entry *head, sort_reference_entry *tail,
+ grn_table_sort_key *keys, int n_keys)
{
int i = 0;
- sort_entry e, c;
+ sort_reference_entry e, c;
grn_table_cursor *tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0);
if (!tc) { return NULL; }
if ((c.id = grn_table_cursor_next_inline(ctx, tc))) {
c.value = grn_obj_get_value_(ctx, keys->key, c.id, &c.size);
while ((e.id = grn_table_cursor_next_inline(ctx, tc))) {
e.value = grn_obj_get_value_(ctx, keys->key, e.id, &e.size);
- if (compare_value(ctx, &c, &e, keys, n_keys)) {
+ if (compare_reference(ctx, &c, &e, keys, n_keys)) {
*head++ = e;
} else {
*tail-- = e;
@@ -8961,6 +9854,336 @@ pack(grn_ctx *ctx, grn_obj *table, sort_entry *head, sort_entry *tail,
}
static int
+grn_table_sort_reference(grn_ctx *ctx, grn_obj *table,
+ int offset, int limit,
+ grn_obj *result,
+ grn_table_sort_key *keys, int n_keys)
+{
+ int e, n;
+ sort_reference_entry *array, *ep;
+ e = offset + limit;
+ n = grn_table_size(ctx, table);
+ if (!(array = GRN_MALLOC(sizeof(sort_reference_entry) * n))) {
+ return 0;
+ }
+ if ((ep = pack_reference(ctx, table, array, array + n - 1, keys, n_keys))) {
+ intptr_t m = ep - array + 1;
+ if (offset < m - 1) {
+ sort_reference(ctx, array, ep - 1, offset, e, keys, n_keys);
+ }
+ if (m < e) {
+ sort_reference(ctx, ep + 1, array + n - 1, offset - m, e - m, keys, n_keys);
+ }
+ }
+ {
+ int i;
+ grn_id *v;
+ for (i = 0, ep = array + offset; i < limit && ep < array + n; i++, ep++) {
+ if (!grn_array_add(ctx, (grn_array *)result, (void **)&v)) { break; }
+ *v = ep->id;
+ }
+ GRN_FREE(array);
+ return i;
+ }
+}
+
+
+typedef struct {
+ grn_id id;
+ grn_obj value;
+} sort_value_entry;
+
+inline static int
+compare_value(grn_ctx *ctx,
+ sort_value_entry *a, sort_value_entry *b,
+ grn_table_sort_key *keys, int n_keys,
+ grn_obj *a_buffer, grn_obj *b_buffer)
+{
+ int i;
+ uint8_t type;
+ uint32_t as, bs;
+ const unsigned char *ap, *bp;
+ for (i = 0; i < n_keys; i++, keys++) {
+ if (i) {
+ GRN_BULK_REWIND(a_buffer);
+ GRN_BULK_REWIND(b_buffer);
+ if (keys->flags & GRN_TABLE_SORT_DESC) {
+ grn_obj_get_value(ctx, keys->key, b->id, a_buffer);
+ grn_obj_get_value(ctx, keys->key, a->id, b_buffer);
+ } else {
+ grn_obj_get_value(ctx, keys->key, a->id, a_buffer);
+ grn_obj_get_value(ctx, keys->key, b->id, b_buffer);
+ }
+ ap = (const unsigned char *)GRN_BULK_HEAD(a_buffer);
+ as = GRN_BULK_VSIZE(a_buffer);
+ bp = (const unsigned char *)GRN_BULK_HEAD(b_buffer);
+ bs = GRN_BULK_VSIZE(b_buffer);
+ } else {
+ if (keys->flags & GRN_TABLE_SORT_DESC) {
+ ap = (const unsigned char *)GRN_BULK_HEAD(&b->value);
+ as = GRN_BULK_VSIZE(&b->value);
+ bp = (const unsigned char *)GRN_BULK_HEAD(&a->value);
+ bs = GRN_BULK_VSIZE(&a->value);
+ } else {
+ ap = (const unsigned char *)GRN_BULK_HEAD(&a->value);
+ as = GRN_BULK_VSIZE(&a->value);
+ bp = (const unsigned char *)GRN_BULK_HEAD(&b->value);
+ bs = GRN_BULK_VSIZE(&b->value);
+ }
+ }
+ type = keys->offset;
+ switch (type) {
+ case KEY_ID :
+ if (ap != bp) { return ap > bp; }
+ break;
+ case KEY_BULK :
+ for (;; ap++, bp++, as--, bs--) {
+ if (!as) { if (bs) { return 0; } else { break; } }
+ if (!bs) { return 1; }
+ if (*ap < *bp) { return 0; }
+ if (*ap > *bp) { return 1; }
+ }
+ break;
+ case KEY_INT8 :
+ CMPNUM(int8_t);
+ break;
+ case KEY_INT16 :
+ CMPNUM(int16_t);
+ break;
+ case KEY_INT32 :
+ CMPNUM(int32_t);
+ break;
+ case KEY_INT64 :
+ CMPNUM(int64_t);
+ break;
+ case KEY_UINT8 :
+ CMPNUM(uint8_t);
+ break;
+ case KEY_UINT16 :
+ CMPNUM(uint16_t);
+ break;
+ case KEY_UINT32 :
+ CMPNUM(uint32_t);
+ break;
+ case KEY_UINT64 :
+ CMPNUM(uint64_t);
+ break;
+ case KEY_FLOAT32 :
+ if (as) {
+ if (bs) {
+ float va = *((float *)(ap));
+ float vb = *((float *)(bp));
+ if (va < vb || va > vb) { return va > vb; }
+ } else {
+ return 1;
+ }
+ } else {
+ if (bs) { return 0; }
+ }
+ break;
+ case KEY_FLOAT64 :
+ if (as) {
+ if (bs) {
+ double va = *((double *)(ap));
+ double vb = *((double *)(bp));
+ if (va < vb || va > vb) { return va > vb; }
+ } else {
+ return 1;
+ }
+ } else {
+ if (bs) { return 0; }
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+inline static void
+swap_value(sort_value_entry *a, sort_value_entry *b)
+{
+ sort_value_entry c_ = *a;
+ *a = *b;
+ *b = c_;
+}
+
+inline static sort_value_entry *
+part_value(grn_ctx *ctx,
+ sort_value_entry *b, sort_value_entry *e,
+ grn_table_sort_key *keys, int n_keys,
+ grn_obj *a_buffer, grn_obj *b_buffer)
+{
+ sort_value_entry *c;
+ intptr_t d = e - b;
+ if (compare_value(ctx, b, e, keys, n_keys, a_buffer, b_buffer)) {
+ swap_value(b, e);
+ }
+ if (d < 2) { return NULL; }
+ c = b + (d >> 1);
+ if (compare_value(ctx, b, c, keys, n_keys, a_buffer, b_buffer)) {
+ swap_value(b, c);
+ } else {
+ if (compare_value(ctx, c, e, keys, n_keys, a_buffer, b_buffer)) {
+ swap_value(c, e);
+ }
+ }
+ if (d < 3) { return NULL; }
+ b++;
+ swap_value(b, c);
+ c = b;
+ for (;;) {
+ do {
+ b++;
+ } while (compare_value(ctx, c, b, keys, n_keys, a_buffer, b_buffer));
+ do {
+ e--;
+ } while (compare_value(ctx, e, c, keys, n_keys, a_buffer, b_buffer));
+ if (b >= e) { break; }
+ swap_value(b, e);
+ }
+ swap_value(c, e);
+ return e;
+}
+
+static void
+sort_value(grn_ctx *ctx,
+ sort_value_entry *head, sort_value_entry *tail,
+ int from, int to,
+ grn_table_sort_key *keys, int n_keys,
+ grn_obj *a_buffer, grn_obj *b_buffer)
+{
+ sort_value_entry *c;
+ if (head < tail && (c = part_value(ctx, head, tail, keys, n_keys,
+ a_buffer, b_buffer))) {
+ intptr_t m = c - head + 1;
+ if (from < m - 1) {
+ sort_value(ctx, head, c - 1, from, to, keys, n_keys, a_buffer, b_buffer);
+ }
+ if (m < to) {
+ sort_value(ctx, c + 1, tail, from - m, to - m, keys, n_keys,
+ a_buffer, b_buffer);
+ }
+ }
+}
+
+static sort_value_entry *
+pack_value(grn_ctx *ctx, grn_obj *table,
+ sort_value_entry *head, sort_value_entry *tail,
+ grn_table_sort_key *keys, int n_keys,
+ grn_obj *a_buffer, grn_obj *b_buffer)
+{
+ int i = 0;
+ sort_value_entry e, c;
+ grn_table_cursor *tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0);
+ if (!tc) { return NULL; }
+ if ((c.id = grn_table_cursor_next_inline(ctx, tc))) {
+ GRN_TEXT_INIT(&c.value, 0);
+ grn_obj_get_value(ctx, keys->key, c.id, &c.value);
+ while ((e.id = grn_table_cursor_next_inline(ctx, tc))) {
+ GRN_TEXT_INIT(&e.value, 0);
+ grn_obj_get_value(ctx, keys->key, e.id, &e.value);
+ if (compare_value(ctx, &c, &e, keys, n_keys, a_buffer, b_buffer)) {
+ *head++ = e;
+ } else {
+ *tail-- = e;
+ }
+ i++;
+ }
+ *head = c;
+ i++;
+ }
+ grn_table_cursor_close(ctx, tc);
+ return i > 2 ? head : NULL;
+}
+
+static int
+grn_table_sort_value(grn_ctx *ctx, grn_obj *table,
+ int offset, int limit,
+ grn_obj *result,
+ grn_table_sort_key *keys, int n_keys)
+{
+ int e, n;
+ sort_value_entry *array, *ep;
+ e = offset + limit;
+ n = grn_table_size(ctx, table);
+ if (!(array = GRN_MALLOC(sizeof(sort_value_entry) * n))) {
+ return 0;
+ }
+ {
+ grn_obj a_buffer;
+ grn_obj b_buffer;
+ GRN_TEXT_INIT(&a_buffer, 0);
+ GRN_TEXT_INIT(&b_buffer, 0);
+ if ((ep = pack_value(ctx, table, array, array + n - 1, keys, n_keys,
+ &a_buffer, &b_buffer))) {
+ intptr_t m = ep - array + 1;
+ if (offset < m - 1) {
+ sort_value(ctx, array, ep - 1, offset, e, keys, n_keys,
+ &a_buffer, &b_buffer);
+ }
+ if (m < e) {
+ sort_value(ctx, ep + 1, array + n - 1, offset - m, e - m, keys, n_keys,
+ &a_buffer, &b_buffer);
+ }
+ }
+ GRN_OBJ_FIN(ctx, &a_buffer);
+ GRN_OBJ_FIN(ctx, &b_buffer);
+ }
+ {
+ int i;
+ grn_id *v;
+ for (i = 0, ep = array + offset; i < limit && ep < array + n; i++, ep++) {
+ if (!grn_array_add(ctx, (grn_array *)result, (void **)&v)) { break; }
+ *v = ep->id;
+ }
+ GRN_FREE(array);
+ return i;
+ }
+}
+
+static grn_bool
+is_compressed_column(grn_ctx *ctx, grn_obj *obj)
+{
+ if (!obj) {
+ return GRN_FALSE;
+ }
+
+ if (obj->header.type != GRN_COLUMN_VAR_SIZE) {
+ return GRN_FALSE;
+ }
+
+ return (obj->header.flags & (GRN_OBJ_COMPRESS_ZLIB | GRN_OBJ_COMPRESS_LZ4));
+}
+
+static grn_bool
+is_sub_record_accessor(grn_ctx *ctx, grn_obj *obj)
+{
+ grn_accessor *accessor;
+
+ if (!obj) {
+ return GRN_FALSE;
+ }
+
+ if (obj->header.type != GRN_ACCESSOR) {
+ return GRN_FALSE;
+ }
+
+ for (accessor = (grn_accessor *)obj; accessor; accessor = accessor->next) {
+ switch (accessor->action) {
+ case GRN_ACCESSOR_GET_VALUE :
+ if (GRN_TABLE_IS_MULTI_KEYS_GROUPED(accessor->obj)) {
+ return GRN_TRUE;
+ }
+ break;
+ default :
+ break;
+ }
+ }
+
+ return GRN_FALSE;
+}
+
+static int
range_is_idp(grn_obj *obj)
{
if (obj && obj->header.type == GRN_ACCESSOR) {
@@ -8979,7 +10202,6 @@ grn_table_sort(grn_ctx *ctx, grn_obj *table, int offset, int limit,
grn_rc rc;
grn_obj *index;
int n, e, i = 0;
- sort_entry *array, *ep;
GRN_API_ENTER;
if (!n_keys || !keys) {
WARN(GRN_INVALID_ARGUMENT, "keys is null");
@@ -9034,8 +10256,17 @@ grn_table_sort(grn_ctx *ctx, grn_obj *table, int offset, int limit,
}
} else {
int j;
+ grn_bool have_compressed_column = GRN_FALSE;
+ grn_bool have_sub_record_accessor = GRN_FALSE;
+ grn_bool have_index_value_get = GRN_FALSE;
grn_table_sort_key *kp;
for (kp = keys, j = n_keys; j; kp++, j--) {
+ if (is_compressed_column(ctx, kp->key)) {
+ have_compressed_column = GRN_TRUE;
+ }
+ if (is_sub_record_accessor(ctx, kp->key)) {
+ have_sub_record_accessor = GRN_TRUE;
+ }
if (range_is_idp(kp->key)) {
kp->offset = KEY_ID;
} else {
@@ -9101,25 +10332,21 @@ grn_table_sort(grn_ctx *ctx, grn_obj *table, int offset, int limit,
}
}
} else {
+ if (kp->key->header.type == GRN_COLUMN_INDEX) {
+ have_index_value_get = GRN_TRUE;
+ }
kp->offset = KEY_UINT32;
}
}
}
- if (!(array = GRN_MALLOC(sizeof(sort_entry) * n))) {
- goto exit;
- }
- if ((ep = pack(ctx, table, array, array + n - 1, keys, n_keys))) {
- intptr_t m = ep - array + 1;
- if (offset < m - 1) { _sort(ctx, array, ep - 1, offset, e, keys, n_keys); }
- if (m < e) { _sort(ctx, ep + 1, array + n - 1, offset - m, e - m, keys, n_keys); }
- }
- {
- grn_id *v;
- for (i = 0, ep = array + offset; i < limit && ep < array + n; i++, ep++) {
- if (!grn_array_add(ctx, (grn_array *)result, (void **)&v)) { break; }
- *v = ep->id;
- }
- GRN_FREE(array);
+ if (have_compressed_column ||
+ have_sub_record_accessor ||
+ have_index_value_get) {
+ i = grn_table_sort_value(ctx, table, offset, limit, result,
+ keys, n_keys);
+ } else {
+ i = grn_table_sort_reference(ctx, table, offset, limit, result,
+ keys, n_keys);
}
}
exit :
@@ -9207,6 +10434,7 @@ grn_db_init_builtin_types(grn_ctx *ctx)
#endif
grn_db_init_builtin_tokenizers(ctx);
grn_db_init_builtin_normalizers(ctx);
+ grn_db_init_builtin_scorers(ctx);
for (id = grn_db_curr_id(ctx, db) + 1; id < 128; id++) {
grn_itoh(id, buf + 3, 2);
grn_obj_register(ctx, db, buf, 5);
@@ -9255,9 +10483,22 @@ grn_column_index_column_match(grn_ctx *ctx, grn_obj *obj, grn_operator op,
{
int n = 0;
grn_obj **ip = indexbuf;
+ grn_hook_entry hook_entry;
grn_hook *hooks;
- for (hooks = DB_OBJ(obj)->hooks[GRN_HOOK_SET]; hooks; hooks = hooks->next) {
+ switch (obj->header.type) {
+ case GRN_TABLE_HASH_KEY :
+ case GRN_TABLE_PAT_KEY :
+ case GRN_TABLE_DAT_KEY :
+ case GRN_TABLE_NO_KEY :
+ hook_entry = GRN_HOOK_INSERT;
+ break;
+ default :
+ hook_entry = GRN_HOOK_SET;
+ break;
+ }
+
+ for (hooks = DB_OBJ(obj)->hooks[hook_entry]; hooks; hooks = hooks->next) {
default_set_value_hook_data *data = (void *)NEXT_ADDR(hooks);
grn_obj *target = grn_ctx_at(ctx, data->target);
if (target->header.type != GRN_COLUMN_INDEX) { continue; }
@@ -9432,7 +10673,7 @@ grn_column_index_accessor(grn_ctx *ctx, grn_obj *obj, grn_operator op,
while (a) {
grn_hook *hooks;
grn_bool found = GRN_FALSE;
- grn_hook_entry entry = -1;
+ grn_hook_entry entry = (grn_hook_entry)-1;
if (a->action == GRN_ACCESSOR_GET_COLUMN_VALUE &&
GRN_OBJ_INDEX_COLUMNP(a->obj)) {
@@ -9451,7 +10692,7 @@ grn_column_index_accessor(grn_ctx *ctx, grn_obj *obj, grn_operator op,
break;
}
- if (entry == -1) {
+ if (entry == (grn_hook_entry)-1) {
break;
}
@@ -9832,7 +11073,7 @@ grn_table_tokenize(grn_ctx *ctx, grn_obj *table,
grn_obj *buf, grn_bool addp)
{
grn_token_cursor *token_cursor = NULL;
- grn_token_mode mode = addp ? GRN_TOKEN_ADD : GRN_TOKEN_GET;
+ grn_tokenize_mode mode = addp ? GRN_TOKENIZE_ADD : GRN_TOKENIZE_GET;
GRN_API_ENTER;
if (!(token_cursor = grn_token_cursor_open(ctx, table, str, str_len, mode, 0))) {
goto exit;
@@ -9844,7 +11085,7 @@ grn_table_tokenize(grn_ctx *ctx, grn_obj *table,
goto exit;
}
}
- while (token_cursor->status != GRN_TOKEN_DONE && token_cursor->status != GRN_TOKEN_DONE_SKIP) {
+ while (token_cursor->status != GRN_TOKEN_CURSOR_DONE && token_cursor->status != GRN_TOKEN_CURSOR_DONE_SKIP) {
grn_id tid;
if ((tid = grn_token_cursor_next(ctx, token_cursor))) {
GRN_RECORD_PUT(ctx, buf, tid);
@@ -10258,7 +11499,7 @@ brace_close(grn_ctx *ctx, grn_loader *loader)
(int)GRN_TEXT_LEN(key_column_name),
GRN_TEXT_VALUE(key_column_name),
column_name_size, column_name);
- return;
+ goto exit;
}
key_column_name = value;
v++;
@@ -10271,7 +11512,62 @@ brace_close(grn_ctx *ctx, grn_loader *loader)
}
break;
case GRN_TABLE_NO_KEY :
- id = grn_table_add(ctx, loader->table, NULL, 0, NULL);
+ {
+ grn_obj *v;
+ grn_bool found_id_column = GRN_FALSE;
+ for (v = value; v + 1 < ve; v = values_next(ctx, v)) {
+ char *column_name = GRN_TEXT_VALUE(v);
+ unsigned int column_name_size = GRN_TEXT_LEN(v);
+ if (v->header.domain == GRN_DB_TEXT &&
+ (name_equal(column_name, column_name_size,
+ GRN_COLUMN_NAME_ID))) {
+ grn_obj *id_column;
+ grn_obj *id_value;
+ if (found_id_column) {
+ GRN_LOG(ctx, GRN_LOG_ERROR, "duplicated '_id' column");
+ goto exit;
+ }
+ found_id_column = GRN_TRUE;
+ id_column = v;
+ v = values_next(ctx, v);
+ id_value = v;
+ switch (id_value->header.type) {
+ case GRN_DB_UINT32 :
+ id = GRN_UINT32_VALUE(id_value);
+ break;
+ case GRN_DB_INT32 :
+ id = GRN_INT32_VALUE(id_value);
+ break;
+ default :
+ {
+ grn_obj casted_id_value;
+ GRN_UINT32_INIT(&casted_id_value, 0);
+ if (grn_obj_cast(ctx, id_value, &casted_id_value, GRN_FALSE)) {
+ grn_obj inspected;
+ GRN_TEXT_INIT(&inspected, 0);
+ grn_inspect(ctx, &inspected, id_value);
+ ERR(GRN_INVALID_ARGUMENT,
+ "<%.*s>: failed to cast to <UInt32>: <%.*s>",
+ (int)column_name_size, column_name,
+ (int)GRN_TEXT_LEN(&inspected),
+ GRN_TEXT_VALUE(&inspected));
+ grn_obj_unlink(ctx, &inspected);
+ goto exit;
+ } else {
+ id = GRN_UINT32_VALUE(&casted_id_value);
+ }
+ GRN_OBJ_FIN(ctx, &casted_id_value);
+ }
+ break;
+ }
+ } else {
+ v = values_next(ctx, v);
+ }
+ }
+ }
+ if (id == GRN_ID_NIL) {
+ id = grn_table_add(ctx, loader->table, NULL, 0, NULL);
+ }
break;
default :
break;
@@ -10329,6 +11625,7 @@ brace_close(grn_ctx *ctx, grn_loader *loader)
GRN_LOG(ctx, GRN_LOG_ERROR, "neither _key nor _id is assigned");
}
}
+ exit:
loader->values_size = begin;
}
}
@@ -10800,3 +12097,161 @@ grn_load(grn_ctx *ctx, grn_content_type input_type,
ifexists, ifexists_len, each, each_len, 1);
GRN_API_RETURN(ctx->rc);
}
+
+static void
+grn_db_recover_database(grn_ctx *ctx, grn_obj *db)
+{
+ if (!grn_obj_is_locked(ctx, db)) {
+ return;
+ }
+
+ ERR(GRN_OBJECT_CORRUPT,
+ "[db][recover] database may be broken. Please re-create the database");
+}
+
+static void
+grn_db_recover_table(grn_ctx *ctx, grn_obj *table)
+{
+ if (!grn_obj_is_locked(ctx, table)) {
+ return;
+ }
+
+ {
+ char name[GRN_TABLE_MAX_KEY_SIZE];
+ unsigned int name_size;
+ name_size = grn_obj_name(ctx, table, name, GRN_TABLE_MAX_KEY_SIZE);
+ ERR(GRN_OBJECT_CORRUPT,
+ "[db][recover] table may be broken: <%.*s>: "
+ "please truncate the table (or clear lock of the table) "
+ "and load data again",
+ (int)name_size, name);
+ }
+}
+
+static void
+grn_db_recover_data_column(grn_ctx *ctx, grn_obj *data_column)
+{
+ if (!grn_obj_is_locked(ctx, data_column)) {
+ return;
+ }
+
+ {
+ char name[GRN_TABLE_MAX_KEY_SIZE];
+ unsigned int name_size;
+ name_size = grn_obj_name(ctx, data_column, name, GRN_TABLE_MAX_KEY_SIZE);
+ ERR(GRN_OBJECT_CORRUPT,
+ "[db][recover] column may be broken: <%.*s>: "
+ "please truncate the column (or clear lock of the column) "
+ "and load data again",
+ (int)name_size, name);
+ }
+}
+
+static void
+grn_db_recover_index_column(grn_ctx *ctx, grn_obj *index_column)
+{
+ grn_ii *ii = (grn_ii *)index_column;
+
+ if (!grn_obj_is_locked(ctx, index_column)) {
+ return;
+ }
+
+ grn_ii_truncate(ctx, ii);
+ build_index(ctx, index_column);
+}
+
+grn_rc
+grn_db_recover(grn_ctx *ctx, grn_obj *db)
+{
+ grn_table_cursor *cursor;
+ grn_id id;
+
+ GRN_API_ENTER;
+
+ grn_db_recover_database(ctx, db);
+ if (ctx->rc != GRN_SUCCESS) {
+ GRN_API_RETURN(ctx->rc);
+ }
+
+ cursor = grn_table_cursor_open(ctx, db,
+ NULL, 0, NULL, 0,
+ 0, -1,
+ GRN_CURSOR_BY_ID);
+ if (!cursor) {
+ GRN_API_RETURN(ctx->rc);
+ }
+
+ while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) {
+ grn_obj *object;
+
+ if ((object = grn_ctx_at(ctx, id))) {
+ switch (object->header.type) {
+ case GRN_TABLE_NO_KEY :
+ case GRN_TABLE_HASH_KEY :
+ case GRN_TABLE_PAT_KEY :
+ case GRN_TABLE_DAT_KEY :
+ grn_db_recover_table(ctx, object);
+ break;
+ case GRN_COLUMN_FIX_SIZE :
+ case GRN_COLUMN_VAR_SIZE :
+ grn_db_recover_data_column(ctx, object);
+ break;
+ case GRN_COLUMN_INDEX :
+ grn_db_recover_index_column(ctx, object);
+ break;
+ default:
+ break;
+ }
+ grn_obj_unlink(ctx, object);
+ } else {
+ ERRCLR(ctx);
+ }
+
+ if (ctx->rc != GRN_SUCCESS) {
+ break;
+ }
+ }
+ grn_table_cursor_close(ctx, cursor);
+
+ GRN_API_RETURN(ctx->rc);
+}
+
+grn_rc
+grn_ctx_get_all_tables(grn_ctx *ctx, grn_obj *tables_buffer)
+{
+ grn_obj *db;
+ grn_table_cursor *cursor;
+ grn_id id;
+
+ GRN_API_ENTER;
+
+ db = ctx->impl->db;
+ if (!db) {
+ ERR(GRN_INVALID_ARGUMENT, "DB isn't associated");
+ GRN_API_RETURN(ctx->rc);
+ }
+
+ cursor = grn_table_cursor_open(ctx, db, NULL, 0, NULL, 0, 0, -1, 0);
+ if (!cursor) {
+ GRN_API_RETURN(ctx->rc);
+ }
+
+ while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) {
+ grn_obj *object;
+
+ if ((object = grn_ctx_at(ctx, id))) {
+ if (grn_obj_is_table(ctx, object)) {
+ GRN_PTR_PUT(ctx, tables_buffer, object);
+ } else {
+ grn_obj_unlink(ctx, object);
+ }
+ } else {
+ if (ctx->rc != GRN_SUCCESS) {
+ ERRCLR(ctx);
+ }
+ }
+ }
+ grn_table_cursor_close(ctx, cursor);
+
+ GRN_API_RETURN(ctx->rc);
+}
diff --git a/storage/mroonga/vendor/groonga/lib/error.c b/storage/mroonga/vendor/groonga/lib/error.c
index 322b29bff7a..e14ef3754fd 100644
--- a/storage/mroonga/vendor/groonga/lib/error.c
+++ b/storage/mroonga/vendor/groonga/lib/error.c
@@ -15,7 +15,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "error.h"
+#include "grn_error.h"
#ifdef HAVE_ERRNO_H
#include <errno.h>
@@ -28,17 +28,28 @@ const char *
grn_current_error_message(void)
{
# define ERROR_MESSAGE_BUFFER_SIZE 4096
- int error_code = WSAGetLastError();
+ int error_code = GetLastError();
static char message[ERROR_MESSAGE_BUFFER_SIZE];
+ DWORD written_bytes;
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- error_code,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- message,
- ERROR_MESSAGE_BUFFER_SIZE,
- NULL);
+ written_bytes = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ error_code,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ message,
+ ERROR_MESSAGE_BUFFER_SIZE,
+ NULL);
+ if (written_bytes >= 2) {
+ if (message[written_bytes - 1] == '\n') {
+ message[written_bytes - 1] = '\0';
+ written_bytes--;
+ }
+ if (message[written_bytes - 1] == '\r') {
+ message[written_bytes - 1] = '\0';
+ written_bytes--;
+ }
+ }
return message;
diff --git a/storage/mroonga/vendor/groonga/lib/expr.c b/storage/mroonga/vendor/groonga/lib/expr.c
index dd70ebecb40..ef477eb77ee 100644
--- a/storage/mroonga/vendor/groonga/lib/expr.c
+++ b/storage/mroonga/vendor/groonga/lib/expr.c
@@ -1,6 +1,6 @@
/* -*- c-basic-offset: 2 -*- */
/*
- Copyright(C) 2010-2014 Brazil
+ Copyright(C) 2010-2015 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -15,33 +15,19 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "groonga_in.h"
-#include "db.h"
-#include "ctx_impl.h"
+#include "grn.h"
+#include "grn_db.h"
+#include "grn_ctx_impl.h"
#include <string.h>
#include <float.h>
-#include "ii.h"
-#include "geo.h"
-#include "expr.h"
-#include "util.h"
-#include "normalizer_in.h"
-#include "mrb.h"
+#include "grn_ii.h"
+#include "grn_geo.h"
+#include "grn_expr.h"
+#include "grn_util.h"
+#include "grn_normalizer.h"
+#include "grn_mrb.h"
#include "mrb/mrb_expr.h"
-static inline int
-function_proc_p(grn_obj *obj)
-{
- return (obj &&
- obj->header.type == GRN_PROC &&
- ((grn_proc *)obj)->type == GRN_PROC_FUNCTION);
-}
-
-static inline int
-selector_proc_p(grn_obj *obj)
-{
- return (function_proc_p(obj) && ((grn_proc *)obj)->selector);
-}
-
grn_obj *
grn_expr_alloc(grn_ctx *ctx, grn_obj *expr, grn_id domain, grn_obj_flags flags)
{
@@ -60,7 +46,7 @@ grn_expr_alloc(grn_ctx *ctx, grn_obj *expr, grn_id domain, grn_obj_flags flags)
return res;
}
-static grn_hash *
+grn_hash *
grn_expr_get_vars(grn_ctx *ctx, grn_obj *expr, unsigned int *nvars)
{
grn_hash *vars = NULL;
@@ -131,6 +117,18 @@ grn_proc_get_info(grn_ctx *ctx, grn_user_data *user_data,
}
grn_obj *
+grn_proc_get_vars(grn_ctx *ctx, grn_user_data *user_data)
+{
+ uint32_t n;
+ grn_proc_ctx *pctx = (grn_proc_ctx *)user_data;
+ if (pctx->proc) {
+ return (grn_obj *)grn_expr_get_vars(ctx, (grn_obj *)pctx->proc, &n);
+ } else {
+ return NULL;
+ }
+}
+
+grn_obj *
grn_proc_get_var(grn_ctx *ctx, grn_user_data *user_data, const char *name, unsigned int name_size)
{
grn_proc_ctx *pctx = (grn_proc_ctx *)user_data;
@@ -170,7 +168,7 @@ grn_rc
grn_proc_set_selector(grn_ctx *ctx, grn_obj *proc, grn_selector_func selector)
{
grn_proc *proc_ = (grn_proc *)proc;
- if (!function_proc_p(proc)) {
+ if (!grn_obj_is_function_proc(ctx, proc)) {
return GRN_INVALID_ARGUMENT;
}
proc_->selector = selector;
@@ -179,151 +177,6 @@ grn_proc_set_selector(grn_ctx *ctx, grn_obj *proc, grn_selector_func selector)
/* grn_expr */
-static const char *opstrs[] = {
- "PUSH",
- "POP",
- "NOP",
- "CALL",
- "INTERN",
- "GET_REF",
- "GET_VALUE",
- "AND",
- "AND_NOT",
- "OR",
- "ASSIGN",
- "STAR_ASSIGN",
- "SLASH_ASSIGN",
- "MOD_ASSIGN",
- "PLUS_ASSIGN",
- "MINUS_ASSIGN",
- "SHIFTL_ASSIGN",
- "SHIFTR_ASSIGN",
- "SHIFTRR_ASSIGN",
- "AND_ASSIGN",
- "XOR_ASSIGN",
- "OR_ASSIGN",
- "JUMP",
- "CJUMP",
- "COMMA",
- "BITWISE_OR",
- "BITWISE_XOR",
- "BITWISE_AND",
- "BITWISE_NOT",
- "EQUAL",
- "NOT_EQUAL",
- "LESS",
- "GREATER",
- "LESS_EQUAL",
- "GREATER_EQUAL",
- "IN",
- "MATCH",
- "NEAR",
- "NEAR2",
- "SIMILAR",
- "TERM_EXTRACT",
- "SHIFTL",
- "SHIFTR",
- "SHIFTRR",
- "PLUS",
- "MINUS",
- "STAR",
- "SLASH",
- "MOD",
- "DELETE",
- "INCR",
- "DECR",
- "INCR_POST",
- "DECR_POST",
- "NOT",
- "ADJUST",
- "EXACT",
- "LCP",
- "PARTIAL",
- "UNSPLIT",
- "PREFIX",
- "SUFFIX",
- "GEO_DISTANCE1",
- "GEO_DISTANCE2",
- "GEO_DISTANCE3",
- "GEO_DISTANCE4",
- "GEO_WITHINP5",
- "GEO_WITHINP6",
- "GEO_WITHINP8",
- "OBJ_SEARCH",
- "EXPR_GET_VAR",
- "TABLE_CREATE",
- "TABLE_SELECT",
- "TABLE_SORT",
- "TABLE_GROUP",
- "JSON_PUT"
-};
-
-static void
-put_value(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
-{
- int len;
- char namebuf[GRN_TABLE_MAX_KEY_SIZE];
- if ((len = grn_column_name(ctx, obj, namebuf, GRN_TABLE_MAX_KEY_SIZE))) {
- GRN_TEXT_PUT(ctx, buf, namebuf, len);
- } else {
- grn_text_otoj(ctx, buf, obj, NULL);
- }
-}
-
-grn_rc
-grn_expr_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *expr)
-{
- uint32_t i, j;
- grn_expr_var *var;
- grn_expr_code *code;
- grn_expr *e = (grn_expr *)expr;
- grn_hash *vars = grn_expr_get_vars(ctx, expr, &i);
- GRN_TEXT_PUTS(ctx, buf, "noname");
- GRN_TEXT_PUTC(ctx, buf, '(');
- {
- int i = 0;
- grn_obj *value;
- const char *name;
- uint32_t name_len;
- GRN_HASH_EACH(ctx, vars, id, &name, &name_len, &value, {
- if (i++) { GRN_TEXT_PUTC(ctx, buf, ','); }
- GRN_TEXT_PUT(ctx, buf, name, name_len);
- GRN_TEXT_PUTC(ctx, buf, ':');
- put_value(ctx, buf, value);
- });
- }
- GRN_TEXT_PUTC(ctx, buf, ')');
- GRN_TEXT_PUTC(ctx, buf, '{');
- for (j = 0, code = e->codes; j < e->codes_curr; j++, code++) {
- if (j) { GRN_TEXT_PUTC(ctx, buf, ','); }
- grn_text_itoa(ctx, buf, code->modify);
- if (code->op == GRN_OP_PUSH) {
- for (i = 0, var = e->vars; i < e->nvars; i++, var++) {
- if (&var->value == code->value) {
- GRN_TEXT_PUTC(ctx, buf, '?');
- if (var->name_size) {
- GRN_TEXT_PUT(ctx, buf, var->name, var->name_size);
- } else {
- grn_text_itoa(ctx, buf, (int)i);
- }
- break;
- }
- }
- if (i == e->nvars) {
- put_value(ctx, buf, code->value);
- }
- } else {
- if (code->value) {
- put_value(ctx, buf, code->value);
- GRN_TEXT_PUTC(ctx, buf, ' ');
- }
- GRN_TEXT_PUTS(ctx, buf, opstrs[code->op]);
- }
- }
- GRN_TEXT_PUTC(ctx, buf, '}');
- return GRN_SUCCESS;
-}
-
grn_obj *
grn_ctx_pop(grn_ctx *ctx)
{
@@ -929,7 +782,8 @@ grn_expr_append_obj(grn_ctx *ctx, grn_obj *expr, grn_obj *obj, grn_operator op,
ERR(GRN_INVALID_ARGUMENT, "invalid function call expression");
goto exit;
}
- if (!function_proc_p(proc)) {
+ if (!(grn_obj_is_function_proc(ctx, proc) ||
+ grn_obj_is_scorer_proc(ctx, proc))) {
grn_obj buffer;
GRN_TEXT_INIT(&buffer, 0);
@@ -1367,425 +1221,6 @@ grn_expr_compile(grn_ctx *ctx, grn_obj *expr)
s1 = sp[-2];\
} while (0)
-#define DO_COMPARE_SUB_NUMERIC(y,op) do {\
- switch ((y)->header.domain) {\
- case GRN_DB_INT8 :\
- r = (x_ op GRN_INT8_VALUE(y));\
- break;\
- case GRN_DB_UINT8 :\
- r = (x_ op GRN_UINT8_VALUE(y));\
- break;\
- case GRN_DB_INT16 :\
- r = (x_ op GRN_INT16_VALUE(y));\
- break;\
- case GRN_DB_UINT16 :\
- r = (x_ op GRN_UINT16_VALUE(y));\
- break;\
- case GRN_DB_INT32 :\
- r = (x_ op GRN_INT32_VALUE(y));\
- break;\
- case GRN_DB_UINT32 :\
- r = (x_ op GRN_UINT32_VALUE(y));\
- break;\
- case GRN_DB_INT64 :\
- r = (x_ op GRN_INT64_VALUE(y));\
- break;\
- case GRN_DB_TIME :\
- r = (GRN_TIME_PACK(x_,0) op GRN_INT64_VALUE(y));\
- break;\
- case GRN_DB_UINT64 :\
- r = (x_ op GRN_UINT64_VALUE(y));\
- break;\
- case GRN_DB_FLOAT :\
- r = (x_ op GRN_FLOAT_VALUE(y));\
- break;\
- default :\
- r = 0;\
- break;\
- }\
-} while (0)
-
-#define DO_COMPARE_SUB(op) do {\
- switch (y->header.domain) {\
- case GRN_DB_SHORT_TEXT :\
- case GRN_DB_TEXT :\
- case GRN_DB_LONG_TEXT :\
- {\
- grn_obj y_;\
- GRN_OBJ_INIT(&y_, GRN_BULK, 0, x->header.domain);\
- if (grn_obj_cast(ctx, y, &y_, GRN_FALSE)) {\
- r = 0;\
- } else {\
- DO_COMPARE_SUB_NUMERIC(&y_, op);\
- }\
- GRN_OBJ_FIN(ctx, &y_);\
- }\
- break;\
- default :\
- DO_COMPARE_SUB_NUMERIC(y,op);\
- break;\
- }\
-} while (0)
-
-#define DO_COMPARE_BUILTIN(x,y,r,op) do {\
- switch (x->header.domain) {\
- case GRN_DB_INT8 :\
- {\
- int8_t x_ = GRN_INT8_VALUE(x);\
- DO_COMPARE_SUB(op);\
- }\
- break;\
- case GRN_DB_UINT8 :\
- {\
- uint8_t x_ = GRN_UINT8_VALUE(x);\
- DO_COMPARE_SUB(op);\
- }\
- break;\
- case GRN_DB_INT16 :\
- {\
- int16_t x_ = GRN_INT16_VALUE(x);\
- DO_COMPARE_SUB(op);\
- }\
- break;\
- case GRN_DB_UINT16 :\
- {\
- uint16_t x_ = GRN_UINT16_VALUE(x);\
- DO_COMPARE_SUB(op);\
- }\
- break;\
- case GRN_DB_INT32 :\
- {\
- int32_t x_ = GRN_INT32_VALUE(x);\
- DO_COMPARE_SUB(op);\
- }\
- break;\
- case GRN_DB_UINT32 :\
- {\
- uint32_t x_ = GRN_UINT32_VALUE(x);\
- DO_COMPARE_SUB(op);\
- }\
- break;\
- case GRN_DB_TIME :\
- {\
- int64_t x_ = GRN_INT64_VALUE(x);\
- switch (y->header.domain) {\
- case GRN_DB_INT32 :\
- r = (x_ op GRN_TIME_PACK(GRN_INT32_VALUE(y), 0));\
- break;\
- case GRN_DB_UINT32 :\
- r = (x_ op GRN_TIME_PACK(GRN_UINT32_VALUE(y), 0));\
- break;\
- case GRN_DB_INT64 :\
- case GRN_DB_TIME :\
- r = (x_ op GRN_INT64_VALUE(y));\
- break;\
- case GRN_DB_UINT64 :\
- r = (x_ op GRN_UINT64_VALUE(y));\
- break;\
- case GRN_DB_FLOAT :\
- r = (x_ op GRN_TIME_PACK(GRN_FLOAT_VALUE(y), 0));\
- break;\
- case GRN_DB_SHORT_TEXT :\
- case GRN_DB_TEXT :\
- case GRN_DB_LONG_TEXT :\
- {\
- const char *p_ = GRN_TEXT_VALUE(y);\
- int i_ = grn_atoi(p_, p_ + GRN_TEXT_LEN(y), NULL);\
- r = (x_ op GRN_TIME_PACK(i_, 0));\
- }\
- break;\
- default :\
- r = 0;\
- break;\
- }\
- }\
- break;\
- case GRN_DB_INT64 :\
- {\
- int64_t x_ = GRN_INT64_VALUE(x);\
- DO_COMPARE_SUB(op);\
- }\
- break;\
- case GRN_DB_UINT64 :\
- {\
- uint64_t x_ = GRN_UINT64_VALUE(x);\
- DO_COMPARE_SUB(op);\
- }\
- break;\
- case GRN_DB_FLOAT :\
- {\
- double x_ = GRN_FLOAT_VALUE(x);\
- DO_COMPARE_SUB(op);\
- }\
- break;\
- case GRN_DB_SHORT_TEXT :\
- case GRN_DB_TEXT :\
- case GRN_DB_LONG_TEXT :\
- if (GRN_DB_SHORT_TEXT <= y->header.domain && y->header.domain <= GRN_DB_LONG_TEXT) {\
- int r_;\
- uint32_t la = GRN_TEXT_LEN(x), lb = GRN_TEXT_LEN(y);\
- if (la > lb) {\
- if (!(r_ = memcmp(GRN_TEXT_VALUE(x), GRN_TEXT_VALUE(y), lb))) {\
- r_ = 1;\
- }\
- } else {\
- if (!(r_ = memcmp(GRN_TEXT_VALUE(x), GRN_TEXT_VALUE(y), la))) {\
- r_ = la == lb ? 0 : -1;\
- }\
- }\
- r = (r_ op 0);\
- } else {\
- const char *q_ = GRN_TEXT_VALUE(x);\
- int x_ = grn_atoi(q_, q_ + GRN_TEXT_LEN(x), NULL);\
- DO_COMPARE_SUB(op);\
- }\
- break;\
- default :\
- r = 0;\
- break;\
- }\
-} while (0)
-
-#define DO_COMPARE(x, y, r, op) do {\
- if (x->header.domain >= GRN_N_RESERVED_TYPES) {\
- grn_obj *table;\
- table = grn_ctx_at(ctx, x->header.domain);\
- switch (table->header.type) {\
- case GRN_TABLE_HASH_KEY :\
- case GRN_TABLE_PAT_KEY :\
- {\
- grn_obj key;\
- int length;\
- GRN_OBJ_INIT(&key, GRN_BULK, 0, table->header.domain);\
- length = grn_table_get_key2(ctx, table, GRN_RECORD_VALUE(x), &key);\
- if (length > 0) {\
- grn_obj *x_original = x;\
- x = &key;\
- DO_COMPARE_BUILTIN((&key), y, r, op);\
- x = x_original;\
- } else {\
- r = 0;\
- }\
- GRN_OBJ_FIN(ctx, &key);\
- }\
- break;\
- default :\
- r = 0;\
- break;\
- }\
- grn_obj_unlink(ctx, table);\
- } else {\
- DO_COMPARE_BUILTIN(x, y, r, op);\
- }\
-} while (0)
-
-#define DO_EQ_SUB do {\
- switch (y->header.domain) {\
- case GRN_DB_INT8 :\
- r = (x_ == GRN_INT8_VALUE(y));\
- break;\
- case GRN_DB_UINT8 :\
- r = (x_ == GRN_UINT8_VALUE(y));\
- break;\
- case GRN_DB_INT16 :\
- r = (x_ == GRN_INT16_VALUE(y));\
- break;\
- case GRN_DB_UINT16 :\
- r = (x_ == GRN_UINT16_VALUE(y));\
- break;\
- case GRN_DB_INT32 :\
- r = (x_ == GRN_INT32_VALUE(y));\
- break;\
- case GRN_DB_UINT32 :\
- r = (x_ == GRN_UINT32_VALUE(y));\
- break;\
- case GRN_DB_INT64 :\
- r = (x_ == GRN_INT64_VALUE(y));\
- break;\
- case GRN_DB_TIME :\
- r = (GRN_TIME_PACK(x_,0) == GRN_INT64_VALUE(y));\
- break;\
- case GRN_DB_UINT64 :\
- r = (x_ == GRN_UINT64_VALUE(y));\
- break;\
- case GRN_DB_FLOAT :\
- r = ((x_ <= GRN_FLOAT_VALUE(y)) && (x_ >= GRN_FLOAT_VALUE(y)));\
- break;\
- case GRN_DB_SHORT_TEXT :\
- case GRN_DB_TEXT :\
- case GRN_DB_LONG_TEXT :\
- {\
- const char *p_ = GRN_TEXT_VALUE(y);\
- int i_ = grn_atoi(p_, p_ + GRN_TEXT_LEN(y), NULL);\
- r = (x_ == i_);\
- }\
- break;\
- default :\
- r = 0;\
- break;\
- }\
-} while (0)
-
-#define DO_EQ(x,y,r) do {\
- switch (x->header.domain) {\
- case GRN_DB_VOID :\
- r = 0;\
- break;\
- case GRN_DB_INT8 :\
- {\
- int8_t x_ = GRN_INT8_VALUE(x);\
- DO_EQ_SUB;\
- }\
- break;\
- case GRN_DB_UINT8 :\
- {\
- uint8_t x_ = GRN_UINT8_VALUE(x);\
- DO_EQ_SUB;\
- }\
- break;\
- case GRN_DB_INT16 :\
- {\
- int16_t x_ = GRN_INT16_VALUE(x);\
- DO_EQ_SUB;\
- }\
- break;\
- case GRN_DB_UINT16 :\
- {\
- uint16_t x_ = GRN_UINT16_VALUE(x);\
- DO_EQ_SUB;\
- }\
- break;\
- case GRN_DB_INT32 :\
- {\
- int32_t x_ = GRN_INT32_VALUE(x);\
- DO_EQ_SUB;\
- }\
- break;\
- case GRN_DB_UINT32 :\
- {\
- uint32_t x_ = GRN_UINT32_VALUE(x);\
- DO_EQ_SUB;\
- }\
- break;\
- case GRN_DB_INT64 :\
- {\
- int64_t x_ = GRN_INT64_VALUE(x);\
- DO_EQ_SUB;\
- }\
- break;\
- case GRN_DB_TIME :\
- {\
- int64_t x_ = GRN_INT64_VALUE(x);\
- switch (y->header.domain) {\
- case GRN_DB_INT32 :\
- r = (x_ == GRN_TIME_PACK(GRN_INT32_VALUE(y), 0));\
- break;\
- case GRN_DB_UINT32 :\
- r = (x_ == GRN_TIME_PACK(GRN_UINT32_VALUE(y), 0));\
- break;\
- case GRN_DB_INT64 :\
- case GRN_DB_TIME :\
- r = (x_ == GRN_INT64_VALUE(y));\
- break;\
- case GRN_DB_UINT64 :\
- r = (x_ == GRN_UINT64_VALUE(y));\
- break;\
- case GRN_DB_FLOAT :\
- r = (x_ == GRN_TIME_PACK(GRN_FLOAT_VALUE(y), 0));\
- break;\
- case GRN_DB_SHORT_TEXT :\
- case GRN_DB_TEXT :\
- case GRN_DB_LONG_TEXT :\
- {\
- const char *p_ = GRN_TEXT_VALUE(y);\
- int i_ = grn_atoi(p_, p_ + GRN_TEXT_LEN(y), NULL);\
- r = (x_ == GRN_TIME_PACK(i_, 0));\
- }\
- break;\
- default :\
- r = 0;\
- break;\
- }\
- }\
- break;\
- case GRN_DB_UINT64 :\
- {\
- uint64_t x_ = GRN_UINT64_VALUE(x);\
- DO_EQ_SUB;\
- }\
- break;\
- case GRN_DB_FLOAT :\
- {\
- double x_ = GRN_FLOAT_VALUE(x);\
- switch (y->header.domain) {\
- case GRN_DB_INT32 :\
- r = ((x_ <= GRN_INT32_VALUE(y)) && (x_ >= GRN_INT32_VALUE(y)));\
- break;\
- case GRN_DB_UINT32 :\
- r = ((x_ <= GRN_UINT32_VALUE(y)) && (x_ >= GRN_UINT32_VALUE(y)));\
- break;\
- case GRN_DB_INT64 :\
- case GRN_DB_TIME :\
- r = ((x_ <= GRN_INT64_VALUE(y)) && (x_ >= GRN_INT64_VALUE(y)));\
- break;\
- case GRN_DB_UINT64 :\
- r = ((x_ <= GRN_UINT64_VALUE(y)) && (x_ >= GRN_UINT64_VALUE(y)));\
- break;\
- case GRN_DB_FLOAT :\
- r = ((x_ <= GRN_FLOAT_VALUE(y)) && (x_ >= GRN_FLOAT_VALUE(y)));\
- break;\
- case GRN_DB_SHORT_TEXT :\
- case GRN_DB_TEXT :\
- case GRN_DB_LONG_TEXT :\
- {\
- const char *p_ = GRN_TEXT_VALUE(y);\
- int i_ = grn_atoi(p_, p_ + GRN_TEXT_LEN(y), NULL);\
- r = (x_ <= i_ && x_ >= i_);\
- }\
- break;\
- default :\
- r = 0;\
- break;\
- }\
- }\
- break;\
- case GRN_DB_SHORT_TEXT :\
- case GRN_DB_TEXT :\
- case GRN_DB_LONG_TEXT :\
- if (GRN_DB_SHORT_TEXT <= y->header.domain && y->header.domain <= GRN_DB_LONG_TEXT) {\
- uint32_t la = GRN_TEXT_LEN(x), lb = GRN_TEXT_LEN(y);\
- r = (la == lb && !memcmp(GRN_TEXT_VALUE(x), GRN_TEXT_VALUE(y), lb));\
- } else {\
- const char *q_ = GRN_TEXT_VALUE(x);\
- int x_ = grn_atoi(q_, q_ + GRN_TEXT_LEN(x), NULL);\
- DO_EQ_SUB;\
- }\
- break;\
- default :\
- if ((x->header.domain == y->header.domain)) {\
- r = (GRN_BULK_VSIZE(x) == GRN_BULK_VSIZE(y) &&\
- !(memcmp(GRN_BULK_HEAD(x), GRN_BULK_HEAD(y), GRN_BULK_VSIZE(x))));\
- } else {\
- grn_obj dest;\
- if (x->header.domain < y->header.domain) {\
- GRN_OBJ_INIT(&dest, GRN_BULK, 0, y->header.domain);\
- if (!grn_obj_cast(ctx, x, &dest, GRN_FALSE)) {\
- r = (GRN_BULK_VSIZE(&dest) == GRN_BULK_VSIZE(y) &&\
- !memcmp(GRN_BULK_HEAD(&dest), GRN_BULK_HEAD(y), GRN_BULK_VSIZE(y))); \
- }\
- } else {\
- GRN_OBJ_INIT(&dest, GRN_BULK, 0, x->header.domain);\
- if (!grn_obj_cast(ctx, y, &dest, GRN_FALSE)) {\
- r = (GRN_BULK_VSIZE(&dest) == GRN_BULK_VSIZE(x) &&\
- !memcmp(GRN_BULK_HEAD(&dest), GRN_BULK_HEAD(x), GRN_BULK_VSIZE(x))); \
- }\
- }\
- GRN_OBJ_FIN(ctx, &dest);\
- }\
- break;\
- }\
-} while (0)
-
#define GEO_RESOLUTION 3600000
#define GEO_RADIOUS 6357303
#define GEO_BES_C1 6334834
@@ -2230,7 +1665,8 @@ grn_proc_call(grn_ctx *ctx, grn_obj *proc, int nargs, grn_obj *caller)
code++; \
} while (0)
-#define ARITHMETIC_BINARY_OPERATION_DISPATCH(integer8_operation, \
+#define ARITHMETIC_BINARY_OPERATION_DISPATCH(operator, \
+ integer8_operation, \
integer16_operation, \
integer32_operation, \
integer64_operation, \
@@ -2242,6 +1678,23 @@ grn_proc_call(grn_ctx *ctx, grn_obj *proc, int nargs, grn_obj *caller)
grn_obj *x, *y; \
\
POP2ALLOC1(x, y, res); \
+ if (x->header.type == GRN_VECTOR || y->header.type == GRN_VECTOR) { \
+ grn_obj inspected_x; \
+ grn_obj inspected_y; \
+ GRN_TEXT_INIT(&inspected_x, 0); \
+ GRN_TEXT_INIT(&inspected_y, 0); \
+ grn_inspect(ctx, &inspected_x, x); \
+ grn_inspect(ctx, &inspected_y, y); \
+ ERR(GRN_INVALID_ARGUMENT, \
+ "<%s> doesn't support vector: <%.*s> %s <%.*s>", \
+ operator, \
+ (int)GRN_TEXT_LEN(&inspected_x), GRN_TEXT_VALUE(&inspected_x), \
+ operator, \
+ (int)GRN_TEXT_LEN(&inspected_y), GRN_TEXT_VALUE(&inspected_y)); \
+ GRN_OBJ_FIN(ctx, &inspected_x); \
+ GRN_OBJ_FIN(ctx, &inspected_y); \
+ goto exit; \
+ } \
if (y != res) { \
res->header.domain = x->header.domain; \
} \
@@ -2667,7 +2120,9 @@ grn_proc_call(grn_ctx *ctx, grn_obj *proc, int nargs, grn_obj *caller)
} \
if (GRN_BULK_VSIZE(var) != (sizeof(grn_obj *) + sizeof(grn_id))) { \
ERR(GRN_INVALID_ARGUMENT, \
- "invalid variable size: expected: %zu, actual: %zu", \
+ "invalid variable size: " \
+ "expected: %" GRN_FMT_SIZE \
+ "actual: %" GRN_FMT_SIZE, \
(sizeof(grn_obj *) + sizeof(grn_id)), GRN_BULK_VSIZE(var)); \
goto exit; \
} \
@@ -2769,49 +2224,271 @@ grn_proc_call(grn_ctx *ctx, grn_obj *proc, int nargs, grn_obj *caller)
} while (0)
static grn_bool
-pseudo_query_scan(grn_ctx *ctx, grn_obj *x, grn_obj *y)
+string_is_contained(grn_ctx *ctx,
+ const char *text, unsigned int text_len,
+ const char *sub_text, unsigned int sub_text_len)
+{
+ /* TODO: Use more fast algorithm such as Boyer-Moore algorithm that
+ * is used in snip.c. */
+ const char *text_end = text + text_len;
+ unsigned int sub_text_current = 0;
+
+ for (; text < text_end; text++) {
+ if (text[0] == sub_text[sub_text_current]) {
+ sub_text_current++;
+ if (sub_text_current == sub_text_len) {
+ return GRN_TRUE;
+ }
+ } else {
+ sub_text_current = 0;
+ }
+ }
+
+ return GRN_FALSE;
+}
+
+static grn_bool
+pseudo_query_scan_raw_text_raw_text(grn_ctx *ctx,
+ const char *x, unsigned int x_len,
+ const char *y, unsigned int y_len)
{
grn_obj *normalizer;
- grn_obj *a = NULL, *b = NULL;
+ grn_obj *norm_x;
+ grn_obj *norm_y;
+ const char *norm_x_raw;
+ const char *norm_y_raw;
+ unsigned int norm_x_raw_length_in_bytes;
+ unsigned int norm_y_raw_length_in_bytes;
grn_bool matched = GRN_FALSE;
+ if (x_len == 0 || y_len == 0) {
+ return GRN_FALSE;
+ }
+
normalizer = grn_ctx_get(ctx, GRN_NORMALIZER_AUTO_NAME, -1);
+ norm_x = grn_string_open(ctx, x, x_len, normalizer, 0);
+ norm_y = grn_string_open(ctx, y, y_len, normalizer, 0);
+ grn_string_get_normalized(ctx, norm_x,
+ &norm_x_raw, &norm_x_raw_length_in_bytes,
+ NULL);
+ grn_string_get_normalized(ctx, norm_y,
+ &norm_y_raw, &norm_y_raw_length_in_bytes,
+ NULL);
+ matched = string_is_contained(ctx,
+ norm_x_raw, norm_x_raw_length_in_bytes,
+ norm_y_raw, norm_y_raw_length_in_bytes);
+
+ grn_obj_close(ctx, norm_x);
+ grn_obj_close(ctx, norm_y);
+ grn_obj_unlink(ctx, normalizer);
+
+ return matched;
+}
+
+static grn_bool
+pseudo_query_scan_record_text(grn_ctx *ctx, grn_obj *record, grn_obj *table,
+ grn_obj *y)
+{
+ grn_obj *normalizer;
+ char x_key[GRN_TABLE_MAX_KEY_SIZE];
+ int x_key_len;
+ grn_bool matched = GRN_FALSE;
+
+ if (table->header.domain != GRN_DB_SHORT_TEXT) {
+ return GRN_FALSE;
+ }
+
+ x_key_len = grn_table_get_key(ctx, table, GRN_RECORD_VALUE(record),
+ x_key, GRN_TABLE_MAX_KEY_SIZE);
+ grn_table_get_info(ctx, table, NULL, NULL, NULL, &normalizer, NULL);
+ if (normalizer) {
+ grn_obj *norm_y;
+ const char *norm_y_raw;
+ unsigned int norm_y_raw_length_in_bytes;
+ norm_y = grn_string_open(ctx, GRN_TEXT_VALUE(y), GRN_TEXT_LEN(y),
+ normalizer, 0);
+ grn_string_get_normalized(ctx, norm_y,
+ &norm_y_raw, &norm_y_raw_length_in_bytes,
+ NULL);
+ matched = string_is_contained(ctx,
+ x_key, x_key_len,
+ norm_y_raw, norm_y_raw_length_in_bytes);
+ grn_obj_close(ctx, norm_y);
+ } else {
+ matched = pseudo_query_scan_raw_text_raw_text(ctx,
+ x_key,
+ x_key_len,
+ GRN_TEXT_VALUE(y),
+ GRN_TEXT_LEN(y));
+ }
+
+ return matched;
+}
+
+static grn_bool
+pseudo_query_scan_text_text(grn_ctx *ctx, grn_obj *x, grn_obj *y)
+{
+ return pseudo_query_scan_raw_text_raw_text(ctx,
+ GRN_TEXT_VALUE(x),
+ GRN_TEXT_LEN(x),
+ GRN_TEXT_VALUE(y),
+ GRN_TEXT_LEN(y));
+}
+
+static grn_bool
+pseudo_query_scan(grn_ctx *ctx, grn_obj *x, grn_obj *y)
+{
switch (x->header.domain) {
- case GRN_DB_SHORT_TEXT:
- case GRN_DB_TEXT:
- case GRN_DB_LONG_TEXT:
- a = grn_string_open(ctx, GRN_TEXT_VALUE(x), GRN_TEXT_LEN(x),
- normalizer, 0);
- break;
+ case GRN_DB_SHORT_TEXT :
+ case GRN_DB_TEXT :
+ case GRN_DB_LONG_TEXT :
+ switch (y->header.domain) {
+ case GRN_DB_SHORT_TEXT :
+ case GRN_DB_TEXT :
+ case GRN_DB_LONG_TEXT :
+ return pseudo_query_scan_text_text(ctx, x, y);
+ default :
+ break;
+ }
+ return GRN_FALSE;
default:
- break;
+ {
+ grn_obj *domain;
+ domain = grn_ctx_at(ctx, x->header.domain);
+ if (GRN_OBJ_TABLEP(domain)) {
+ switch (y->header.domain) {
+ case GRN_DB_SHORT_TEXT :
+ case GRN_DB_TEXT :
+ case GRN_DB_LONG_TEXT :
+ return pseudo_query_scan_record_text(ctx, x, domain, y);
+ default :
+ break;
+ }
+ }
+ }
+ return GRN_FALSE;
}
+}
- switch (y->header.domain) {
- case GRN_DB_SHORT_TEXT:
- case GRN_DB_TEXT:
- case GRN_DB_LONG_TEXT:
- b = grn_string_open(ctx, GRN_TEXT_VALUE(y), GRN_TEXT_LEN(y),
- normalizer, 0);
- break;
- default:
- break;
+static grn_bool
+pseudo_prefix_search_match(grn_ctx *ctx,
+ const char *x, unsigned int x_len,
+ const char *y, unsigned int y_len)
+{
+ return (x_len >= y_len && strncmp(x, y, y_len) == 0);
+}
+
+static grn_bool
+pseudo_prefix_search_raw_text_raw_text(grn_ctx *ctx,
+ const char *x, unsigned int x_len,
+ const char *y, unsigned int y_len)
+{
+ grn_obj *normalizer;
+ grn_obj *norm_x;
+ grn_obj *norm_y;
+ const char *norm_x_raw;
+ const char *norm_y_raw;
+ unsigned int norm_x_raw_len;
+ unsigned int norm_y_raw_len;
+ grn_bool matched = GRN_FALSE;
+
+ normalizer = grn_ctx_get(ctx, GRN_NORMALIZER_AUTO_NAME, -1);
+ norm_x = grn_string_open(ctx, x, x_len, normalizer, 0);
+ norm_y = grn_string_open(ctx, y, y_len, normalizer, 0);
+ grn_string_get_normalized(ctx, norm_x, &norm_x_raw, &norm_x_raw_len, NULL);
+ grn_string_get_normalized(ctx, norm_y, &norm_y_raw, &norm_y_raw_len, NULL);
+ matched = pseudo_prefix_search_match(ctx,
+ norm_x_raw, norm_x_raw_len,
+ norm_y_raw, norm_y_raw_len);
+
+ grn_obj_close(ctx, norm_x);
+ grn_obj_close(ctx, norm_y);
+ grn_obj_unlink(ctx, normalizer);
+
+ return matched;
+}
+
+static grn_bool
+pseudo_prefix_search_record_text(grn_ctx *ctx, grn_obj *record, grn_obj *table,
+ grn_obj *y)
+{
+ grn_obj *normalizer;
+ char x_key[GRN_TABLE_MAX_KEY_SIZE];
+ int x_key_len;
+ grn_bool matched = GRN_FALSE;
+
+ if (table->header.domain != GRN_DB_SHORT_TEXT) {
+ return GRN_FALSE;
}
- /* normalized str doesn't contain '\0'. */
- if (a && b) {
- const char *a_norm, *b_norm;
- grn_string_get_normalized(ctx, a, &a_norm, NULL, NULL);
- grn_string_get_normalized(ctx, b, &b_norm, NULL, NULL);
- matched = (strstr(a_norm, b_norm) != NULL);
+ x_key_len = grn_table_get_key(ctx, table, GRN_RECORD_VALUE(record),
+ x_key, GRN_TABLE_MAX_KEY_SIZE);
+ grn_table_get_info(ctx, table, NULL, NULL, NULL, &normalizer, NULL);
+ if (normalizer) {
+ grn_obj *norm_y;
+ const char *norm_y_raw;
+ unsigned int norm_y_raw_len;
+ norm_y = grn_string_open(ctx, GRN_TEXT_VALUE(y), GRN_TEXT_LEN(y),
+ normalizer, 0);
+ grn_string_get_normalized(ctx, norm_y, &norm_y_raw, &norm_y_raw_len, NULL);
+ matched = pseudo_prefix_search_match(ctx,
+ x_key, x_key_len,
+ norm_y_raw, norm_y_raw_len);
+ grn_obj_close(ctx, norm_y);
+ } else {
+ matched = pseudo_prefix_search_raw_text_raw_text(ctx,
+ x_key,
+ x_key_len,
+ GRN_TEXT_VALUE(y),
+ GRN_TEXT_LEN(y));
}
- if (a) { grn_obj_close(ctx, a); }
- if (b) { grn_obj_close(ctx, b); }
+ return matched;
+}
- if (normalizer) { grn_obj_unlink(ctx, normalizer); }
+static grn_bool
+pseudo_prefix_search_text_text(grn_ctx *ctx, grn_obj *x, grn_obj *y)
+{
+ return pseudo_prefix_search_raw_text_raw_text(ctx,
+ GRN_TEXT_VALUE(x),
+ GRN_TEXT_LEN(x),
+ GRN_TEXT_VALUE(y),
+ GRN_TEXT_LEN(y));
+}
- return matched;
+static grn_bool
+pseudo_prefix_search(grn_ctx *ctx, grn_obj *x, grn_obj *y)
+{
+ switch (x->header.domain) {
+ case GRN_DB_SHORT_TEXT :
+ case GRN_DB_TEXT :
+ case GRN_DB_LONG_TEXT :
+ switch (y->header.domain) {
+ case GRN_DB_SHORT_TEXT :
+ case GRN_DB_TEXT :
+ case GRN_DB_LONG_TEXT :
+ return pseudo_prefix_search_text_text(ctx, x, y);
+ default :
+ break;
+ }
+ return GRN_FALSE;
+ default:
+ {
+ grn_obj *domain;
+ domain = grn_ctx_at(ctx, x->header.domain);
+ if (GRN_OBJ_TABLEP(domain)) {
+ switch (y->header.domain) {
+ case GRN_DB_SHORT_TEXT :
+ case GRN_DB_TEXT :
+ case GRN_DB_LONG_TEXT :
+ return pseudo_prefix_search_record_text(ctx, x, domain, y);
+ default :
+ break;
+ }
+ }
+ }
+ return GRN_FALSE;
+ }
}
inline static void
@@ -2831,10 +2508,10 @@ grn_expr_exec_get_member(grn_ctx *ctx,
GRN_TEXT_INIT(&values, 0);
grn_obj_get_value(ctx, column, record_id, &values);
- grn_obj_reinit(ctx, result, DB_OBJ(column)->range, 0);
i = GRN_UINT32_VALUE(index);
if (values.header.type == GRN_UVECTOR) {
int n_elements;
+ grn_obj_reinit(ctx, result, DB_OBJ(column)->range, 0);
n_elements = GRN_BULK_VSIZE(&values) / sizeof(grn_id);
if (n_elements > i) {
grn_id value;
@@ -2843,11 +2520,14 @@ grn_expr_exec_get_member(grn_ctx *ctx,
}
} else {
if (values.u.v.n_sections > i) {
- grn_section *section = &(values.u.v.sections[i]);
- grn_obj *body = values.u.v.body;
- const char *value;
- value = GRN_BULK_HEAD(body) + section->offset;
- grn_bulk_write(ctx, result, value, section->length);
+ const char *content;
+ unsigned int content_length;
+ grn_id domain;
+
+ content_length = grn_vector_get_element(ctx, &values, i,
+ &content, NULL, &domain);
+ grn_obj_reinit(ctx, result, domain, 0);
+ grn_bulk_write(ctx, result, content, content_length);
}
}
@@ -2861,7 +2541,16 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs)
uint32_t stack_curr = ctx->impl->stack_curr;
GRN_API_ENTER;
if (expr->header.type == GRN_PROC) {
- grn_proc_call(ctx, expr, nargs, expr);
+ grn_proc *proc = (grn_proc *)expr;
+ if (proc->type == GRN_PROC_COMMAND) {
+ grn_command_input *input;
+ input = grn_command_input_open(ctx, expr);
+ grn_command_run(ctx, expr, input);
+ grn_command_input_close(ctx, input);
+ GRN_API_RETURN(NULL);
+ } else {
+ grn_proc_call(ctx, expr, nargs, expr);
+ }
} else {
grn_expr *e = (grn_expr *)expr;
register grn_obj **s_ = ctx->impl->stack, *s0 = NULL, *s1 = NULL, **sp, *vp = e->values;
@@ -3218,12 +2907,7 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs)
case GRN_OP_GET_VALUE :
{
grn_obj *col, *rec;
- grn_obj pat_value;
- GRN_TEXT_INIT(&pat_value, 0);
do {
- uint32_t size;
- const char *value;
- grn_bool is_pat_key_accessor = GRN_FALSE;
if (code->nargs == 1) {
rec = v0;
if (code->value) {
@@ -3245,39 +2929,14 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs)
col = grn_obj_column(ctx, table, GRN_BULK_HEAD(col), GRN_BULK_VSIZE(col));
if (col) { grn_expr_take_obj(ctx, (grn_obj *)expr, col); }
}
- if (col) {
- grn_obj_reinit_for(ctx, res, col);
- if (col->header.type == GRN_ACCESSOR &&
- ((grn_accessor *)col)->action == GRN_ACCESSOR_GET_KEY &&
- ((grn_accessor *)col)->obj->header.type == GRN_TABLE_PAT_KEY) {
- is_pat_key_accessor = GRN_TRUE;
- GRN_BULK_REWIND(&pat_value);
- grn_obj_get_value(ctx, col, GRN_RECORD_VALUE(rec), &pat_value);
- value = GRN_BULK_HEAD(&pat_value);
- size = GRN_BULK_VSIZE(&pat_value);
- } else {
- value = grn_obj_get_value_(ctx, col, GRN_RECORD_VALUE(rec),
- &size);
- }
- } else {
+ if (!col) {
ERR(GRN_INVALID_ARGUMENT, "col resolve failed");
- GRN_OBJ_FIN(ctx, &pat_value);
goto exit;
}
- if (!is_pat_key_accessor && size == GRN_OBJ_GET_VALUE_IMD) {
- GRN_RECORD_SET(ctx, res, (uintptr_t)value);
- } else {
- if (value) {
- if (res->header.type == GRN_VECTOR) {
- grn_vector_decode(ctx, res, value, size);
- } else {
- grn_bulk_write_from(ctx, res, value, 0, size);
- }
- }
- }
+ grn_obj_reinit_for(ctx, res, col);
+ grn_obj_get_value(ctx, col, GRN_RECORD_VALUE(rec), res);
code++;
} while (code < ce && code->op == GRN_OP_GET_VALUE);
- GRN_OBJ_FIN(ctx, &pat_value);
}
break;
case GRN_OP_OBJ_SEARCH :
@@ -3521,35 +3180,38 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs)
break;
case GRN_OP_EQUAL :
{
- int r = GRN_FALSE;
+ grn_bool is_equal;
grn_obj *x, *y;
POP2ALLOC1(x, y, res);
- DO_EQ(x, y, r);
+ is_equal = grn_operator_exec_equal(ctx, x, y);
grn_obj_reinit(ctx, res, GRN_DB_INT32, 0);
- GRN_INT32_SET(ctx, res, r);
+ GRN_INT32_SET(ctx, res, is_equal ? 1 : 0);
}
code++;
break;
case GRN_OP_NOT_EQUAL :
{
- int r = GRN_FALSE;
+ grn_bool is_not_equal;
grn_obj *x, *y;
POP2ALLOC1(x, y, res);
- DO_EQ(x, y, r);
+ is_not_equal = grn_operator_exec_not_equal(ctx, x, y);
grn_obj_reinit(ctx, res, GRN_DB_INT32, 0);
- GRN_INT32_SET(ctx, res, 1 - r);
+ GRN_INT32_SET(ctx, res, is_not_equal ? 1 : 0);
}
code++;
break;
case GRN_OP_PREFIX :
{
grn_obj *x, *y;
- POP2ALLOC1(x, y, res);
- GRN_INT32_SET(ctx, res,
- (GRN_TEXT_LEN(x) >= GRN_TEXT_LEN(y) &&
- !memcmp(GRN_TEXT_VALUE(x), GRN_TEXT_VALUE(y), GRN_TEXT_LEN(y))));
- res->header.type = GRN_BULK;
- res->header.domain = GRN_DB_INT32;
+ grn_bool matched;
+ POP1(y);
+ POP1(x);
+ WITH_SPSAVE({
+ matched = pseudo_prefix_search(ctx, x, y);
+ });
+ ALLOC1(res);
+ grn_obj_reinit(ctx, res, GRN_DB_INT32, 0);
+ GRN_INT32_SET(ctx, res, matched ? 1 : 0);
}
code++;
break;
@@ -3568,11 +3230,11 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs)
break;
case GRN_OP_LESS :
{
- int r;
+ grn_bool r;
grn_obj *x, *y;
POP2ALLOC1(x, y, res);
- DO_COMPARE(x, y, r, <);
- GRN_INT32_SET(ctx, res, r);
+ r = grn_operator_exec_less(ctx, x, y);
+ GRN_INT32_SET(ctx, res, r ? 1 : 0);
res->header.type = GRN_BULK;
res->header.domain = GRN_DB_INT32;
}
@@ -3580,11 +3242,11 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs)
break;
case GRN_OP_GREATER :
{
- int r;
+ grn_bool r;
grn_obj *x, *y;
POP2ALLOC1(x, y, res);
- DO_COMPARE(x, y, r, >);
- GRN_INT32_SET(ctx, res, r);
+ r = grn_operator_exec_greater(ctx, x, y);
+ GRN_INT32_SET(ctx, res, r ? 1 : 0);
res->header.type = GRN_BULK;
res->header.domain = GRN_DB_INT32;
}
@@ -3592,11 +3254,11 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs)
break;
case GRN_OP_LESS_EQUAL :
{
- int r;
+ grn_bool r;
grn_obj *x, *y;
POP2ALLOC1(x, y, res);
- DO_COMPARE(x, y, r, <=);
- GRN_INT32_SET(ctx, res, r);
+ r = grn_operator_exec_less_equal(ctx, x, y);
+ GRN_INT32_SET(ctx, res, r ? 1 : 0);
res->header.type = GRN_BULK;
res->header.domain = GRN_DB_INT32;
}
@@ -3604,11 +3266,11 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs)
break;
case GRN_OP_GREATER_EQUAL :
{
- int r;
+ grn_bool r;
grn_obj *x, *y;
POP2ALLOC1(x, y, res);
- DO_COMPARE(x, y, r, >=);
- GRN_INT32_SET(ctx, res, r);
+ r = grn_operator_exec_greater_equal(ctx, x, y);
+ GRN_INT32_SET(ctx, res, r ? 1 : 0);
res->header.type = GRN_BULK;
res->header.domain = GRN_DB_INT32;
}
@@ -3799,6 +3461,7 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs)
break;
case GRN_OP_PLUS :
ARITHMETIC_BINARY_OPERATION_DISPATCH(
+ "+",
INTEGER_ARITHMETIC_OPERATION_PLUS,
INTEGER_ARITHMETIC_OPERATION_PLUS,
INTEGER_ARITHMETIC_OPERATION_PLUS,
@@ -3847,6 +3510,7 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs)
,);
} else {
ARITHMETIC_BINARY_OPERATION_DISPATCH(
+ "-",
INTEGER_ARITHMETIC_OPERATION_MINUS,
INTEGER_ARITHMETIC_OPERATION_MINUS,
INTEGER_ARITHMETIC_OPERATION_MINUS,
@@ -3865,6 +3529,7 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs)
break;
case GRN_OP_STAR :
ARITHMETIC_BINARY_OPERATION_DISPATCH(
+ "*",
INTEGER_ARITHMETIC_OPERATION_STAR,
INTEGER_ARITHMETIC_OPERATION_STAR,
INTEGER_ARITHMETIC_OPERATION_STAR,
@@ -3914,6 +3579,7 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs)
break;
case GRN_OP_BITWISE_OR :
ARITHMETIC_BINARY_OPERATION_DISPATCH(
+ "|",
INTEGER_ARITHMETIC_OPERATION_BITWISE_OR,
INTEGER_ARITHMETIC_OPERATION_BITWISE_OR,
INTEGER_ARITHMETIC_OPERATION_BITWISE_OR,
@@ -3925,6 +3591,7 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs)
break;
case GRN_OP_BITWISE_XOR :
ARITHMETIC_BINARY_OPERATION_DISPATCH(
+ "^",
INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR,
INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR,
INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR,
@@ -3936,6 +3603,7 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs)
break;
case GRN_OP_BITWISE_AND :
ARITHMETIC_BINARY_OPERATION_DISPATCH(
+ "&",
INTEGER_ARITHMETIC_OPERATION_BITWISE_AND,
INTEGER_ARITHMETIC_OPERATION_BITWISE_AND,
INTEGER_ARITHMETIC_OPERATION_BITWISE_AND,
@@ -3947,6 +3615,7 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs)
break;
case GRN_OP_SHIFTL :
ARITHMETIC_BINARY_OPERATION_DISPATCH(
+ "<<",
INTEGER_ARITHMETIC_OPERATION_SHIFTL,
INTEGER_ARITHMETIC_OPERATION_SHIFTL,
INTEGER_ARITHMETIC_OPERATION_SHIFTL,
@@ -3958,6 +3627,7 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs)
break;
case GRN_OP_SHIFTR :
ARITHMETIC_BINARY_OPERATION_DISPATCH(
+ ">>",
INTEGER_ARITHMETIC_OPERATION_SHIFTR,
INTEGER_ARITHMETIC_OPERATION_SHIFTR,
INTEGER_ARITHMETIC_OPERATION_SHIFTR,
@@ -3969,6 +3639,7 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs)
break;
case GRN_OP_SHIFTRR :
ARITHMETIC_BINARY_OPERATION_DISPATCH(
+ ">>>",
INTEGER8_ARITHMETIC_OPERATION_SHIFTRR,
INTEGER16_ARITHMETIC_OPERATION_SHIFTRR,
INTEGER32_ARITHMETIC_OPERATION_SHIFTRR,
@@ -4010,10 +3681,11 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs)
case GRN_OP_NOT :
{
grn_obj *value;
+ grn_bool value_boolean;
POP1ALLOC1(value, res);
+ GRN_TRUEP(ctx, value, value_boolean);
grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0);
- grn_obj_cast(ctx, value, res, GRN_FALSE);
- GRN_BOOL_SET(ctx, res, !GRN_BOOL_VALUE(res));
+ GRN_BOOL_SET(ctx, res, !value_boolean);
}
code++;
break;
@@ -4066,6 +3738,8 @@ grn_expr_get_value(grn_ctx *ctx, grn_obj *expr, int offset)
#define DEFAULT_TERM_EXTRACT_POLICY 0
#define DEFAULT_WEIGHT_VECTOR_SIZE 4096
+#define GRN_SCAN_INFO_MAX_N_ARGS 128
+
struct _grn_scan_info {
uint32_t start;
uint32_t end;
@@ -4076,9 +3750,10 @@ struct _grn_scan_info {
grn_obj wv;
grn_obj index;
grn_obj *query;
- grn_obj *args[8];
+ grn_obj *args[GRN_SCAN_INFO_MAX_N_ARGS];
int max_interval;
int similarity_threshold;
+ grn_obj *scorer;
};
#define SI_FREE(si) do {\
@@ -4102,6 +3777,7 @@ struct _grn_scan_info {
(si)->max_interval = DEFAULT_MAX_INTERVAL;\
(si)->similarity_threshold = DEFAULT_SIMILARITY_THRESHOLD;\
(si)->start = (st);\
+ (si)->scorer = NULL;\
} while (0)
static scan_info **
@@ -4168,15 +3844,163 @@ put_logical_op(grn_ctx *ctx, scan_info **sis, int *ip, grn_operator op, int star
return sis;
}
+/* TODO: Remove me if nobody doesn't want to reuse the implementation again. */
+#if 0
+static const char *opstrs[] = {
+ "PUSH",
+ "POP",
+ "NOP",
+ "CALL",
+ "INTERN",
+ "GET_REF",
+ "GET_VALUE",
+ "AND",
+ "AND_NOT",
+ "OR",
+ "ASSIGN",
+ "STAR_ASSIGN",
+ "SLASH_ASSIGN",
+ "MOD_ASSIGN",
+ "PLUS_ASSIGN",
+ "MINUS_ASSIGN",
+ "SHIFTL_ASSIGN",
+ "SHIFTR_ASSIGN",
+ "SHIFTRR_ASSIGN",
+ "AND_ASSIGN",
+ "XOR_ASSIGN",
+ "OR_ASSIGN",
+ "JUMP",
+ "CJUMP",
+ "COMMA",
+ "BITWISE_OR",
+ "BITWISE_XOR",
+ "BITWISE_AND",
+ "BITWISE_NOT",
+ "EQUAL",
+ "NOT_EQUAL",
+ "LESS",
+ "GREATER",
+ "LESS_EQUAL",
+ "GREATER_EQUAL",
+ "IN",
+ "MATCH",
+ "NEAR",
+ "NEAR2",
+ "SIMILAR",
+ "TERM_EXTRACT",
+ "SHIFTL",
+ "SHIFTR",
+ "SHIFTRR",
+ "PLUS",
+ "MINUS",
+ "STAR",
+ "SLASH",
+ "MOD",
+ "DELETE",
+ "INCR",
+ "DECR",
+ "INCR_POST",
+ "DECR_POST",
+ "NOT",
+ "ADJUST",
+ "EXACT",
+ "LCP",
+ "PARTIAL",
+ "UNSPLIT",
+ "PREFIX",
+ "SUFFIX",
+ "GEO_DISTANCE1",
+ "GEO_DISTANCE2",
+ "GEO_DISTANCE3",
+ "GEO_DISTANCE4",
+ "GEO_WITHINP5",
+ "GEO_WITHINP6",
+ "GEO_WITHINP8",
+ "OBJ_SEARCH",
+ "EXPR_GET_VAR",
+ "TABLE_CREATE",
+ "TABLE_SELECT",
+ "TABLE_SORT",
+ "TABLE_GROUP",
+ "JSON_PUT"
+};
+
+static void
+put_value(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
+{
+ int len;
+ char namebuf[GRN_TABLE_MAX_KEY_SIZE];
+ if ((len = grn_column_name(ctx, obj, namebuf, GRN_TABLE_MAX_KEY_SIZE))) {
+ GRN_TEXT_PUT(ctx, buf, namebuf, len);
+ } else {
+ grn_text_otoj(ctx, buf, obj, NULL);
+ }
+}
+
+static grn_rc
+grn_expr_inspect_internal(grn_ctx *ctx, grn_obj *buf, grn_obj *expr)
+{
+ uint32_t i, j;
+ grn_expr_var *var;
+ grn_expr_code *code;
+ grn_expr *e = (grn_expr *)expr;
+ grn_hash *vars = grn_expr_get_vars(ctx, expr, &i);
+ GRN_TEXT_PUTS(ctx, buf, "noname");
+ GRN_TEXT_PUTC(ctx, buf, '(');
+ {
+ int i = 0;
+ grn_obj *value;
+ const char *name;
+ uint32_t name_len;
+ GRN_HASH_EACH(ctx, vars, id, &name, &name_len, &value, {
+ if (i++) { GRN_TEXT_PUTC(ctx, buf, ','); }
+ GRN_TEXT_PUT(ctx, buf, name, name_len);
+ GRN_TEXT_PUTC(ctx, buf, ':');
+ put_value(ctx, buf, value);
+ });
+ }
+ GRN_TEXT_PUTC(ctx, buf, ')');
+ GRN_TEXT_PUTC(ctx, buf, '{');
+ for (j = 0, code = e->codes; j < e->codes_curr; j++, code++) {
+ if (j) { GRN_TEXT_PUTC(ctx, buf, ','); }
+ grn_text_itoa(ctx, buf, code->modify);
+ if (code->op == GRN_OP_PUSH) {
+ for (i = 0, var = e->vars; i < e->nvars; i++, var++) {
+ if (&var->value == code->value) {
+ GRN_TEXT_PUTC(ctx, buf, '?');
+ if (var->name_size) {
+ GRN_TEXT_PUT(ctx, buf, var->name, var->name_size);
+ } else {
+ grn_text_itoa(ctx, buf, (int)i);
+ }
+ break;
+ }
+ }
+ if (i == e->nvars) {
+ put_value(ctx, buf, code->value);
+ }
+ } else {
+ if (code->value) {
+ put_value(ctx, buf, code->value);
+ GRN_TEXT_PUTC(ctx, buf, ' ');
+ }
+ GRN_TEXT_PUTS(ctx, buf, opstrs[code->op]);
+ }
+ }
+ GRN_TEXT_PUTC(ctx, buf, '}');
+ return GRN_SUCCESS;
+}
#define EXPRLOG(name,expr) do {\
grn_obj strbuf;\
GRN_TEXT_INIT(&strbuf, 0);\
- grn_expr_inspect(ctx, &strbuf, (expr));\
+ grn_expr_inspect_internal(ctx, &strbuf, (expr));\
GRN_TEXT_PUTC(ctx, &strbuf, '\0');\
GRN_LOG(ctx, GRN_LOG_NOTICE, "%s=(%s)", (name), GRN_TEXT_VALUE(&strbuf));\
GRN_OBJ_FIN(ctx, &strbuf);\
} while (0)
+#endif
+
static void
scan_info_put_index(grn_ctx *ctx, scan_info *si, grn_obj *index, uint32_t sid, int32_t weight)
@@ -4243,6 +4067,7 @@ grn_scan_info_open(grn_ctx *ctx, int start)
si->max_interval = DEFAULT_MAX_INTERVAL;
si->similarity_threshold = DEFAULT_SIMILARITY_THRESHOLD;
si->start = start;
+ si->scorer = NULL;
return si;
}
@@ -4344,10 +4169,22 @@ grn_scan_info_set_similarity_threshold(scan_info *si, int similarity_threshold)
si->similarity_threshold = similarity_threshold;
}
+grn_obj *
+grn_scan_info_get_scorer(scan_info *si)
+{
+ return si->scorer;
+}
+
+void
+grn_scan_info_set_scorer(scan_info *si, grn_obj *scorer)
+{
+ si->scorer = scorer;
+}
+
grn_bool
grn_scan_info_push_arg(scan_info *si, grn_obj *arg)
{
- if (si->nargs >= 8) {
+ if (si->nargs >= GRN_SCAN_INFO_MAX_N_ARGS) {
return GRN_FALSE;
}
@@ -4374,10 +4211,10 @@ scan_info_build_find_index_column_index(grn_ctx *ctx,
uint32_t offset = 0;
grn_obj *index;
int sid = 0;
- int32_t weight = 0;
+ int32_t weight;
index = ec->value;
- if (n_rest_codes > 2 &&
+ if (n_rest_codes >= 2 &&
ec[1].value &&
(ec[1].value->header.domain == GRN_DB_INT32 ||
ec[1].value->header.domain == GRN_DB_UINT32) &&
@@ -4388,15 +4225,159 @@ scan_info_build_find_index_column_index(grn_ctx *ctx,
sid = GRN_UINT32_VALUE(ec[1].value) + 1;
}
offset = 2;
- weight = get_weight(ctx, ec + offset);
- } else {
- weight = get_weight(ctx, ec);
}
+ weight = get_weight(ctx, ec + offset);
scan_info_put_index(ctx, si, index, sid, weight);
return offset;
}
+static uint32_t
+scan_info_build_match_expr_codes(grn_ctx *ctx, scan_info *si,
+ grn_expr *expr, uint32_t i)
+{
+ grn_expr_code *ec;
+ grn_obj *index;
+ int sid;
+
+ ec = &(expr->codes[i]);
+ if (!ec->value) {
+ return i + 1;
+ }
+
+ switch (ec->value->header.type) {
+ case GRN_ACCESSOR :
+ if (grn_column_index(ctx, ec->value, si->op, &index, 1, &sid)) {
+ int32_t weight = get_weight(ctx, ec);
+ si->flags |= SCAN_ACCESSOR;
+ if (((grn_accessor *)ec->value)->next) {
+ scan_info_put_index(ctx, si, ec->value, sid, weight);
+ } else {
+ scan_info_put_index(ctx, si, index, sid, weight);
+ }
+ }
+ break;
+ case GRN_COLUMN_FIX_SIZE :
+ case GRN_COLUMN_VAR_SIZE :
+ if (grn_column_index(ctx, ec->value, si->op, &index, 1, &sid)) {
+ scan_info_put_index(ctx, si, index, sid, get_weight(ctx, ec));
+ }
+ break;
+ case GRN_COLUMN_INDEX :
+ {
+ uint32_t n_rest_codes;
+ uint32_t offset;
+ n_rest_codes = expr->codes_curr - i;
+ offset = scan_info_build_find_index_column_index(ctx, si, ec,
+ n_rest_codes, si->op);
+ i += offset;
+ }
+ break;
+ case GRN_PROC :
+ if (!grn_obj_is_scorer_proc(ctx, ec->value)) {
+ grn_obj inspected;
+ GRN_TEXT_INIT(&inspected, 0);
+ grn_inspect(ctx, &inspected, ec->value);
+ ERR(GRN_INVALID_ARGUMENT,
+ "procedure must be scorer: <%.*s>",
+ (int)GRN_TEXT_LEN(&inspected),
+ GRN_TEXT_VALUE(&inspected));
+ GRN_OBJ_FIN(ctx, &inspected);
+ return expr->codes_curr;
+ }
+ si->scorer = ec->value;
+ i = scan_info_build_match_expr_codes(ctx, si, expr, i + 1);
+ if (expr->codes[i].op != GRN_OP_CALL) {
+ grn_obj inspected;
+ GRN_TEXT_INIT(&inspected, 0);
+ grn_inspect(ctx, &inspected, si->scorer);
+ ERR(GRN_INVALID_ARGUMENT,
+ "scorer must have only one argument: <%.*s>",
+ (int)GRN_TEXT_LEN(&inspected),
+ GRN_TEXT_VALUE(&inspected));
+ GRN_OBJ_FIN(ctx, &inspected);
+ return expr->codes_curr;
+ }
+ break;
+ case GRN_TABLE_NO_KEY :
+ case GRN_TABLE_HASH_KEY :
+ case GRN_TABLE_PAT_KEY :
+ case GRN_TABLE_DAT_KEY :
+ {
+ char name[GRN_TABLE_MAX_KEY_SIZE];
+ int name_size;
+ name_size = grn_obj_name(ctx, ec->value, name, GRN_TABLE_MAX_KEY_SIZE);
+ ERR(GRN_INVALID_ARGUMENT,
+ "invalid match target: <%.*s>",
+ name_size, name);
+ return expr->codes_curr;
+ }
+ break;
+ }
+
+ return i + 1;
+}
+
+static void
+scan_info_build_match_expr(grn_ctx *ctx, scan_info *si, grn_expr *expr)
+{
+ uint32_t i;
+ i = 0;
+ while (i < expr->codes_curr) {
+ i = scan_info_build_match_expr_codes(ctx, si, expr, i);
+ }
+}
+
+static void
+scan_info_build_match(grn_ctx *ctx, scan_info *si)
+{
+ int sid;
+ grn_obj *index, **p = si->args, **pe = si->args + si->nargs;
+ for (; p < pe; p++) {
+ if ((*p)->header.type == GRN_EXPR) {
+ scan_info_build_match_expr(ctx, si, (grn_expr *)(*p));
+ } else if (GRN_DB_OBJP(*p)) {
+ if (grn_column_index(ctx, *p, si->op, &index, 1, &sid)) {
+ scan_info_put_index(ctx, si, index, sid, 1);
+ }
+ } else if (GRN_ACCESSORP(*p)) {
+ si->flags |= SCAN_ACCESSOR;
+ if (grn_column_index(ctx, *p, si->op, &index, 1, &sid)) {
+ if (((grn_accessor *)(*p))->next) {
+ scan_info_put_index(ctx, si, *p, sid, 1);
+ } else {
+ scan_info_put_index(ctx, si, index, sid, 1);
+ }
+ }
+ } else {
+ switch (si->op) {
+ case GRN_OP_NEAR :
+ case GRN_OP_NEAR2 :
+ if (si->nargs == 3 &&
+ *p == si->args[2] &&
+ (*p)->header.domain == GRN_DB_INT32) {
+ si->max_interval = GRN_INT32_VALUE(*p);
+ } else {
+ si->query = *p;
+ }
+ break;
+ case GRN_OP_SIMILAR :
+ if (si->nargs == 3 &&
+ *p == si->args[2] &&
+ (*p)->header.domain == GRN_DB_INT32) {
+ si->similarity_threshold = GRN_INT32_VALUE(*p);
+ } else {
+ si->query = *p;
+ }
+ break;
+ default :
+ si->query = *p;
+ break;
+ }
+ }
+ }
+}
+
static scan_info **
scan_info_build(grn_ctx *ctx, grn_obj *expr, int *n,
grn_operator op, uint32_t size)
@@ -4435,6 +4416,21 @@ scan_info_build(grn_ctx *ctx, grn_obj *expr, int *n,
stat = SCAN_START;
m++;
break;
+ case GRN_OP_BITWISE_OR :
+ case GRN_OP_BITWISE_XOR :
+ case GRN_OP_BITWISE_AND :
+ case GRN_OP_BITWISE_NOT :
+ case GRN_OP_SHIFTL :
+ case GRN_OP_SHIFTR :
+ case GRN_OP_SHIFTRR :
+ case GRN_OP_PLUS :
+ case GRN_OP_MINUS :
+ case GRN_OP_STAR :
+ case GRN_OP_MOD :
+ if (stat < SCAN_COL1 || SCAN_CONST < stat) { return NULL; }
+ stat = SCAN_START;
+ if (m != o + 1) { return NULL; }
+ break;
case GRN_OP_AND :
case GRN_OP_OR :
case GRN_OP_AND_NOT :
@@ -4500,86 +4496,12 @@ scan_info_build(grn_ctx *ctx, grn_obj *expr, int *n,
si->op = c->op;
si->end = c - e->codes;
sis[i++] = si;
- {
- int sid;
- grn_obj *index, **p = si->args, **pe = si->args + si->nargs;
- for (; p < pe; p++) {
- if ((*p)->header.type == GRN_EXPR) {
- uint32_t j;
- grn_expr_code *ec;
- grn_expr *e = (grn_expr *)(*p);
- for (j = e->codes_curr, ec = e->codes; j--; ec++) {
- if (ec->value) {
- switch (ec->value->header.type) {
- case GRN_ACCESSOR :
- if (grn_column_index(ctx, ec->value, c->op, &index, 1, &sid)) {
- int32_t weight = get_weight(ctx, ec);
- si->flags |= SCAN_ACCESSOR;
- if (((grn_accessor *)ec->value)->next) {
- scan_info_put_index(ctx, si, ec->value, sid, weight);
- } else {
- scan_info_put_index(ctx, si, index, sid, weight);
- }
- }
- break;
- case GRN_COLUMN_FIX_SIZE :
- case GRN_COLUMN_VAR_SIZE :
- if (grn_column_index(ctx, ec->value, c->op, &index, 1, &sid)) {
- scan_info_put_index(ctx, si, index, sid, get_weight(ctx, ec));
- }
- break;
- case GRN_COLUMN_INDEX :
- {
- uint32_t offset;
- offset = scan_info_build_find_index_column_index(ctx, si, ec,
- j, c->op);
- j -= offset;
- ec += offset;
- }
- break;
- }
- }
- }
- } else if (GRN_DB_OBJP(*p)) {
- if (grn_column_index(ctx, *p, c->op, &index, 1, &sid)) {
- scan_info_put_index(ctx, si, index, sid, 1);
- }
- } else if (GRN_ACCESSORP(*p)) {
- si->flags |= SCAN_ACCESSOR;
- if (grn_column_index(ctx, *p, c->op, &index, 1, &sid)) {
- if (((grn_accessor *)(*p))->next) {
- scan_info_put_index(ctx, si, *p, sid, 1);
- } else {
- scan_info_put_index(ctx, si, index, sid, 1);
- }
- }
- } else {
- switch (c->op) {
- case GRN_OP_NEAR :
- case GRN_OP_NEAR2 :
- if (si->nargs == 3 &&
- *p == si->args[2] &&
- (*p)->header.domain == GRN_DB_INT32) {
- si->max_interval = GRN_INT32_VALUE(*p);
- } else {
- si->query = *p;
- }
- break;
- case GRN_OP_SIMILAR :
- if (si->nargs == 3 &&
- *p == si->args[2] &&
- (*p)->header.domain == GRN_DB_INT32) {
- si->similarity_threshold = GRN_INT32_VALUE(*p);
- } else {
- si->query = *p;
- }
- break;
- default :
- si->query = *p;
- break;
- }
- }
- }
+ scan_info_build_match(ctx, si);
+ if (ctx->rc != GRN_SUCCESS) {
+ int j;
+ for (j = 0; j < i; j++) { SI_FREE(sis[j]); }
+ GRN_FREE(sis);
+ return NULL;
}
si = NULL;
break;
@@ -4595,7 +4517,7 @@ scan_info_build(grn_ctx *ctx, grn_obj *expr, int *n,
if (c->value == var) {
stat = SCAN_VAR;
} else {
- if (si->nargs < 8) {
+ if (si->nargs < GRN_SCAN_INFO_MAX_N_ARGS) {
si->args[si->nargs++] = c->value;
}
if (stat == SCAN_START) { si->flags |= SCAN_PRE_CONST; }
@@ -4610,7 +4532,7 @@ scan_info_build(grn_ctx *ctx, grn_obj *expr, int *n,
case SCAN_CONST :
case SCAN_VAR :
stat = SCAN_COL1;
- if (si->nargs < 8) {
+ if (si->nargs < GRN_SCAN_INFO_MAX_N_ARGS) {
si->args[si->nargs++] = c->value;
}
break;
@@ -4628,6 +4550,7 @@ scan_info_build(grn_ctx *ctx, grn_obj *expr, int *n,
"invalid expression: can't use column as a value: %.*s",
(int)GRN_TEXT_LEN(&inspected), GRN_TEXT_VALUE(&inspected));
GRN_OBJ_FIN(ctx, &inspected);
+ SI_FREE(si);
for (j = 0; j < i; j++) { SI_FREE(sis[j]); }
GRN_FREE(sis);
return NULL;
@@ -4694,6 +4617,43 @@ scan_info_build(grn_ctx *ctx, grn_obj *expr, int *n,
return sis;
}
+void
+grn_inspect_scan_info_list(grn_ctx *ctx, grn_obj *buffer, scan_info **sis, int n)
+{
+ int i;
+
+ for (i = 0; i < n; i++) {
+ scan_info *si = sis[i];
+
+ grn_text_printf(ctx, buffer, "[%d]\n", i);
+ grn_text_printf(ctx, buffer,
+ " op: <%s>\n",
+ grn_operator_to_string(si->op));
+ grn_text_printf(ctx, buffer,
+ " logical_op: <%s>\n",
+ grn_operator_to_string(si->logical_op));
+
+ GRN_TEXT_PUTS(ctx, buffer, " query: <");
+ grn_inspect(ctx, buffer, si->query);
+ GRN_TEXT_PUTS(ctx, buffer, ">\n");
+
+ grn_text_printf(ctx, buffer,
+ " expr: <%d..%d>\n", si->start, si->end);
+ }
+}
+
+void
+grn_p_scan_info_list(grn_ctx *ctx, scan_info **sis, int n)
+{
+ grn_obj inspected;
+ GRN_TEXT_INIT(&inspected, 0);
+ grn_inspect_scan_info_list(ctx, &inspected, sis, n);
+ printf("%.*s\n",
+ (int)GRN_TEXT_LEN(&inspected),
+ GRN_TEXT_VALUE(&inspected));
+ GRN_OBJ_FIN(ctx, &inspected);
+}
+
inline static int32_t
exec_result_to_score(grn_ctx *ctx, grn_obj *result, grn_obj *score_buffer)
{
@@ -4719,8 +4679,8 @@ exec_result_to_score(grn_ctx *ctx, grn_obj *result, grn_obj *score_buffer)
}
static void
-grn_table_select_(grn_ctx *ctx, grn_obj *table, grn_obj *expr, grn_obj *v,
- grn_obj *res, grn_operator op)
+grn_table_select_sequential(grn_ctx *ctx, grn_obj *table, grn_obj *expr,
+ grn_obj *v, grn_obj *res, grn_operator op)
{
int32_t score;
grn_id id, *idp;
@@ -4737,6 +4697,9 @@ grn_table_select_(grn_ctx *ctx, grn_obj *table, grn_obj *expr, grn_obj *v,
while ((id = grn_table_cursor_next(ctx, tc))) {
GRN_RECORD_SET(ctx, v, id);
r = grn_expr_exec(ctx, expr, 0);
+ if (ctx->rc) {
+ break;
+ }
score = exec_result_to_score(ctx, r, &score_buffer);
if (score > 0) {
grn_rset_recinfo *ri;
@@ -4754,6 +4717,9 @@ grn_table_select_(grn_ctx *ctx, grn_obj *table, grn_obj *expr, grn_obj *v,
grn_hash_cursor_get_key(ctx, hc, (void **) &idp);
GRN_RECORD_SET(ctx, v, *idp);
r = grn_expr_exec(ctx, expr, 0);
+ if (ctx->rc) {
+ break;
+ }
score = exec_result_to_score(ctx, r, &score_buffer);
if (score > 0) {
grn_rset_recinfo *ri;
@@ -4772,6 +4738,9 @@ grn_table_select_(grn_ctx *ctx, grn_obj *table, grn_obj *expr, grn_obj *v,
grn_hash_cursor_get_key(ctx, hc, (void **) &idp);
GRN_RECORD_SET(ctx, v, *idp);
r = grn_expr_exec(ctx, expr, 0);
+ if (ctx->rc) {
+ break;
+ }
score = exec_result_to_score(ctx, r, &score_buffer);
if (score > 0) {
grn_hash_cursor_delete(ctx, hc, NULL);
@@ -4786,6 +4755,9 @@ grn_table_select_(grn_ctx *ctx, grn_obj *table, grn_obj *expr, grn_obj *v,
grn_hash_cursor_get_key(ctx, hc, (void **) &idp);
GRN_RECORD_SET(ctx, v, *idp);
r = grn_expr_exec(ctx, expr, 0);
+ if (ctx->rc) {
+ break;
+ }
score = exec_result_to_score(ctx, r, &score_buffer);
if (score > 0) {
grn_rset_recinfo *ri;
@@ -4854,13 +4826,29 @@ grn_table_select_index_range_column(grn_ctx *ctx, grn_obj *table,
min, min_size, max, max_size,
offset, limit, flags);
if (cursor) {
- grn_id index_id;
- while ((index_id = grn_table_cursor_next(ctx, cursor))) {
- grn_ii_at(ctx, (grn_ii *)index, index_id,
- (grn_hash *)res, logical_op);
+ uint32_t sid;
+ int32_t weight;
+ grn_obj *index_cursor;
+
+ sid = GRN_UINT32_VALUE_AT(&(si->wv), 0);
+ weight = GRN_INT32_VALUE_AT(&(si->wv), 1);
+ index_cursor = grn_index_cursor_open(ctx, cursor, index,
+ GRN_ID_NIL, GRN_ID_MAX, 0);
+ if (index_cursor) {
+ grn_posting *posting;
+ while ((posting = grn_index_cursor_next(ctx, index_cursor, NULL))) {
+ if (sid == 0 || posting->sid == sid) {
+ grn_ii_posting ii_posting;
+ ii_posting.rid = posting->rid;
+ ii_posting.sid = posting->sid;
+ ii_posting.weight = posting->weight * weight;
+ grn_ii_posting_add(ctx, &ii_posting, (grn_hash *)res, logical_op);
+ }
+ }
+ processed = GRN_TRUE;
+ grn_obj_unlink(ctx, index_cursor);
}
grn_table_cursor_close(ctx, cursor);
- processed = GRN_TRUE;
}
grn_ii_resolve_sel_and(ctx, (grn_hash *)res, logical_op);
@@ -4913,11 +4901,21 @@ grn_table_select_index_range_accessor(grn_ctx *ctx, grn_obj *table,
{
int i;
+ grn_obj weight_vector;
+ grn_search_optarg optarg;
+ GRN_INT32_INIT(&weight_vector, GRN_OBJ_VECTOR);
+ memset(&optarg, 0, sizeof(grn_search_optarg));
+ if (si->op == GRN_OP_MATCH) {
+ optarg.mode = GRN_OP_EXACT;
+ } else {
+ optarg.mode = si->op;
+ }
for (i = n_accessors - 1; i > 0; i--) {
grn_rc rc = GRN_SUCCESS;
grn_accessor *accessor;
grn_obj *index;
+ int section;
grn_obj *domain;
grn_obj *target;
grn_obj *next_res;
@@ -4926,12 +4924,28 @@ grn_table_select_index_range_accessor(grn_ctx *ctx, grn_obj *table,
accessor = (grn_accessor *)GRN_PTR_VALUE_AT(accessor_stack, i - 1);
target = accessor->obj;
- if (grn_column_index(ctx, target, GRN_OP_EQUAL, &index, 1, NULL) == 0) {
+ if (grn_column_index(ctx, target, GRN_OP_EQUAL, &index, 1, &section) == 0) {
grn_obj_unlink(ctx, current_res);
current_res = NULL;
break;
}
+ if (section > 0) {
+ int j;
+ int weight_position = section - 1;
+
+ GRN_BULK_REWIND(&weight_vector);
+ GRN_INT32_SET_AT(ctx, &weight_vector, weight_position, 1);
+ optarg.weight_vector = &(GRN_INT32_VALUE(&weight_vector));
+ optarg.vector_size = GRN_BULK_VSIZE(&weight_vector) / sizeof(int32_t);
+ for (j = 0; j < weight_position - 1; j++) {
+ optarg.weight_vector[j] = 0;
+ }
+ } else {
+ optarg.weight_vector = NULL;
+ optarg.vector_size = 1;
+ }
+
{
grn_obj *range;
range = grn_ctx_at(ctx, DB_OBJ(index)->range);
@@ -4954,14 +4968,14 @@ grn_table_select_index_range_accessor(grn_ctx *ctx, grn_obj *table,
if (domain->header.type == GRN_TABLE_NO_KEY) {
rc = grn_ii_sel(ctx, (grn_ii *)index,
(const char *)next_record_id, sizeof(grn_id),
- (grn_hash *)next_res, next_op, NULL);
+ (grn_hash *)next_res, next_op, &optarg);
} else {
char key[GRN_TABLE_MAX_KEY_SIZE];
int key_len;
key_len = grn_table_get_key(ctx, domain, *next_record_id,
key, GRN_TABLE_MAX_KEY_SIZE);
rc = grn_ii_sel(ctx, (grn_ii *)index, key, key_len,
- (grn_hash *)next_res, next_op, NULL);
+ (grn_hash *)next_res, next_op, &optarg);
}
if (rc != GRN_SUCCESS) {
break;
@@ -4986,6 +5000,7 @@ grn_table_select_index_range_accessor(grn_ctx *ctx, grn_obj *table,
break;
}
}
+ GRN_OBJ_FIN(ctx, &weight_vector);
}
return current_res == res;
@@ -5202,6 +5217,7 @@ grn_table_select_index(grn_ctx *ctx, grn_obj *table, scan_info *si,
optarg.vector_size = 1;
optarg.proc = NULL;
optarg.max_size = 0;
+ optarg.scorer = si->scorer;
ctx->flags |= GRN_CTX_TEMPORARY_DISABLE_II_RESOLVE_SEL_AND;
for (; j--; ip++, wp += 2) {
uint32_t sid = (uint32_t) wp[0];
@@ -5250,7 +5266,7 @@ grn_table_select_index(grn_ctx *ctx, grn_obj *table, scan_info *si,
}
break;
case GRN_OP_CALL :
- if (selector_proc_p(si->args[0])) {
+ if (grn_obj_is_selector_proc(ctx, si->args[0])) {
grn_rc rc;
grn_proc *proc = (grn_proc *)(si->args[0]);
rc = proc->selector(ctx, table, index, si->nargs, si->args,
@@ -5276,7 +5292,7 @@ grn_table_select_index(grn_ctx *ctx, grn_obj *table, scan_info *si,
} else {
switch (si->op) {
case GRN_OP_CALL :
- if (selector_proc_p(si->args[0])) {
+ if (grn_obj_is_selector_proc(ctx, si->args[0])) {
grn_rc rc;
grn_proc *proc = (grn_proc *)(si->args[0]);
rc = proc->selector(ctx, table, NULL, si->nargs, si->args,
@@ -5361,11 +5377,13 @@ grn_table_select(grn_ctx *ctx, grn_obj *table, grn_obj *expr,
if (ctx->rc) { break; }
e->codes = codes + si->start;
e->codes_curr = si->end - si->start + 1;
- grn_table_select_(ctx, table, expr, v, res, si->logical_op);
+ grn_table_select_sequential(ctx, table, expr, v,
+ res, si->logical_op);
}
}
GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE,
":", "filter(%d)", grn_table_size(ctx, res));
+ if (ctx->rc) { break; }
}
for (i = 0; i < n; i++) {
scan_info *si = sis[i];
@@ -5377,7 +5395,7 @@ grn_table_select(grn_ctx *ctx, grn_obj *table, grn_obj *expr,
e->codes_curr = codes_curr;
} else {
if (!ctx->rc) {
- grn_table_select_(ctx, table, expr, v, res, op);
+ grn_table_select_sequential(ctx, table, expr, v, res, op);
}
}
}
@@ -5408,7 +5426,7 @@ grn_int32_value_at(grn_obj *obj, int offset)
/* grn_expr_create_from_str */
-#include "snip.h"
+#include "grn_snip.h"
typedef struct {
grn_ctx *ctx;
@@ -5936,8 +5954,8 @@ section_weight_cb(grn_ctx *ctx, grn_hash *r, const void *rid, int sid, void *arg
}
#endif
-#include "ecmascript.h"
-#include "ecmascript.c"
+#include "grn_ecmascript.h"
+#include "grn_ecmascript.c"
static grn_rc
grn_expr_parser_open(grn_ctx *ctx)
@@ -6090,7 +6108,7 @@ get_word_(grn_ctx *ctx, efs_info *q)
GRN_INT32_PUT(ctx, &q->mode_stack, mode);
return GRN_SUCCESS;
- } else if (GRN_TEXT_LEN(&q->buf) > 1 && *end == GRN_QUERY_PREFIX) {
+ } else if (GRN_TEXT_LEN(&q->buf) > 0 && *end == GRN_QUERY_PREFIX) {
q->cur = end + 1;
GRN_INT32_PUT(ctx, &q->mode_stack, GRN_OP_PREFIX);
break;
@@ -6912,7 +6930,7 @@ grn_expr_parse(grn_ctx *ctx, grn_obj *expr,
/*
grn_obj strbuf;
GRN_TEXT_INIT(&strbuf, 0);
- grn_expr_inspect(ctx, &strbuf, expr);
+ grn_expr_inspect_internal(ctx, &strbuf, expr);
GRN_TEXT_PUTC(ctx, &strbuf, '\0');
GRN_LOG(ctx, GRN_LOG_NOTICE, "query=(%s)", GRN_TEXT_VALUE(&strbuf));
GRN_OBJ_FIN(ctx, &strbuf);
@@ -7156,3 +7174,24 @@ grn_expr_syntax_escape_query(grn_ctx *ctx, const char *query, int query_size,
target_characters, GRN_QUERY_ESCAPE,
escaped_query);
}
+
+grn_rc
+grn_expr_dump_plan(grn_ctx *ctx, grn_obj *expr, grn_obj *buffer)
+{
+ int n;
+ scan_info **sis;
+
+ GRN_API_ENTER;
+ sis = scan_info_build(ctx, expr, &n, GRN_OP_OR, 0);
+ if (sis) {
+ int i;
+ grn_inspect_scan_info_list(ctx, buffer, sis, n);
+ for (i = 0; i < n; i++) {
+ SI_FREE(sis[i]);
+ }
+ GRN_FREE(sis);
+ } else {
+ GRN_TEXT_PUTS(ctx, buffer, "sequential search\n");
+ }
+ GRN_API_RETURN(GRN_SUCCESS);
+}
diff --git a/storage/mroonga/vendor/groonga/lib/geo.c b/storage/mroonga/vendor/groonga/lib/geo.c
index 1bb621487a8..21b50c4a1a4 100644
--- a/storage/mroonga/vendor/groonga/lib/geo.c
+++ b/storage/mroonga/vendor/groonga/lib/geo.c
@@ -15,9 +15,9 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "geo.h"
-#include "pat.h"
-#include "util.h"
+#include "grn_geo.h"
+#include "grn_pat.h"
+#include "grn_util.h"
#include <string.h>
#include <stdlib.h>
@@ -1989,13 +1989,13 @@ exit:
return rc;
}
-int
-grn_geo_estimate_in_rectangle(grn_ctx *ctx,
- grn_obj *index,
- grn_obj *top_left_point,
- grn_obj *bottom_right_point)
+uint32_t
+grn_geo_estimate_size_in_rectangle(grn_ctx *ctx,
+ grn_obj *index,
+ grn_obj *top_left_point,
+ grn_obj *bottom_right_point)
{
- int n = 0;
+ uint32_t n = 0;
int total_records;
grn_rc rc;
in_rectangle_data data;
@@ -2004,7 +2004,6 @@ grn_geo_estimate_in_rectangle(grn_ctx *ctx,
GRN_VOID_INIT(&(data.bottom_right_point_buffer));
if (in_rectangle_data_prepare(ctx, index, top_left_point, bottom_right_point,
"grn_geo_estimate_in_rectangle()", &data)) {
- n = -1;
goto exit;
}
@@ -2025,8 +2024,6 @@ grn_geo_estimate_in_rectangle(grn_ctx *ctx,
if (rc == GRN_END_OF_DATA) {
n = total_records;
rc = GRN_SUCCESS;
- } else {
- n = -1;
}
goto exit;
}
@@ -2052,7 +2049,7 @@ grn_geo_estimate_in_rectangle(grn_ctx *ctx,
(double)total_longitude_distance);
}
estimated_n_records = ceil(total_records * select_ratio);
- n = (int)estimated_n_records;
+ n = (uint32_t)estimated_n_records;
}
exit :
@@ -2061,6 +2058,25 @@ exit :
return n;
}
+int
+grn_geo_estimate_in_rectangle(grn_ctx *ctx,
+ grn_obj *index,
+ grn_obj *top_left_point,
+ grn_obj *bottom_right_point)
+{
+ uint32_t size;
+
+ size = grn_geo_estimate_size_in_rectangle(ctx,
+ index,
+ top_left_point,
+ bottom_right_point);
+ if (ctx->rc != GRN_SUCCESS) {
+ return -1;
+ }
+
+ return size;
+}
+
grn_bool
grn_geo_in_circle(grn_ctx *ctx, grn_obj *point, grn_obj *center,
grn_obj *radius_or_point,
diff --git a/storage/mroonga/vendor/groonga/lib/groonga_in.h b/storage/mroonga/vendor/groonga/lib/grn.h
index d7ecff2808b..c33ad7f7ec4 100644
--- a/storage/mroonga/vendor/groonga/lib/groonga_in.h
+++ b/storage/mroonga/vendor/groonga/lib/grn.h
@@ -1,5 +1,5 @@
/* -*- c-basic-offset: 2 -*- */
-/* Copyright(C) 2009-2012 Brazil
+/* Copyright(C) 2009-2014 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -16,55 +16,55 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef GROONGA_IN_H
-#define GROONGA_IN_H
+#ifndef GRN_H
+#define GRN_H
#ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
#endif /* HAVE_CONFIG_H */
#ifdef __cplusplus
-#define __STDC_LIMIT_MACROS
+# define __STDC_LIMIT_MACROS
#endif
#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
+# include <stdlib.h>
#endif /* HAVE_STDLIB_H */
#ifdef HAVE_STDINT_H
-#include <stdint.h>
+# include <stdint.h>
#endif /* HAVE_STDINT_H */
#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
+# include <sys/types.h>
#endif /* HAVE_SYS_TYPES_H */
#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
+# include <sys/param.h>
#endif /* HAVE_SYS_PARAM_H */
#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
+# include <sys/mman.h>
#endif /* HAVE_SYS_MMAN_H */
#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
+# include <sys/time.h>
#endif /* HAVE_SYS_TIME_H */
#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
+# include <sys/resource.h>
#endif /* HAVE_SYS_RESOURCE_H */
#ifdef WIN32
-# define GRN_API __declspec(dllexport)
+# define GRN_API __declspec(dllexport)
#ifdef GROONGA_MAIN
-# define GRN_VAR __declspec(dllimport)
+# define GRN_VAR __declspec(dllimport)
#else
-# define GRN_VAR __declspec(dllexport) extern
+# define GRN_VAR __declspec(dllexport) extern
#endif /* GROONGA_MAIN */
#else
-# define GRN_API
-# define GRN_VAR extern
+# define GRN_API
+# define GRN_VAR extern
#endif
#ifdef HAVE_OPEN
@@ -93,84 +93,93 @@
#ifdef WIN32
-#if defined(__GNUC__) && !defined(WINVER)
+# if defined(__GNUC__) && !defined(WINVER)
# include <w32api.h>
# define WINVER WindowsXP
-#endif /* defined(__GNUC__) && !defined(WINVER) */
-
-#include <basetsd.h>
-#include <process.h>
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <windows.h>
-#include <stddef.h>
-#include <windef.h>
-#include <float.h>
-#include <time.h>
-#include <sys/types.h>
-
-#ifndef __GNUC__
-# define PATH_MAX (MAX_PATH - 1)
-# ifndef __cplusplus
-# define inline _inline
+# endif /* defined(__GNUC__) && !defined(WINVER) */
+
+# include <basetsd.h>
+# include <process.h>
+# include <winsock2.h>
+# include <ws2tcpip.h>
+# include <windows.h>
+# include <stddef.h>
+# include <windef.h>
+# include <float.h>
+# include <time.h>
+# include <sys/types.h>
+
+# ifndef __GNUC__
+# define PATH_MAX (MAX_PATH - 1)
+# ifndef __cplusplus
+# define inline _inline
+# endif
# endif
-#endif
-
-#ifndef __GNUC__
-# define snprintf(str, size, ...) _snprintf(str, size, __VA_ARGS__)
-#endif /* __GNUC__ */
-#if !defined(__GNUC__) && _MSC_VER < 1500
-# define vsnprintf(str, size, format, ap) _vsnprintf(str, size, format, ap)
-#endif /* !defined(__GNUC__) && _MSC_VER < 1500 */
-#define unlink(pathname) _unlink(pathname)
-#define lseek(fd, offset, whence) _lseek(fd, offset, whence)
-#define getpid() _getpid()
-#if !defined(__GNUC__) && _MSC_VER < 1400
-# define fstat(fd, buf) _fstat(fd, buf)
-#endif /* !defined(__GNUC__) && _MSC_VER < 1400 */
-#if !defined(strcasecmp)
-# define strcasecmp(s1, s2) _stricmp(s1, s2)
-#endif /* !defined(strcasecmp) */
-#ifdef __GNUC__
-#include <stdint.h>
-#else
-#define uint8_t UINT8
-#define int8_t INT8
-#define int_least8_t INT8
-#define uint_least8_t UINT8
-#define int16_t INT16
-#define uint16_t UINT16
-#define int32_t INT32
-#define uint32_t UINT32
-#define int64_t INT64
-#define uint64_t UINT64
-#define ssize_t SSIZE_T
-#define pid_t int
-#endif
+# ifndef __GNUC__
+# define snprintf(str, size, ...) _snprintf(str, size, __VA_ARGS__)
+# endif /* __GNUC__ */
+# if !defined(__GNUC__) && _MSC_VER < 1500
+# define vsnprintf(str, size, format, ap) _vsnprintf(str, size, format, ap)
+# endif /* !defined(__GNUC__) && _MSC_VER < 1500 */
+# ifndef HAVE_UNLINK
+# define unlink(pathname) _unlink(pathname)
+# endif
+# define getpid() _getpid()
+# if !defined(__GNUC__) && _MSC_VER < 1400
+# define fstat(fd, buf) _fstat(fd, buf)
+# endif /* !defined(__GNUC__) && _MSC_VER < 1400 */
+# ifdef HAVE__STRICMP
+# ifdef strcasecmp
+# undef strcasecmp
+# endif /* strcasecmp */
+# define strcasecmp(s1, s2) _stricmp(s1, s2)
+# endif /* defined(HAVE__STRICMP) */
+
+# ifdef __GNUC__
+# include <stdint.h>
+# else
+typedef UINT8 uint8_t;
+typedef INT8 int8_t;
+typedef INT8 int_least8_t;
+typedef UINT8 uint_least8_t;
+typedef INT16 int16_t;
+typedef UINT16 uint16_t;
+typedef INT32 int32_t;
+typedef UINT32 uint32_t;
+typedef INT64 int64_t;
+typedef UINT64 uint64_t;
+typedef SSIZE_T ssize_t;
+typedef int pid_t;
+typedef int64_t off64_t;
+# endif
-#undef MSG_WAITALL
-#define MSG_WAITALL 0 /* before Vista, not supported... */
-#define SHUT_RDWR SD_BOTH
+# undef MSG_WAITALL
+# define MSG_WAITALL 0 /* before Vista, not supported... */
+# define SHUT_RDWR SD_BOTH
typedef SOCKET grn_sock;
-#define grn_sock_close(sock) closesocket(sock)
+# define grn_sock_close(sock) closesocket(sock)
-#define CALLBACK __stdcall
+# define CALLBACK __stdcall
-#ifndef __GNUC__
-#include <intrin.h>
-#include <sys/timeb.h>
-#include <errno.h>
-#endif
+# ifndef __GNUC__
+# include <intrin.h>
+# include <sys/timeb.h>
+# include <errno.h>
+# endif
#else /* WIN32 */
-#define GROONGA_API
+# define GROONGA_API
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif /* HAVE_UNISTD_H */
+# ifdef HAVE_UNISTD_H
+# include <unistd.h>
+# endif /* HAVE_UNISTD_H */
+
+# ifndef __off64_t_defined
+typedef off_t off64_t;
+# endif
# ifndef PATH_MAX
# if defined(MAXPATHLEN)
@@ -192,90 +201,100 @@ typedef int grn_sock;
#endif /* WIN32 */
#ifndef INT8_MAX
-#define INT8_MAX (127)
+# define INT8_MAX (127)
#endif /* INT8_MAX */
#ifndef INT8_MIN
-#define INT8_MIN (-128)
+# define INT8_MIN (-128)
#endif /* INT8_MIN */
#ifndef INT16_MAX
-#define INT16_MAX (32767)
+# define INT16_MAX (32767)
#endif /* INT16_MAX */
#ifndef INT16_MIN
-#define INT16_MIN (-32768)
+# define INT16_MIN (-32768)
#endif /* INT16_MIN */
#ifndef INT32_MAX
-#define INT32_MAX (2147483647)
+# define INT32_MAX (2147483647)
#endif /* INT32_MAX */
#ifndef INT32_MIN
-#define INT32_MIN (-2147483648)
+# define INT32_MIN (-2147483648)
#endif /* INT32_MIN */
#ifndef UINT32_MAX
-#define UINT32_MAX (4294967295)
+# define UINT32_MAX (4294967295)
#endif /* UINT32_MAX */
#ifndef INT64_MAX
-#define INT64_MAX (9223372036854775807)
+# define INT64_MAX (9223372036854775807)
#endif /* INT64_MAX */
#ifndef INT64_MIN
-#define INT64_MIN (-9223372036854775808)
+# define INT64_MIN (-9223372036854775808)
#endif /* INT64_MIN */
+
+#ifdef WIN32
+# define grn_lseek(fd, offset, whence) _lseeki64(fd, offset, whence)
+#else /* WIN32 */
+# define grn_lseek(fd, offset, whence) lseek(fd, offset, whence)
+#endif /* WIN32 */
+
+
#ifdef HAVE_PTHREAD_H
-#include <pthread.h>
+# include <pthread.h>
typedef pthread_t grn_thread;
-#define THREAD_CREATE(thread,func,arg) \
+typedef void * grn_thread_func_result;
+# define GRN_THREAD_FUNC_RETURN_VALUE NULL
+# define THREAD_CREATE(thread,func,arg) \
(pthread_create(&(thread), NULL, (func), (arg)))
-#define THREAD_JOIN(thread) (pthread_join(thread, NULL))
+# define THREAD_JOIN(thread) (pthread_join(thread, NULL))
typedef pthread_mutex_t grn_mutex;
-#define MUTEX_INIT(m) pthread_mutex_init(&m, NULL)
-#define MUTEX_LOCK(m) pthread_mutex_lock(&m)
-#define MUTEX_UNLOCK(m) pthread_mutex_unlock(&m)
-#define MUTEX_FIN(m)
-#ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED
-# define MUTEX_INIT_SHARED(m) do {\
+# define MUTEX_INIT(m) pthread_mutex_init(&m, NULL)
+# define MUTEX_LOCK(m) pthread_mutex_lock(&m)
+# define MUTEX_UNLOCK(m) pthread_mutex_unlock(&m)
+# define MUTEX_FIN(m)
+# ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED
+# define MUTEX_INIT_SHARED(m) do {\
pthread_mutexattr_t mutexattr;\
pthread_mutexattr_init(&mutexattr);\
pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);\
pthread_mutex_init(&m, &mutexattr);\
} while (0)
-#else
-# define MUTEX_INIT_SHARED MUTEX_INIT
-#endif /* HAVE_PTHREAD_MUTEXATTR_SETPSHARED */
+# else
+# define MUTEX_INIT_SHARED MUTEX_INIT
+# endif /* HAVE_PTHREAD_MUTEXATTR_SETPSHARED */
typedef pthread_mutex_t grn_critical_section;
-#define CRITICAL_SECTION_INIT(cs) pthread_mutex_init(&(cs), NULL)
-#define CRITICAL_SECTION_ENTER(cs) pthread_mutex_lock(&(cs))
-#define CRITICAL_SECTION_LEAVE(cs) pthread_mutex_unlock(&(cs))
-#define CRITICAL_SECTION_FIN(cs)
+# define CRITICAL_SECTION_INIT(cs) pthread_mutex_init(&(cs), NULL)
+# define CRITICAL_SECTION_ENTER(cs) pthread_mutex_lock(&(cs))
+# define CRITICAL_SECTION_LEAVE(cs) pthread_mutex_unlock(&(cs))
+# define CRITICAL_SECTION_FIN(cs)
typedef pthread_cond_t grn_cond;
-#define COND_INIT(c) pthread_cond_init(&c, NULL)
-#define COND_SIGNAL(c) pthread_cond_signal(&c)
-#define COND_WAIT(c,m) pthread_cond_wait(&c, &m)
-#define COND_BROADCAST(c) pthread_cond_broadcast(&c)
-#ifdef HAVE_PTHREAD_CONDATTR_SETPSHARED
-# define COND_INIT_SHARED(c) do {\
+# define COND_INIT(c) pthread_cond_init(&c, NULL)
+# define COND_SIGNAL(c) pthread_cond_signal(&c)
+# define COND_WAIT(c,m) pthread_cond_wait(&c, &m)
+# define COND_BROADCAST(c) pthread_cond_broadcast(&c)
+# ifdef HAVE_PTHREAD_CONDATTR_SETPSHARED
+# define COND_INIT_SHARED(c) do {\
pthread_condattr_t condattr;\
pthread_condattr_init(&condattr);\
pthread_condattr_setpshared(&condattr, PTHREAD_PROCESS_SHARED);\
pthread_cond_init(&c, &condattr);\
} while (0)
-#else
-# define COND_INIT_SHARED COND_INIT
-#endif /* HAVE_PTHREAD_CONDATTR_SETPSHARE */
+# else
+# define COND_INIT_SHARED COND_INIT
+# endif /* HAVE_PTHREAD_CONDATTR_SETPSHARE */
typedef pthread_key_t grn_thread_key;
-#define THREAD_KEY_CREATE(key, destr) pthread_key_create(key, destr)
-#define THREAD_KEY_DELETE(key) pthread_key_delete(key)
-#define THREAD_SETSPECIFIC(key, value) pthread_setspecific(key, value)
-#define THREAD_GETSPECIFIC(key) pthread_getspecific(key)
+# define THREAD_KEY_CREATE(key, destr) pthread_key_create(key, destr)
+# define THREAD_KEY_DELETE(key) pthread_key_delete(key)
+# define THREAD_SETSPECIFIC(key, value) pthread_setspecific(key, value)
+# define THREAD_GETSPECIFIC(key) pthread_getspecific(key)
#if USE_UYIELD
extern int grn_uyield_count;
@@ -305,35 +324,37 @@ typedef pthread_key_t grn_thread_key;
#if !defined(_POSIX_PRIORITY_SCHEDULING)
#define sched_yield() grn_nanosleep(1000000 * 20)
#endif
-#else /* USE_UYIELD */
+# else /* USE_UYIELD */
#define GRN_TEST_YIELD() do {} while (0)
-#endif /* USE_UYIELD */
+# endif /* USE_UYIELD */
#else /* HAVE_PTHREAD_H */
/* todo */
typedef int grn_thread_key;
-#define THREAD_KEY_CREATE(key,destr)
-#define THREAD_KEY_DELETE(key)
-#define THREAD_SETSPECIFIC(key)
-#define THREAD_GETSPECIFIC(key,value)
+# define THREAD_KEY_CREATE(key,destr)
+# define THREAD_KEY_DELETE(key)
+# define THREAD_SETSPECIFIC(key)
+# define THREAD_GETSPECIFIC(key,value)
-#ifdef WIN32
+# ifdef WIN32
typedef uintptr_t grn_thread;
-#define THREAD_CREATE(thread,func,arg) \
- (((thread)=_beginthreadex(NULL, 0, (func), (arg), 0, NULL)) == NULL)
-#define THREAD_JOIN(thread) \
- (WaitForSingleObject((thread), INFINITE) == WAIT_FAILED)
+typedef unsigned int grn_thread_func_result;
+# define GRN_THREAD_FUNC_RETURN_VALUE 0
+# define THREAD_CREATE(thread,func,arg) \
+ (((thread)=_beginthreadex(NULL, 0, (func), (arg), 0, NULL)) == (grn_thread)0)
+# define THREAD_JOIN(thread) \
+ (WaitForSingleObject((HANDLE)(thread), INFINITE) == WAIT_FAILED)
typedef HANDLE grn_mutex;
-#define MUTEX_INIT(m) ((m) = CreateMutex(0, FALSE, NULL))
-#define MUTEX_LOCK(m) WaitForSingleObject((m), INFINITE)
-#define MUTEX_UNLOCK(m) ReleaseMutex(m)
-#define MUTEX_FIN(m) CloseHandle(m)
+# define MUTEX_INIT(m) ((m) = CreateMutex(0, FALSE, NULL))
+# define MUTEX_LOCK(m) WaitForSingleObject((m), INFINITE)
+# define MUTEX_UNLOCK(m) ReleaseMutex(m)
+# define MUTEX_FIN(m) CloseHandle(m)
typedef CRITICAL_SECTION grn_critical_section;
-#define CRITICAL_SECTION_INIT(cs) InitializeCriticalSection(&(cs))
-#define CRITICAL_SECTION_ENTER(cs) EnterCriticalSection(&(cs))
-#define CRITICAL_SECTION_LEAVE(cs) LeaveCriticalSection(&(cs))
-#define CRITICAL_SECTION_FIN(cs) DeleteCriticalSection(&(cs))
+# define CRITICAL_SECTION_INIT(cs) InitializeCriticalSection(&(cs))
+# define CRITICAL_SECTION_ENTER(cs) EnterCriticalSection(&(cs))
+# define CRITICAL_SECTION_LEAVE(cs) LeaveCriticalSection(&(cs))
+# define CRITICAL_SECTION_FIN(cs) DeleteCriticalSection(&(cs))
typedef struct
{
@@ -344,14 +365,14 @@ typedef struct
size_t was_broadcast_;
} grn_cond;
-#define COND_INIT(c) do { \
+# define COND_INIT(c) do { \
(c).waiters_count_ = 0; \
(c).sema_ = CreateSemaphore(NULL, 0, 0x7fffffff, NULL); \
MUTEX_INIT((c).waiters_count_lock_); \
(c).waiters_done_ = CreateEvent(NULL, FALSE, FALSE, NULL); \
} while (0)
-#define COND_SIGNAL(c) do { \
+# define COND_SIGNAL(c) do { \
MUTEX_LOCK((c).waiters_count_lock_); \
{ \
int have_waiters = (c).waiters_count_ > 0; \
@@ -362,7 +383,7 @@ typedef struct
} \
} while (0)
-#define COND_BROADCAST(c) do { \
+# define COND_BROADCAST(c) do { \
MUTEX_LOCK((c).waiters_count_lock_); \
{ \
int have_waiters = (c).waiters_count_ > 0; \
@@ -382,7 +403,7 @@ typedef struct
} \
} while (0)
-#define COND_WAIT(c,m) do { \
+# define COND_WAIT(c,m) do { \
MUTEX_LOCK((c).waiters_count_lock_); \
(c).waiters_count_++; \
MUTEX_UNLOCK((c).waiters_count_lock_); \
@@ -401,24 +422,24 @@ typedef struct
} \
} while (0)
-#else /* WIN32 */
+# else /* WIN32 */
/* todo */
typedef int grn_cond;
-#define COND_INIT(c) ((c) = 0)
-#define COND_SIGNAL(c)
-#define COND_WAIT(c,m) do { \
+# define COND_INIT(c) ((c) = 0)
+# define COND_SIGNAL(c)
+# define COND_WAIT(c,m) do { \
MUTEX_UNLOCK(m); \
grn_nanosleep(1000000); \
MUTEX_LOCK(m); \
} while (0)
/* todo : must be enhanced! */
-#endif /* WIN32 */
+# endif /* WIN32 */
-#define MUTEX_INIT_SHARED MUTEX_INIT
-#define COND_INIT_SHARED COND_INIT
+# define MUTEX_INIT_SHARED MUTEX_INIT
+# define COND_INIT_SHARED COND_INIT
-#define GRN_TEST_YIELD() do {} while (0)
+# define GRN_TEST_YIELD() do {} while (0)
#endif /* HAVE_PTHREAD_H */
@@ -429,16 +450,12 @@ typedef int grn_cond;
# define GRN_FMT_INT32U PRIu32
# define GRN_FMT_INT64D PRId64
# define GRN_FMT_INT64U PRIu64
-# define GRN_FMT_LLD "lld"
-# define GRN_FMT_LLU "llu"
#else /* HAVE_INTTYPES_H */
# ifdef WIN32
# define GRN_FMT_INT32D "I32d"
# define GRN_FMT_INT32U "I32u"
# define GRN_FMT_INT64D "I64d"
# define GRN_FMT_INT64U "I64u"
-# define GRN_FMT_LLD "I64d"
-# define GRN_FMT_LLU "I64u"
# else /* WIN32 */
# define GRN_FMT_INT32D "d"
# define GRN_FMT_INT32U "u"
@@ -449,11 +466,27 @@ typedef int grn_cond;
# define GRN_FMT_INT64D "lld"
# define GRN_FMT_INT64U "llu"
# endif /* __x86_64__ */
-# define GRN_FMT_LLD "lld"
-# define GRN_FMT_LLU "llu"
# endif /* WIN32 */
#endif /* HAVE_INTTYPES_H */
+#ifdef WIN32
+# define GRN_FMT_LLD "I64d"
+# define GRN_FMT_LLU "I64u"
+# define GRN_FMT_SIZE "Iu"
+# define GRN_FMT_SSIZE "Id"
+# ifdef WIN64
+# define GRN_FMT_SOCKET GRN_FMT_INT64U
+# else /* WIN64 */
+# define GRN_FMT_SOCKET "u"
+# endif /* WIN64 */
+#else /* WIN32 */
+# define GRN_FMT_LLD "lld"
+# define GRN_FMT_LLU "llu"
+# define GRN_FMT_SIZE "zu"
+# define GRN_FMT_SSIZE "zd"
+# define GRN_FMT_SOCKET "d"
+#endif /* WIN32 */
+
#ifdef __GNUC__
# if (defined(__i386__) || defined(__x86_64__)) /* ATOMIC ADD */
/*
@@ -486,6 +519,11 @@ typedef int grn_cond;
/* todo */
# define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--)
# define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r)
+# elif defined(__ATOMIC_SEQ_CST) /* GCC atomic builtins */
+# define GRN_ATOMIC_ADD_EX(p,i,r) \
+ (r = __atomic_fetch_add(p, i, __ATOMIC_SEQ_CST))
+# define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--)
+# define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r)
# else /* ATOMIC ADD */
/* todo */
# define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--)
@@ -505,13 +543,17 @@ typedef int grn_cond;
# elif defined(__ATOMIC_SEQ_CST) /* GCC atomic builtins */
# define GRN_SET_64BIT(p,v) \
__atomic_store_n(p, v, __ATOMIC_SEQ_CST)
+# else
+# warning Need atomic 64bit operation support. The current implementation may break data.
+# define GRN_SET_64BIT(p,v) \
+ (*(p) = (v))
# endif /* ATOMIC 64BIT SET */
# ifdef HAVE_MKOSTEMP
# define GRN_MKOSTEMP(template,flags,mode) mkostemp(template,flags)
# else /* HAVE_MKOSTEMP */
# define GRN_MKOSTEMP(template,flags,mode) \
- (mktemp(template), GRN_OPEN((template),flags,mode))
+ (mktemp(template), GRN_OPEN((template),((flags)|O_RDWR|O_CREAT|O_EXCL),mode))
# endif /* HAVE_MKOSTEMP */
#elif (defined(WIN32) || defined (_WIN64)) /* __GNUC__ */
@@ -544,7 +586,7 @@ typedef int grn_cond;
# define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r)
# define GRN_MKOSTEMP(template,flags,mode) \
- (mktemp(template), GRN_OPEN((template),((flags)|O_BINARY),mode))
+ (mktemp(template), GRN_OPEN((template),((flags)|O_RDWR|O_CREAT),mode))
#else /* __GNUC__ */
@@ -554,9 +596,6 @@ typedef int grn_cond;
# define GRN_ATOMIC_ADD_EX(p,i,r) \
(r = atomic_add_32_nv(p, i) - i)
/* todo */
-# define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--)
-# define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r)
-/* todo */
# define GRN_SET_64BIT(p,v) \
(void)atomic_swap_64(p, v)
# endif /* ATOMIC ADD */
@@ -739,8 +778,6 @@ grn_str_greater(const uint8_t *ap, uint32_t as, const uint8_t *bp, uint32_t bs)
GRN_API void grn_sleep(uint32_t seconds);
GRN_API void grn_nanosleep(uint64_t nanoseconds);
-#ifndef GROONGA_H
-# include "groonga.h"
-#endif /* GROONGA_H */
+#include <groonga.h>
-#endif /* GROONGA_IN_H */
+#endif /* GRN_H */
diff --git a/storage/mroonga/vendor/groonga/lib/com.h b/storage/mroonga/vendor/groonga/lib/grn_com.h
index c0690ccfe76..203ed56c88d 100644
--- a/storage/mroonga/vendor/groonga/lib/com.h
+++ b/storage/mroonga/vendor/groonga/lib/grn_com.h
@@ -18,17 +18,9 @@
#ifndef GRN_COM_H
#define GRN_COM_H
-#ifndef GROONGA_H
-#include "groonga_in.h"
-#endif /* GROONGA_H */
-
-#ifndef GRN_STR_H
-#include "str.h"
-#endif /* GRN_STR_H */
-
-#ifndef GRN_HASH_H
-#include "hash.h"
-#endif /* GRN_HASH_H */
+#include "grn.h"
+#include "grn_str.h"
+#include "grn_hash.h"
#ifdef HAVE_NETDB_H
#include <netdb.h>
diff --git a/storage/mroonga/vendor/groonga/lib/ctx.h b/storage/mroonga/vendor/groonga/lib/grn_ctx.h
index 656abfa94b9..dbf461e668e 100644
--- a/storage/mroonga/vendor/groonga/lib/ctx.h
+++ b/storage/mroonga/vendor/groonga/lib/grn_ctx.h
@@ -1,6 +1,6 @@
/* -*- c-basic-offset: 2 -*- */
/*
- Copyright(C) 2009-2014 Brazil
+ Copyright(C) 2009-2015 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -18,13 +18,10 @@
#ifndef GRN_CTX_H
#define GRN_CTX_H
-#ifndef GROONGA_IN_H
-#include "groonga_in.h"
-#endif /* GROONGA_IN_H */
+#include "grn.h"
+#include "grn_error.h"
-#ifdef HAVE_ERRNO_H
#include <errno.h>
-#endif /* HAVE_ERRNO_H */
#ifdef HAVE_SIGNAL_H
#include <signal.h>
@@ -35,9 +32,7 @@
#include <execinfo.h>
#endif /* HAVE_EXECINFO_H */
-#ifndef GRN_IO_H
-#include "io.h"
-#endif /* GRN_IO_H */
+#include "grn_io.h"
#ifdef __cplusplus
extern "C" {
@@ -157,8 +152,104 @@ GRN_API void grn_ctx_impl_set_current_error_message(grn_ctx *ctx);
} while (0)
#ifdef WIN32
+
+#define SYSTEM_ERROR_MESSAGE_BUFFER_SIZE 1024
#define SERR(str) do {\
grn_rc rc;\
+ const char *system_message;\
+ int error = GetLastError();\
+ system_message = grn_current_error_message();\
+ switch (error) {\
+ case ERROR_FILE_NOT_FOUND :\
+ case ERROR_PATH_NOT_FOUND :\
+ rc = GRN_NO_SUCH_FILE_OR_DIRECTORY;\
+ break;\
+ case ERROR_TOO_MANY_OPEN_FILES :\
+ rc = GRN_TOO_MANY_OPEN_FILES;\
+ break;\
+ case ERROR_ACCESS_DENIED :\
+ rc = GRN_PERMISSION_DENIED;\
+ break;\
+ case ERROR_INVALID_HANDLE :\
+ rc = GRN_INVALID_ARGUMENT;\
+ break;\
+ case ERROR_ARENA_TRASHED :\
+ rc = GRN_ADDRESS_IS_NOT_AVAILABLE;\
+ break;\
+ case ERROR_NOT_ENOUGH_MEMORY :\
+ rc = GRN_NO_MEMORY_AVAILABLE;\
+ break;\
+ case ERROR_INVALID_BLOCK :\
+ case ERROR_BAD_ENVIRONMENT :\
+ rc = GRN_INVALID_ARGUMENT;\
+ break;\
+ case ERROR_BAD_FORMAT :\
+ rc = GRN_INVALID_FORMAT;\
+ break;\
+ case ERROR_INVALID_DATA :\
+ rc = GRN_INVALID_ARGUMENT;\
+ break;\
+ case ERROR_OUTOFMEMORY :\
+ rc = GRN_NO_MEMORY_AVAILABLE;\
+ break;\
+ case ERROR_INVALID_DRIVE :\
+ rc = GRN_INVALID_ARGUMENT;\
+ break;\
+ case ERROR_WRITE_PROTECT :\
+ rc = GRN_PERMISSION_DENIED;\
+ break;\
+ case ERROR_BAD_LENGTH :\
+ rc = GRN_INVALID_ARGUMENT;\
+ break;\
+ case ERROR_SEEK :\
+ rc = GRN_INVALID_SEEK;\
+ break;\
+ case ERROR_NOT_SUPPORTED :\
+ rc = GRN_OPERATION_NOT_SUPPORTED;\
+ break;\
+ case ERROR_NETWORK_ACCESS_DENIED :\
+ rc = GRN_OPERATION_NOT_PERMITTED;\
+ break;\
+ case ERROR_FILE_EXISTS :\
+ rc = GRN_FILE_EXISTS;\
+ break;\
+ case ERROR_INVALID_PARAMETER :\
+ rc = GRN_INVALID_ARGUMENT;\
+ break;\
+ case ERROR_BROKEN_PIPE :\
+ rc = GRN_BROKEN_PIPE;\
+ break;\
+ case ERROR_CALL_NOT_IMPLEMENTED :\
+ rc = GRN_FUNCTION_NOT_IMPLEMENTED;\
+ break;\
+ case ERROR_INVALID_NAME :\
+ rc = GRN_INVALID_ARGUMENT;\
+ break;\
+ case ERROR_BUSY_DRIVE :\
+ case ERROR_PATH_BUSY :\
+ rc = GRN_RESOURCE_BUSY;\
+ break;\
+ case ERROR_BAD_ARGUMENTS :\
+ rc = GRN_INVALID_ARGUMENT;\
+ break;\
+ case ERROR_BUSY :\
+ rc = GRN_RESOURCE_BUSY;\
+ break;\
+ case ERROR_ALREADY_EXISTS :\
+ rc = GRN_FILE_EXISTS;\
+ break;\
+ case ERROR_BAD_EXE_FORMAT :\
+ rc = GRN_EXEC_FORMAT_ERROR;\
+ break;\
+ default:\
+ rc = GRN_UNKNOWN_ERROR;\
+ break;\
+ }\
+ ERR(rc, "syscall error '%s' (%s)[%d]", str, system_message, error);\
+} while (0)
+
+#define SOERR(str) do {\
+ grn_rc rc;\
const char *m;\
int e = WSAGetLastError();\
switch (e) {\
@@ -235,12 +326,16 @@ GRN_API void grn_ctx_impl_set_current_error_message(grn_ctx *ctx);
m = "unknown error";\
break;\
}\
- ERR(rc, "syscall error '%s' (%s)", str, m);\
+ ERR(rc, "socket error '%s' (%s)[%d]", str, m, e);\
} while (0)
+
#else /* WIN32 */
#define SERR(str) do {\
grn_rc rc;\
- switch (errno) {\
+ int errno_keep = errno;\
+ grn_bool show_errno = GRN_FALSE;\
+ const char *system_message = grn_current_error_message();\
+ switch (errno_keep) {\
case ELOOP : rc = GRN_TOO_MANY_SYMBOLIC_LINKS; break;\
case ENAMETOOLONG : rc = GRN_FILENAME_TOO_LONG; break;\
case ENOENT : rc = GRN_NO_SUCH_FILE_OR_DIRECTORY; break;\
@@ -286,10 +381,20 @@ GRN_API void grn_ctx_impl_set_current_error_message(grn_ctx *ctx);
case ETIMEDOUT : rc = GRN_OPERATION_TIMEOUT; break;\
case ECONNREFUSED: rc = GRN_CONNECTION_REFUSED; break;\
case EAGAIN: rc = GRN_OPERATION_WOULD_BLOCK; break;\
- default : rc = GRN_UNKNOWN_ERROR; break;\
+ default :\
+ rc = GRN_UNKNOWN_ERROR;\
+ show_errno = GRN_TRUE;\
+ break;\
+ }\
+ if (show_errno) {\
+ ERR(rc, "syscall error '%s' (%s)[%d]", str, system_message, errno_keep); \
+ } else {\
+ ERR(rc, "syscall error '%s' (%s)", str, system_message);\
}\
- ERR(rc, "syscall error '%s' (%s)", str, strerror(errno));\
} while (0)
+
+#define SOERR(str) SERR(str)
+
#endif /* WIN32 */
#define GERR(rc,...) ERRSET(&grn_gctx, GRN_ERROR, (rc), __VA_ARGS__)
@@ -453,6 +558,9 @@ typedef struct {
uint8_t subrec_offset;
uint8_t record_unit;
uint8_t subrec_unit;
+ union {
+ grn_table_group_flags group;
+ } flags;
// grn_obj_flags flags;
} grn_db_obj;
diff --git a/storage/mroonga/vendor/groonga/lib/ctx_impl.h b/storage/mroonga/vendor/groonga/lib/grn_ctx_impl.h
index 33f1402e6e1..9e0b5677497 100644
--- a/storage/mroonga/vendor/groonga/lib/ctx_impl.h
+++ b/storage/mroonga/vendor/groonga/lib/grn_ctx_impl.h
@@ -1,6 +1,6 @@
/* -*- c-basic-offset: 2 -*- */
/*
- Copyright(C) 2009-2014 Brazil
+ Copyright(C) 2009-2015 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -19,11 +19,11 @@
#define GRN_CTX_IMPL_H
#ifndef GRN_CTX_H
-#include "ctx.h"
+#include "grn_ctx.h"
#endif /* GRN_CTX_H */
#ifndef GRN_COM_H
-#include "com.h"
+#include "grn_com.h"
#endif /* GRN_COM_H */
#ifdef GRN_WITH_MESSAGE_PACK
@@ -88,6 +88,9 @@ struct _grn_alloc_info
int freed;
char alloc_backtrace[4096];
char free_backtrace[4096];
+ char *file;
+ int line;
+ char *func;
grn_alloc_info *next;
};
#endif
@@ -96,8 +99,18 @@ struct _grn_alloc_info
typedef struct _grn_mrb_data grn_mrb_data;
struct _grn_mrb_data {
mrb_state *state;
+ char base_directory[PATH_MAX];
struct RClass *module;
struct RClass *object_class;
+ grn_hash *checked_procs;
+ grn_hash *registered_plugins;
+ struct {
+ grn_obj from;
+ grn_obj to;
+ } buffer;
+ struct {
+ struct RClass *time_class;
+ } builtin;
};
#endif
diff --git a/storage/mroonga/vendor/groonga/lib/ctx_impl_mrb.h b/storage/mroonga/vendor/groonga/lib/grn_ctx_impl_mrb.h
index 6810d1fc097..61cf088b2ae 100644
--- a/storage/mroonga/vendor/groonga/lib/ctx_impl_mrb.h
+++ b/storage/mroonga/vendor/groonga/lib/grn_ctx_impl_mrb.h
@@ -19,8 +19,8 @@
#ifndef GRN_CTX_IMPL_MRB_H
#define GRN_CTX_IMPL_MRB_H
-#include "groonga_in.h"
-#include "ctx.h"
+#include "grn.h"
+#include "grn_ctx.h"
#ifdef __cplusplus
extern "C" {
diff --git a/storage/mroonga/vendor/groonga/lib/dat.h b/storage/mroonga/vendor/groonga/lib/grn_dat.h
index d0c44b7035d..aefd044d0b7 100644
--- a/storage/mroonga/vendor/groonga/lib/dat.h
+++ b/storage/mroonga/vendor/groonga/lib/grn_dat.h
@@ -17,11 +17,11 @@
#ifndef GRN_DAT_H
#define GRN_DAT_H
-#ifndef GROONGA_IN_H
-# include "groonga_in.h"
-#endif /* GROONGA_IN_H */
+#ifndef GRN_H
+# include "grn.h"
+#endif /* GRN_H */
-#include "db.h"
+#include "grn_db.h"
#ifdef __cplusplus
extern "C" {
@@ -58,20 +58,6 @@ struct _grn_dat_cursor {
grn_id curr_rec;
};
-typedef struct _grn_dat_scan_hit grn_dat_scan_hit;
-
-struct _grn_dat_scan_hit {
- grn_id id;
- unsigned int offset;
- unsigned int length;
-};
-
-GRN_API int grn_dat_scan(grn_ctx *ctx, grn_dat *dat, const char *str,
- unsigned int str_size, grn_dat_scan_hit *scan_hits,
- unsigned int max_num_scan_hits, const char **str_rest);
-GRN_API grn_id grn_dat_lcp_search(grn_ctx *ctx, grn_dat *dat,
- const void *key, unsigned int key_size);
-
GRN_API grn_id grn_dat_curr_id(grn_ctx *ctx, grn_dat *dat);
/*
diff --git a/storage/mroonga/vendor/groonga/lib/db.h b/storage/mroonga/vendor/groonga/lib/grn_db.h
index f2f95560b08..0eeab145e0e 100644
--- a/storage/mroonga/vendor/groonga/lib/db.h
+++ b/storage/mroonga/vendor/groonga/lib/grn_db.h
@@ -1,5 +1,5 @@
/* -*- c-basic-offset: 2 -*- */
-/* Copyright(C) 2009-2013 Brazil
+/* Copyright(C) 2009-2015 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -17,19 +17,14 @@
#ifndef GRN_DB_H
#define GRN_DB_H
-#ifndef GROONGA_IN_H
-#include "groonga_in.h"
-#endif /* GROONGA_IN_H */
-
-#ifndef GRN_CTX_H
-#include "ctx.h"
-#endif /* GRN_CTX_H */
-
-#ifndef GRN_STORE_H
-#include "store.h"
-#endif /* GRN_STORE_H */
+#include "grn.h"
+#include "grn_ctx.h"
+#include "grn_store.h"
+#include "grn_rset.h"
+#include <groonga/command.h>
#include <groonga/token_filter.h>
+#include <groonga/scorer.h>
#ifdef __cplusplus
extern "C" {
@@ -40,30 +35,6 @@ extern "C" {
#define GRN_N_RESERVED_TYPES 256
-typedef struct {
- int score;
- int n_subrecs;
- int subrecs[1];
-} grn_rset_recinfo;
-
-typedef struct {
- grn_id rid;
- uint32_t sid;
- uint32_t pos;
-} grn_rset_posinfo;
-
-#define GRN_RSET_UTIL_BIT (0x80000000)
-
-#define GRN_RSET_SCORE_SIZE (sizeof(int))
-
-#define GRN_RSET_N_SUBRECS(ri) ((ri)->n_subrecs & ~GRN_RSET_UTIL_BIT)
-
-#define GRN_RSET_SUBRECS_CMP(a,b,dir) (((a) - (b))*(dir))
-#define GRN_RSET_SUBRECS_NTH(subrecs,size,n) \
- ((int *)((byte *)subrecs + n * (GRN_RSET_SCORE_SIZE + size)))
-#define GRN_RSET_SUBRECS_COPY(subrecs,size,n,src) \
- (memcpy(GRN_RSET_SUBRECS_NTH(subrecs, size, n), src, GRN_RSET_SCORE_SIZE + size))
-
#define GRN_JSON_LOAD_OPEN_BRACKET 0x40000000
#define GRN_JSON_LOAD_OPEN_BRACE 0x40000001
@@ -113,7 +84,7 @@ int grn_table_get_key2(grn_ctx *ctx, grn_obj *table, grn_id id, grn_obj *bulk);
grn_table_cursor *grn_table_cursor_open_by_id(grn_ctx *ctx, grn_obj *table,
grn_id min, grn_id max, int flags);
-void grn_table_add_subrec(grn_obj *table, grn_rset_recinfo *ri, int score,
+void grn_table_add_subrec(grn_obj *table, grn_rset_recinfo *ri, double score,
grn_rset_posinfo *pi, int dir);
grn_obj *grn_obj_graft(grn_ctx *ctx, grn_obj *obj);
@@ -189,10 +160,16 @@ struct _grn_proc {
union {
struct {
+ grn_command_run_func *run;
+ } command;
+ struct {
grn_token_filter_init_func *init;
grn_token_filter_filter_func *filter;
grn_token_filter_fin_func *fin;
} token_filter;
+ struct {
+ grn_scorer_score_func *score;
+ } scorer;
} callbacks;
void *user_data;
@@ -203,11 +180,14 @@ struct _grn_proc {
// grn_obj results[16];
};
+#define GRN_PROC_GET_VARS() (grn_proc_get_vars(ctx, user_data))
#define GRN_PROC_GET_VAR(name) (grn_proc_get_var(ctx, user_data, name, strlen(name)))
#define GRN_PROC_GET_VAR_BY_OFFSET(offset) (grn_proc_get_var_by_offset(ctx, user_data, offset))
#define GRN_PROC_GET_OR_ADD_VAR(name) (grn_proc_get_or_add_var(ctx, user_data, name, strlen(name)))
#define GRN_PROC_ALLOC(domain, flags) (grn_proc_alloc(ctx, user_data, domain, flags))
+grn_obj *grn_proc_get_vars(grn_ctx *ctx, grn_user_data *user_data);
+
grn_obj *grn_proc_get_var(grn_ctx *ctx, grn_user_data *user_data,
const char *name, unsigned int name_size);
@@ -245,6 +225,10 @@ enum {
GRN_ACCESSOR_GET_VALUE,
GRN_ACCESSOR_GET_SCORE,
GRN_ACCESSOR_GET_NSUBRECS,
+ GRN_ACCESSOR_GET_MAX,
+ GRN_ACCESSOR_GET_MIN,
+ GRN_ACCESSOR_GET_SUM,
+ GRN_ACCESSOR_GET_AVG,
GRN_ACCESSOR_GET_COLUMN_VALUE,
GRN_ACCESSOR_GET_DB_OBJ,
GRN_ACCESSOR_LOOKUP,
@@ -329,8 +313,6 @@ struct _grn_expr {
grn_expr_code *code0;
};
-GRN_API grn_rc grn_expr_clear_vars(grn_ctx *ctx, grn_obj *expr);
-
grn_rc grn_expr_parser_close(grn_ctx *ctx);
GRN_API grn_rc grn_obj_cast(grn_ctx *ctx, grn_obj *src, grn_obj *dest, grn_bool addp);
@@ -451,6 +433,7 @@ grn_rc grn_obj_reinit_for(grn_ctx *ctx, grn_obj *obj, grn_obj *domain_obj);
void grn_expr_pack(grn_ctx *ctx, grn_obj *buf, grn_obj *expr);
GRN_API grn_rc grn_expr_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *expr);
+grn_hash *grn_expr_get_vars(grn_ctx *ctx, grn_obj *expr, unsigned int *nvars);
grn_obj *grn_expr_open(grn_ctx *ctx, grn_obj_spec *spec, const uint8_t *p, const uint8_t *pe);
GRN_API void grn_load_(grn_ctx *ctx, grn_content_type input_type,
diff --git a/storage/mroonga/vendor/groonga/lib/ecmascript.c b/storage/mroonga/vendor/groonga/lib/grn_ecmascript.c
index e973f1281a4..80c596bc6b3 100644
--- a/storage/mroonga/vendor/groonga/lib/ecmascript.c
+++ b/storage/mroonga/vendor/groonga/lib/grn_ecmascript.c
@@ -4,10 +4,10 @@
/* First off, code is included that follows the "include" declaration
** in the input grammar file. */
#include <stdio.h>
-#line 4 "ecmascript.lemon"
+#line 4 "grn_ecmascript.lemon"
#define assert GRN_ASSERT
-#line 11 "ecmascript.c"
+#line 11 "grn_ecmascript.c"
/* Next is all token values, in a form suitable for use by makeheaders.
** This section will be null unless lemon is run with the -m switch.
*/
@@ -867,11 +867,11 @@ static void yy_destructor(
*/
case 74: /* suppress_unused_variable_warning */
{
-#line 11 "ecmascript.lemon"
+#line 11 "grn_ecmascript.lemon"
(void)efsi;
-#line 875 "ecmascript.c"
+#line 875 "grn_ecmascript.c"
}
break;
default: break; /* If no destructor action specified: do nothing */
@@ -1295,46 +1295,46 @@ static void yy_reduce(
** break;
*/
case 5: /* query ::= query query_element */
-#line 46 "ecmascript.lemon"
+#line 46 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, grn_int32_value_at(&efsi->op_stack, -1), 2);
}
-#line 1303 "ecmascript.c"
+#line 1303 "grn_ecmascript.c"
break;
case 6: /* query ::= query LOGICAL_AND query_element */
case 35: /* logical_and_expression ::= logical_and_expression LOGICAL_AND bitwise_or_expression */ yytestcase(yyruleno==35);
-#line 49 "ecmascript.lemon"
+#line 49 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_AND, 2);
}
-#line 1311 "ecmascript.c"
+#line 1311 "grn_ecmascript.c"
break;
case 7: /* query ::= query LOGICAL_AND_NOT query_element */
case 36: /* logical_and_expression ::= logical_and_expression LOGICAL_AND_NOT bitwise_or_expression */ yytestcase(yyruleno==36);
-#line 52 "ecmascript.lemon"
+#line 52 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_AND_NOT, 2);
}
-#line 1319 "ecmascript.c"
+#line 1319 "grn_ecmascript.c"
break;
case 8: /* query ::= query LOGICAL_OR query_element */
case 33: /* logical_or_expression ::= logical_or_expression LOGICAL_OR logical_and_expression */ yytestcase(yyruleno==33);
-#line 55 "ecmascript.lemon"
+#line 55 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_OR, 2);
}
-#line 1327 "ecmascript.c"
+#line 1327 "grn_ecmascript.c"
break;
case 11: /* query_element ::= RELATIVE_OP query_element */
-#line 62 "ecmascript.lemon"
+#line 62 "grn_ecmascript.lemon"
{
int mode;
GRN_INT32_POP(&efsi->mode_stack, mode);
}
-#line 1335 "ecmascript.c"
+#line 1335 "grn_ecmascript.c"
break;
case 12: /* query_element ::= IDENTIFIER RELATIVE_OP query_element */
-#line 66 "ecmascript.lemon"
+#line 66 "grn_ecmascript.lemon"
{
int mode;
grn_obj *c;
@@ -1358,310 +1358,310 @@ static void yy_reduce(
break;
}
}
-#line 1362 "ecmascript.c"
+#line 1362 "grn_ecmascript.c"
break;
case 13: /* query_element ::= BRACEL expression BRACER */
case 14: /* query_element ::= EVAL primary_expression */ yytestcase(yyruleno==14);
-#line 89 "ecmascript.lemon"
+#line 89 "grn_ecmascript.lemon"
{
efsi->flags = efsi->default_flags;
}
-#line 1370 "ecmascript.c"
+#line 1370 "grn_ecmascript.c"
break;
case 16: /* expression ::= expression COMMA assignment_expression */
-#line 97 "ecmascript.lemon"
+#line 97 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_COMMA, 2);
}
-#line 1377 "ecmascript.c"
+#line 1377 "grn_ecmascript.c"
break;
case 18: /* assignment_expression ::= lefthand_side_expression ASSIGN assignment_expression */
-#line 102 "ecmascript.lemon"
+#line 102 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_ASSIGN, 2);
}
-#line 1384 "ecmascript.c"
+#line 1384 "grn_ecmascript.c"
break;
case 19: /* assignment_expression ::= lefthand_side_expression STAR_ASSIGN assignment_expression */
-#line 105 "ecmascript.lemon"
+#line 105 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_STAR_ASSIGN, 2);
}
-#line 1391 "ecmascript.c"
+#line 1391 "grn_ecmascript.c"
break;
case 20: /* assignment_expression ::= lefthand_side_expression SLASH_ASSIGN assignment_expression */
-#line 108 "ecmascript.lemon"
+#line 108 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SLASH_ASSIGN, 2);
}
-#line 1398 "ecmascript.c"
+#line 1398 "grn_ecmascript.c"
break;
case 21: /* assignment_expression ::= lefthand_side_expression MOD_ASSIGN assignment_expression */
-#line 111 "ecmascript.lemon"
+#line 111 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MOD_ASSIGN, 2);
}
-#line 1405 "ecmascript.c"
+#line 1405 "grn_ecmascript.c"
break;
case 22: /* assignment_expression ::= lefthand_side_expression PLUS_ASSIGN assignment_expression */
-#line 114 "ecmascript.lemon"
+#line 114 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PLUS_ASSIGN, 2);
}
-#line 1412 "ecmascript.c"
+#line 1412 "grn_ecmascript.c"
break;
case 23: /* assignment_expression ::= lefthand_side_expression MINUS_ASSIGN assignment_expression */
-#line 117 "ecmascript.lemon"
+#line 117 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MINUS_ASSIGN, 2);
}
-#line 1419 "ecmascript.c"
+#line 1419 "grn_ecmascript.c"
break;
case 24: /* assignment_expression ::= lefthand_side_expression SHIFTL_ASSIGN assignment_expression */
-#line 120 "ecmascript.lemon"
+#line 120 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTL_ASSIGN, 2);
}
-#line 1426 "ecmascript.c"
+#line 1426 "grn_ecmascript.c"
break;
case 25: /* assignment_expression ::= lefthand_side_expression SHIFTR_ASSIGN assignment_expression */
-#line 123 "ecmascript.lemon"
+#line 123 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTR_ASSIGN, 2);
}
-#line 1433 "ecmascript.c"
+#line 1433 "grn_ecmascript.c"
break;
case 26: /* assignment_expression ::= lefthand_side_expression SHIFTRR_ASSIGN assignment_expression */
-#line 126 "ecmascript.lemon"
+#line 126 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTRR_ASSIGN, 2);
}
-#line 1440 "ecmascript.c"
+#line 1440 "grn_ecmascript.c"
break;
case 27: /* assignment_expression ::= lefthand_side_expression AND_ASSIGN assignment_expression */
-#line 129 "ecmascript.lemon"
+#line 129 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_AND_ASSIGN, 2);
}
-#line 1447 "ecmascript.c"
+#line 1447 "grn_ecmascript.c"
break;
case 28: /* assignment_expression ::= lefthand_side_expression XOR_ASSIGN assignment_expression */
-#line 132 "ecmascript.lemon"
+#line 132 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_XOR_ASSIGN, 2);
}
-#line 1454 "ecmascript.c"
+#line 1454 "grn_ecmascript.c"
break;
case 29: /* assignment_expression ::= lefthand_side_expression OR_ASSIGN assignment_expression */
-#line 135 "ecmascript.lemon"
+#line 135 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_OR_ASSIGN, 2);
}
-#line 1461 "ecmascript.c"
+#line 1461 "grn_ecmascript.c"
break;
case 31: /* conditional_expression ::= logical_or_expression QUESTION assignment_expression COLON assignment_expression */
-#line 140 "ecmascript.lemon"
+#line 140 "grn_ecmascript.lemon"
{
grn_expr *e = (grn_expr *)efsi->e;
e->codes[yymsp[-3].minor.yy0].nargs = yymsp[-1].minor.yy0 - yymsp[-3].minor.yy0;
e->codes[yymsp[-1].minor.yy0].nargs = e->codes_curr - yymsp[-1].minor.yy0 - 1;
}
-#line 1470 "ecmascript.c"
+#line 1470 "grn_ecmascript.c"
break;
case 38: /* bitwise_or_expression ::= bitwise_or_expression BITWISE_OR bitwise_xor_expression */
-#line 160 "ecmascript.lemon"
+#line 160 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_BITWISE_OR, 2);
}
-#line 1477 "ecmascript.c"
+#line 1477 "grn_ecmascript.c"
break;
case 40: /* bitwise_xor_expression ::= bitwise_xor_expression BITWISE_XOR bitwise_and_expression */
-#line 165 "ecmascript.lemon"
+#line 165 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_BITWISE_XOR, 2);
}
-#line 1484 "ecmascript.c"
+#line 1484 "grn_ecmascript.c"
break;
case 42: /* bitwise_and_expression ::= bitwise_and_expression BITWISE_AND equality_expression */
-#line 170 "ecmascript.lemon"
+#line 170 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_BITWISE_AND, 2);
}
-#line 1491 "ecmascript.c"
+#line 1491 "grn_ecmascript.c"
break;
case 44: /* equality_expression ::= equality_expression EQUAL relational_expression */
-#line 175 "ecmascript.lemon"
+#line 175 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_EQUAL, 2);
}
-#line 1498 "ecmascript.c"
+#line 1498 "grn_ecmascript.c"
break;
case 45: /* equality_expression ::= equality_expression NOT_EQUAL relational_expression */
-#line 178 "ecmascript.lemon"
+#line 178 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_NOT_EQUAL, 2);
}
-#line 1505 "ecmascript.c"
+#line 1505 "grn_ecmascript.c"
break;
case 47: /* relational_expression ::= relational_expression LESS shift_expression */
-#line 183 "ecmascript.lemon"
+#line 183 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_LESS, 2);
}
-#line 1512 "ecmascript.c"
+#line 1512 "grn_ecmascript.c"
break;
case 48: /* relational_expression ::= relational_expression GREATER shift_expression */
-#line 186 "ecmascript.lemon"
+#line 186 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_GREATER, 2);
}
-#line 1519 "ecmascript.c"
+#line 1519 "grn_ecmascript.c"
break;
case 49: /* relational_expression ::= relational_expression LESS_EQUAL shift_expression */
-#line 189 "ecmascript.lemon"
+#line 189 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_LESS_EQUAL, 2);
}
-#line 1526 "ecmascript.c"
+#line 1526 "grn_ecmascript.c"
break;
case 50: /* relational_expression ::= relational_expression GREATER_EQUAL shift_expression */
-#line 192 "ecmascript.lemon"
+#line 192 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_GREATER_EQUAL, 2);
}
-#line 1533 "ecmascript.c"
+#line 1533 "grn_ecmascript.c"
break;
case 51: /* relational_expression ::= relational_expression IN shift_expression */
-#line 195 "ecmascript.lemon"
+#line 195 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_IN, 2);
}
-#line 1540 "ecmascript.c"
+#line 1540 "grn_ecmascript.c"
break;
case 52: /* relational_expression ::= relational_expression MATCH shift_expression */
case 130: /* adjust_match_expression ::= IDENTIFIER MATCH STRING */ yytestcase(yyruleno==130);
-#line 198 "ecmascript.lemon"
+#line 198 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MATCH, 2);
}
-#line 1548 "ecmascript.c"
+#line 1548 "grn_ecmascript.c"
break;
case 53: /* relational_expression ::= relational_expression NEAR shift_expression */
-#line 201 "ecmascript.lemon"
+#line 201 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_NEAR, 2);
}
-#line 1555 "ecmascript.c"
+#line 1555 "grn_ecmascript.c"
break;
case 54: /* relational_expression ::= relational_expression NEAR2 shift_expression */
-#line 204 "ecmascript.lemon"
+#line 204 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_NEAR2, 2);
}
-#line 1562 "ecmascript.c"
+#line 1562 "grn_ecmascript.c"
break;
case 55: /* relational_expression ::= relational_expression SIMILAR shift_expression */
-#line 207 "ecmascript.lemon"
+#line 207 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SIMILAR, 2);
}
-#line 1569 "ecmascript.c"
+#line 1569 "grn_ecmascript.c"
break;
case 56: /* relational_expression ::= relational_expression TERM_EXTRACT shift_expression */
-#line 210 "ecmascript.lemon"
+#line 210 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_TERM_EXTRACT, 2);
}
-#line 1576 "ecmascript.c"
+#line 1576 "grn_ecmascript.c"
break;
case 57: /* relational_expression ::= relational_expression LCP shift_expression */
-#line 213 "ecmascript.lemon"
+#line 213 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_LCP, 2);
}
-#line 1583 "ecmascript.c"
+#line 1583 "grn_ecmascript.c"
break;
case 58: /* relational_expression ::= relational_expression PREFIX shift_expression */
-#line 216 "ecmascript.lemon"
+#line 216 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PREFIX, 2);
}
-#line 1590 "ecmascript.c"
+#line 1590 "grn_ecmascript.c"
break;
case 59: /* relational_expression ::= relational_expression SUFFIX shift_expression */
-#line 219 "ecmascript.lemon"
+#line 219 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SUFFIX, 2);
}
-#line 1597 "ecmascript.c"
+#line 1597 "grn_ecmascript.c"
break;
case 61: /* shift_expression ::= shift_expression SHIFTL additive_expression */
-#line 224 "ecmascript.lemon"
+#line 224 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTL, 2);
}
-#line 1604 "ecmascript.c"
+#line 1604 "grn_ecmascript.c"
break;
case 62: /* shift_expression ::= shift_expression SHIFTR additive_expression */
-#line 227 "ecmascript.lemon"
+#line 227 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTR, 2);
}
-#line 1611 "ecmascript.c"
+#line 1611 "grn_ecmascript.c"
break;
case 63: /* shift_expression ::= shift_expression SHIFTRR additive_expression */
-#line 230 "ecmascript.lemon"
+#line 230 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTRR, 2);
}
-#line 1618 "ecmascript.c"
+#line 1618 "grn_ecmascript.c"
break;
case 65: /* additive_expression ::= additive_expression PLUS multiplicative_expression */
case 127: /* adjuster ::= adjuster PLUS adjust_expression */ yytestcase(yyruleno==127);
-#line 235 "ecmascript.lemon"
+#line 235 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PLUS, 2);
}
-#line 1626 "ecmascript.c"
+#line 1626 "grn_ecmascript.c"
break;
case 66: /* additive_expression ::= additive_expression MINUS multiplicative_expression */
-#line 238 "ecmascript.lemon"
+#line 238 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MINUS, 2);
}
-#line 1633 "ecmascript.c"
+#line 1633 "grn_ecmascript.c"
break;
case 68: /* multiplicative_expression ::= multiplicative_expression STAR unary_expression */
case 129: /* adjust_expression ::= adjust_match_expression STAR DECIMAL */ yytestcase(yyruleno==129);
-#line 243 "ecmascript.lemon"
+#line 243 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_STAR, 2);
}
-#line 1641 "ecmascript.c"
+#line 1641 "grn_ecmascript.c"
break;
case 69: /* multiplicative_expression ::= multiplicative_expression SLASH unary_expression */
-#line 246 "ecmascript.lemon"
+#line 246 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SLASH, 2);
}
-#line 1648 "ecmascript.c"
+#line 1648 "grn_ecmascript.c"
break;
case 70: /* multiplicative_expression ::= multiplicative_expression MOD unary_expression */
-#line 249 "ecmascript.lemon"
+#line 249 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MOD, 2);
}
-#line 1655 "ecmascript.c"
+#line 1655 "grn_ecmascript.c"
break;
case 72: /* unary_expression ::= DELETE unary_expression */
-#line 254 "ecmascript.lemon"
+#line 254 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_DELETE, 1);
}
-#line 1662 "ecmascript.c"
+#line 1662 "grn_ecmascript.c"
break;
case 73: /* unary_expression ::= INCR unary_expression */
-#line 257 "ecmascript.lemon"
+#line 257 "grn_ecmascript.lemon"
{
grn_ctx *ctx = efsi->ctx;
grn_expr *e = (grn_expr *)(efsi->e);
@@ -1679,10 +1679,10 @@ static void yy_reduce(
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_INCR, 1);
}
}
-#line 1683 "ecmascript.c"
+#line 1683 "grn_ecmascript.c"
break;
case 74: /* unary_expression ::= DECR unary_expression */
-#line 274 "ecmascript.lemon"
+#line 274 "grn_ecmascript.lemon"
{
grn_ctx *ctx = efsi->ctx;
grn_expr *e = (grn_expr *)(efsi->e);
@@ -1700,66 +1700,66 @@ static void yy_reduce(
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_DECR, 1);
}
}
-#line 1704 "ecmascript.c"
+#line 1704 "grn_ecmascript.c"
break;
case 75: /* unary_expression ::= PLUS unary_expression */
-#line 291 "ecmascript.lemon"
+#line 291 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PLUS, 1);
}
-#line 1711 "ecmascript.c"
+#line 1711 "grn_ecmascript.c"
break;
case 76: /* unary_expression ::= MINUS unary_expression */
-#line 294 "ecmascript.lemon"
+#line 294 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MINUS, 1);
}
-#line 1718 "ecmascript.c"
+#line 1718 "grn_ecmascript.c"
break;
case 77: /* unary_expression ::= NOT unary_expression */
-#line 297 "ecmascript.lemon"
+#line 297 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_NOT, 1);
}
-#line 1725 "ecmascript.c"
+#line 1725 "grn_ecmascript.c"
break;
case 78: /* unary_expression ::= BITWISE_NOT unary_expression */
-#line 300 "ecmascript.lemon"
+#line 300 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_BITWISE_NOT, 1);
}
-#line 1732 "ecmascript.c"
+#line 1732 "grn_ecmascript.c"
break;
case 79: /* unary_expression ::= ADJUST unary_expression */
-#line 303 "ecmascript.lemon"
+#line 303 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_ADJUST, 1);
}
-#line 1739 "ecmascript.c"
+#line 1739 "grn_ecmascript.c"
break;
case 80: /* unary_expression ::= EXACT unary_expression */
-#line 306 "ecmascript.lemon"
+#line 306 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_EXACT, 1);
}
-#line 1746 "ecmascript.c"
+#line 1746 "grn_ecmascript.c"
break;
case 81: /* unary_expression ::= PARTIAL unary_expression */
-#line 309 "ecmascript.lemon"
+#line 309 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PARTIAL, 1);
}
-#line 1753 "ecmascript.c"
+#line 1753 "grn_ecmascript.c"
break;
case 82: /* unary_expression ::= UNSPLIT unary_expression */
-#line 312 "ecmascript.lemon"
+#line 312 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_UNSPLIT, 1);
}
-#line 1760 "ecmascript.c"
+#line 1760 "grn_ecmascript.c"
break;
case 84: /* postfix_expression ::= lefthand_side_expression INCR */
-#line 317 "ecmascript.lemon"
+#line 317 "grn_ecmascript.lemon"
{
grn_ctx *ctx = efsi->ctx;
grn_expr *e = (grn_expr *)(efsi->e);
@@ -1777,10 +1777,10 @@ static void yy_reduce(
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_INCR_POST, 1);
}
}
-#line 1781 "ecmascript.c"
+#line 1781 "grn_ecmascript.c"
break;
case 85: /* postfix_expression ::= lefthand_side_expression DECR */
-#line 334 "ecmascript.lemon"
+#line 334 "grn_ecmascript.lemon"
{
grn_ctx *ctx = efsi->ctx;
grn_expr *e = (grn_expr *)(efsi->e);
@@ -1798,51 +1798,51 @@ static void yy_reduce(
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_DECR_POST, 1);
}
}
-#line 1802 "ecmascript.c"
+#line 1802 "grn_ecmascript.c"
break;
case 88: /* call_expression ::= member_expression arguments */
-#line 355 "ecmascript.lemon"
+#line 355 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_CALL, yymsp[0].minor.yy0);
}
-#line 1809 "ecmascript.c"
+#line 1809 "grn_ecmascript.c"
break;
case 113: /* member_expression_part ::= BRACKETL expression BRACKETR */
-#line 391 "ecmascript.lemon"
+#line 391 "grn_ecmascript.lemon"
{
grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_GET_MEMBER, 2);
}
-#line 1816 "ecmascript.c"
+#line 1816 "grn_ecmascript.c"
break;
case 115: /* arguments ::= PARENL argument_list PARENR */
-#line 396 "ecmascript.lemon"
+#line 396 "grn_ecmascript.lemon"
{ yygotominor.yy0 = yymsp[-1].minor.yy0; }
-#line 1821 "ecmascript.c"
+#line 1821 "grn_ecmascript.c"
break;
case 116: /* argument_list ::= */
-#line 397 "ecmascript.lemon"
+#line 397 "grn_ecmascript.lemon"
{ yygotominor.yy0 = 0; }
-#line 1826 "ecmascript.c"
+#line 1826 "grn_ecmascript.c"
break;
case 117: /* argument_list ::= assignment_expression */
-#line 398 "ecmascript.lemon"
+#line 398 "grn_ecmascript.lemon"
{ yygotominor.yy0 = 1; }
-#line 1831 "ecmascript.c"
+#line 1831 "grn_ecmascript.c"
break;
case 118: /* argument_list ::= argument_list COMMA assignment_expression */
-#line 399 "ecmascript.lemon"
+#line 399 "grn_ecmascript.lemon"
{ yygotominor.yy0 = yymsp[-2].minor.yy0 + 1; }
-#line 1836 "ecmascript.c"
+#line 1836 "grn_ecmascript.c"
break;
case 119: /* output_columns ::= */
-#line 401 "ecmascript.lemon"
+#line 401 "grn_ecmascript.lemon"
{
yygotominor.yy0 = 0;
}
-#line 1843 "ecmascript.c"
+#line 1843 "grn_ecmascript.c"
break;
case 120: /* output_columns ::= output_column */
-#line 404 "ecmascript.lemon"
+#line 404 "grn_ecmascript.lemon"
{
if (yymsp[0].minor.yy0) {
yygotominor.yy0 = 0;
@@ -1850,10 +1850,10 @@ static void yy_reduce(
yygotominor.yy0 = 1;
}
}
-#line 1854 "ecmascript.c"
+#line 1854 "grn_ecmascript.c"
break;
case 121: /* output_columns ::= output_columns COMMA output_column */
-#line 412 "ecmascript.lemon"
+#line 412 "grn_ecmascript.lemon"
{
if (yymsp[0].minor.yy0) {
yygotominor.yy0 = yymsp[-2].minor.yy0;
@@ -1864,10 +1864,10 @@ static void yy_reduce(
yygotominor.yy0 = 1;
}
}
-#line 1868 "ecmascript.c"
+#line 1868 "grn_ecmascript.c"
break;
case 122: /* output_column ::= STAR */
-#line 423 "ecmascript.lemon"
+#line 423 "grn_ecmascript.lemon"
{
grn_ctx *ctx = efsi->ctx;
grn_obj *expr = efsi->e;
@@ -1905,21 +1905,21 @@ static void yy_reduce(
yygotominor.yy0 = GRN_TRUE;
}
}
-#line 1909 "ecmascript.c"
+#line 1909 "grn_ecmascript.c"
break;
case 123: /* output_column ::= NONEXISTENT_COLUMN */
-#line 460 "ecmascript.lemon"
+#line 460 "grn_ecmascript.lemon"
{
yygotominor.yy0 = GRN_TRUE;
}
-#line 1916 "ecmascript.c"
+#line 1916 "grn_ecmascript.c"
break;
case 124: /* output_column ::= assignment_expression */
-#line 463 "ecmascript.lemon"
+#line 463 "grn_ecmascript.lemon"
{
yygotominor.yy0 = GRN_FALSE;
}
-#line 1923 "ecmascript.c"
+#line 1923 "grn_ecmascript.c"
break;
default:
/* (0) input ::= query */ yytestcase(yyruleno==0);
@@ -2033,7 +2033,7 @@ static void yy_syntax_error(
){
grn_expr_parserARG_FETCH;
#define TOKEN (yyminor.yy0)
-#line 17 "ecmascript.lemon"
+#line 17 "grn_ecmascript.lemon"
{
grn_ctx *ctx = efsi->ctx;
@@ -2055,7 +2055,7 @@ static void yy_syntax_error(
GRN_OBJ_FIN(ctx, &message);
}
}
-#line 2059 "ecmascript.c"
+#line 2059 "grn_ecmascript.c"
grn_expr_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */
}
diff --git a/storage/mroonga/vendor/groonga/lib/ecmascript.h b/storage/mroonga/vendor/groonga/lib/grn_ecmascript.h
index c8e74b2fb8f..c8e74b2fb8f 100644
--- a/storage/mroonga/vendor/groonga/lib/ecmascript.h
+++ b/storage/mroonga/vendor/groonga/lib/grn_ecmascript.h
diff --git a/storage/mroonga/vendor/groonga/lib/ecmascript.lemon b/storage/mroonga/vendor/groonga/lib/grn_ecmascript.lemon
index 322d7ac8264..322d7ac8264 100644
--- a/storage/mroonga/vendor/groonga/lib/ecmascript.lemon
+++ b/storage/mroonga/vendor/groonga/lib/grn_ecmascript.lemon
diff --git a/storage/mroonga/vendor/groonga/lib/error.h b/storage/mroonga/vendor/groonga/lib/grn_error.h
index f425e4644f1..2581f934135 100644
--- a/storage/mroonga/vendor/groonga/lib/error.h
+++ b/storage/mroonga/vendor/groonga/lib/grn_error.h
@@ -18,15 +18,15 @@
#ifndef GRN_ERROR_H
#define GRN_ERROR_H
-#ifndef GROONGA_IN_H
-#include "groonga_in.h"
-#endif /* GROONGA_IN_H */
+#ifndef GRN_H
+#include "grn.h"
+#endif /* GRN_H */
#ifdef __cplusplus
extern "C" {
#endif
-const char *grn_current_error_message(void);
+GRN_API const char *grn_current_error_message(void);
#ifdef __cplusplus
}
diff --git a/storage/mroonga/vendor/groonga/lib/expr.h b/storage/mroonga/vendor/groonga/lib/grn_expr.h
index 67e134e47b9..0a21f72bb92 100644
--- a/storage/mroonga/vendor/groonga/lib/expr.h
+++ b/storage/mroonga/vendor/groonga/lib/grn_expr.h
@@ -1,6 +1,6 @@
/* -*- c-basic-offset: 2 -*- */
/*
- Copyright(C) 2013-2014 Brazil
+ Copyright(C) 2013-2015 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -19,7 +19,7 @@
#ifndef GRN_EXPR_H
#define GRN_EXPR_H
-#include "db.h"
+#include "grn_db.h"
#ifdef __cplusplus
extern "C" {
@@ -59,6 +59,8 @@ int grn_scan_info_get_max_interval(scan_info *si);
void grn_scan_info_set_max_interval(scan_info *si, int max_interval);
int grn_scan_info_get_similarity_threshold(scan_info *si);
void grn_scan_info_set_similarity_threshold(scan_info *si, int similarity_threshold);
+grn_obj *grn_scan_info_get_scorer(scan_info *si);
+void grn_scan_info_set_scorer(scan_info *si, grn_obj *scorer);
grn_bool grn_scan_info_push_arg(scan_info *si, grn_obj *arg);
grn_obj *grn_scan_info_get_arg(grn_ctx *ctx, scan_info *si, int i);
diff --git a/storage/mroonga/vendor/groonga/lib/geo.h b/storage/mroonga/vendor/groonga/lib/grn_geo.h
index b1e04061876..5becbe4f45c 100644
--- a/storage/mroonga/vendor/groonga/lib/geo.h
+++ b/storage/mroonga/vendor/groonga/lib/grn_geo.h
@@ -17,12 +17,12 @@
#ifndef GRN_GEO_H
#define GRN_GEO_H
-#ifndef GROONGA_IN_H
-#include "groonga_in.h"
-#endif /* GROONGA_IN_H */
+#ifndef GRN_H
+#include "grn.h"
+#endif /* GRN_H */
-#include "ii.h"
-#include "db.h"
+#include "grn_ii.h"
+#include "grn_db.h"
#if defined(WIN32) || defined(__sun)
# define _USE_MATH_DEFINES
diff --git a/storage/mroonga/vendor/groonga/lib/hash.h b/storage/mroonga/vendor/groonga/lib/grn_hash.h
index 6f2e68de246..44f5bcba0ed 100644
--- a/storage/mroonga/vendor/groonga/lib/hash.h
+++ b/storage/mroonga/vendor/groonga/lib/grn_hash.h
@@ -17,13 +17,8 @@
#ifndef GRN_HASH_H
#define GRN_HASH_H
-#ifndef GROONGA_IN_H
-#include "groonga_in.h"
-#endif /* GROONGA_IN_H */
-
-#ifndef GRN_CTX_H
-#include "ctx.h"
-#endif /* GRN_CTX_H */
+#include "grn.h"
+#include "grn_ctx.h"
#ifdef __cplusplus
extern "C" {
diff --git a/storage/mroonga/vendor/groonga/lib/ii.h b/storage/mroonga/vendor/groonga/lib/grn_ii.h
index 877200fff7c..0d44079a38c 100644
--- a/storage/mroonga/vendor/groonga/lib/ii.h
+++ b/storage/mroonga/vendor/groonga/lib/grn_ii.h
@@ -19,21 +19,10 @@
/* "ii" is for inverted index */
-#ifndef GROONGA_IN_H
-#include "groonga_in.h"
-#endif /* GROONGA_IN_H */
-
-#ifndef GRN_HASH_H
-#include "hash.h"
-#endif /* GRN_HASH_H */
-
-#ifndef GRN_IO_H
-#include "io.h"
-#endif /* GRN_IO_H */
-
-#ifndef GRN_STORE_H
-#include "store.h"
-#endif /* GRN_STORE_H */
+#include "grn.h"
+#include "grn_hash.h"
+#include "grn_io.h"
+#include "grn_store.h"
#ifdef __cplusplus
extern "C" {
@@ -113,8 +102,6 @@ grn_rc grn_ii_updspec_close(grn_ctx *ctx, grn_ii_updspec *u);
grn_rc grn_ii_updspec_add(grn_ctx *ctx, grn_ii_updspec *u, int pos, int32_t weight);
int grn_ii_updspec_cmp(grn_ii_updspec *a, grn_ii_updspec *b);
-uint32_t grn_ii_estimate_size(grn_ctx *ctx, grn_ii *ii, uint32_t key);
-
void grn_ii_expire(grn_ctx *ctx, grn_ii *ii);
typedef struct {
@@ -141,7 +128,6 @@ GRN_API grn_rc grn_ii_cursor_close(grn_ctx *ctx, grn_ii_cursor *c);
uint32_t grn_ii_max_section(grn_ii *ii);
-int grn_ii_check(grn_ii *ii);
const char *grn_ii_path(grn_ii *ii);
grn_obj *grn_ii_lexicon(grn_ii *ii);
@@ -165,6 +151,7 @@ struct _grn_select_optarg {
int (*func)(grn_ctx *, grn_hash *, const void *, int, void *);
void *func_arg;
int max_size;
+ grn_obj *scorer;
};
GRN_API grn_rc grn_ii_column_update(grn_ctx *ctx, grn_ii *ii, grn_id id,
@@ -184,7 +171,7 @@ void grn_ii_resolve_sel_and(grn_ctx *ctx, grn_hash *s, grn_operator op);
grn_rc grn_ii_at(grn_ctx *ctx, grn_ii *ii, grn_id id, grn_hash *s, grn_operator op);
-void grn_ii_inspect_elements(grn_ctx *ctx, grn_ii *ii, grn_obj *buf);
+void grn_ii_inspect_values(grn_ctx *ctx, grn_ii *ii, grn_obj *buf);
void grn_ii_cursor_inspect(grn_ctx *ctx, grn_ii_cursor *c, grn_obj *buf);
grn_rc grn_ii_build(grn_ctx *ctx, grn_ii *ii, uint64_t sparsity);
diff --git a/storage/mroonga/vendor/groonga/lib/io.h b/storage/mroonga/vendor/groonga/lib/grn_io.h
index 04c75919c5f..00a1c3a0936 100644
--- a/storage/mroonga/vendor/groonga/lib/io.h
+++ b/storage/mroonga/vendor/groonga/lib/grn_io.h
@@ -1,5 +1,5 @@
/* -*- c-basic-offset: 2 -*- */
-/* Copyright(C) 2009-2012 Brazil
+/* Copyright(C) 2009-2015 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -17,30 +17,17 @@
#ifndef GRN_IO_H
#define GRN_IO_H
-#ifndef GROONGA_IN_H
-#include "groonga_in.h"
-#endif /* GROONGA_IN_H */
-
-#ifndef GRN_ERROR_H
-#include "error.h"
-#endif /* GRN_ERROR_H */
+#include "grn.h"
+#include "grn_error.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef WIN32
-#ifdef WIN32_FMO_EACH
-#define GRN_IO_FILE_SIZE 1073741824UL
-#else /* FMO_EACH */
-#define GRN_IO_FILE_SIZE 134217728L
-#endif /* FMO_EACH */
-#define GRN_IO_COPY grn_io_rdonly
-#define GRN_IO_UPDATE grn_io_wronly
+# define GRN_IO_FILE_CREATE_MODE (GENERIC_READ | GENERIC_WRITE)
#else /* WIN32 */
-#define GRN_IO_FILE_SIZE 1073741824UL
-#define GRN_IO_COPY grn_io_rdwr
-#define GRN_IO_UPDATE grn_io_rdwr
+# define GRN_IO_FILE_CREATE_MODE 0644
#endif /* WIN32 */
typedef enum {
@@ -72,19 +59,19 @@ typedef struct {
void *addr;
uint32_t diff;
int32_t cached;
-#if defined(WIN32) && defined(WIN32_FMO_EACH)
+#ifdef WIN32
HANDLE fmo;
-#endif /* defined(WIN32) && defined(WIN32_FMO_EACH) */
- void *value;
+#endif /* WIN32 */
+ void *uncompressed_value;
} grn_io_win;
typedef struct {
void *map;
uint32_t nref;
uint32_t count;
-#if defined(WIN32) && defined(WIN32_FMO_EACH)
+#ifdef WIN32
HANDLE fmo;
-#endif /* defined(WIN32) && defined(WIN32_FMO_EACH) */
+#endif /* WIN32 */
} grn_io_mapinfo;
typedef struct _grn_io_array_info grn_io_array_info;
@@ -135,13 +122,8 @@ GRN_API void *grn_io_header(grn_io *io);
void *grn_io_win_map(grn_io *io, grn_ctx *ctx, grn_io_win *iw, uint32_t segment,
uint32_t offset, uint32_t size, grn_io_rw_mode mode);
-grn_rc grn_io_win_mapv(grn_io_win **list, grn_ctx *ctx, int nent);
grn_rc grn_io_win_unmap(grn_io_win *iw);
-void *grn_io_win_map2(grn_io *io, grn_ctx *ctx, grn_io_win *iw, uint32_t segment,
- uint32_t offset, uint32_t size, grn_io_rw_mode mode);
-grn_rc grn_io_win_unmap2(grn_io_win *iw);
-
typedef struct _grn_io_ja_einfo grn_io_ja_einfo;
typedef struct _grn_io_ja_ehead grn_io_ja_ehead;
diff --git a/storage/mroonga/vendor/groonga/lib/mrb.h b/storage/mroonga/vendor/groonga/lib/grn_mrb.h
index fe51e5e7670..7fae820d342 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb.h
+++ b/storage/mroonga/vendor/groonga/lib/grn_mrb.h
@@ -1,6 +1,6 @@
/* -*- c-basic-offset: 2 -*- */
/*
- Copyright(C) 2013 Brazil
+ Copyright(C) 2013-2014 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -19,8 +19,8 @@
#ifndef GRN_MRB_H
#define GRN_MRB_H
-#include "groonga_in.h"
-#include "ctx.h"
+#include "grn.h"
+#include "grn_ctx.h"
#ifdef GRN_WITH_MRUBY
# include <mruby.h>
@@ -34,6 +34,7 @@ extern "C" {
GRN_API mrb_value grn_mrb_eval(grn_ctx *ctx, const char *script, int script_length);
GRN_API mrb_value grn_mrb_load(grn_ctx *ctx, const char *path);
GRN_API grn_rc grn_mrb_to_grn(grn_ctx *ctx, mrb_value mrb_object, grn_obj *grn_object);
+GRN_API const char *grn_mrb_get_system_ruby_scripts_dir(grn_ctx *ctx);
#endif
#ifdef __cplusplus
diff --git a/storage/mroonga/vendor/groonga/lib/normalizer_in.h b/storage/mroonga/vendor/groonga/lib/grn_normalizer.h
index 201c789f626..8c7bfddf810 100644
--- a/storage/mroonga/vendor/groonga/lib/normalizer_in.h
+++ b/storage/mroonga/vendor/groonga/lib/grn_normalizer.h
@@ -15,20 +15,12 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef GRN_NORMALIZER_IN_H
-#define GRN_NORMALIZER_IN_H
+#ifndef GRN_NORMALIZER_H
+#define GRN_NORMALIZER_H
-#ifndef GROONGA_IN_H
-#include "groonga_in.h"
-#endif /* GROONGA_IN_H */
-
-#ifndef GRN_CTX_H
-#include "ctx.h"
-#endif /* GRN_CTX_H */
-
-#ifndef GRN_DB_H
-#include "db.h"
-#endif /* GRN_DB_H */
+#include "grn.h"
+#include "grn_ctx.h"
+#include "grn_db.h"
#ifdef __cplusplus
extern "C" {
@@ -49,4 +41,4 @@ grn_rc grn_db_init_builtin_normalizers(grn_ctx *ctx);
}
#endif
-#endif /* GRN_NORMALIZER_IN_H */
+#endif /* GRN_NORMALIZER_H */
diff --git a/storage/mroonga/vendor/groonga/lib/output.h b/storage/mroonga/vendor/groonga/lib/grn_output.h
index 7c8a3f7a769..63752e90bd9 100644
--- a/storage/mroonga/vendor/groonga/lib/output.h
+++ b/storage/mroonga/vendor/groonga/lib/grn_output.h
@@ -17,21 +17,10 @@
#ifndef GRN_OUTPUT_H
#define GRN_OUTPUT_H
-#ifndef GROONGA_IN_H
-#include "groonga_in.h"
-#endif /* GROONGA_IN_H */
-
-#ifndef GRN_CTX_H
-#include "ctx.h"
-#endif /* GRN_CTX_H */
-
-#ifndef GRN_STORE_H
-#include "store.h"
-#endif /* GRN_STORE_H */
-
-#ifndef GRN_CTX_IMPL_H
-#include "ctx_impl.h"
-#endif /* GRN_CTX_IMPL_H */
+#include "grn.h"
+#include "grn_ctx.h"
+#include "grn_store.h"
+#include "grn_ctx_impl.h"
#ifdef __cplusplus
extern "C" {
@@ -59,6 +48,21 @@ GRN_API void grn_output_bool(grn_ctx *ctx, grn_obj *outbuf,
grn_content_type output_type,
grn_bool value);
+GRN_API void grn_output_table_columns(grn_ctx *ctx,
+ grn_obj *outbuf,
+ grn_content_type output_type,
+ grn_obj *table,
+ grn_obj_format *format);
+GRN_API void grn_output_table_records(grn_ctx *ctx,
+ grn_obj *outbuf,
+ grn_content_type output_type,
+ grn_obj *table,
+ grn_obj_format *format);
+
+grn_rc grn_output_format_set_columns(grn_ctx *ctx, grn_obj_format *format,
+ grn_obj *table,
+ const char *columns, int columns_len);
+
#define GRN_OUTPUT_ARRAY_OPEN(name,nelements) \
(grn_ctx_output_array_open(ctx, name, nelements))
#define GRN_OUTPUT_ARRAY_CLOSE() \
@@ -81,6 +85,10 @@ GRN_API void grn_output_bool(grn_ctx *ctx, grn_obj *outbuf,
(grn_ctx_output_bool(ctx, value))
#define GRN_OUTPUT_OBJ(obj,format)\
(grn_ctx_output_obj(ctx, obj, format))
+#define GRN_OUTPUT_TABLE_COLUMNS(table,format)\
+ (grn_ctx_output_table_columns(ctx, table, format))
+#define GRN_OUTPUT_TABLE_RECORDS(table,format)\
+ (grn_ctx_output_table_records(ctx, table, format))
#ifdef __cplusplus
}
diff --git a/storage/mroonga/vendor/groonga/lib/pat.h b/storage/mroonga/vendor/groonga/lib/grn_pat.h
index d2d10322c7c..763c6848a63 100644
--- a/storage/mroonga/vendor/groonga/lib/pat.h
+++ b/storage/mroonga/vendor/groonga/lib/grn_pat.h
@@ -17,12 +17,9 @@
#ifndef GRN_PAT_H
#define GRN_PAT_H
-#ifndef GROONGA_IN_H
-#include "groonga_in.h"
-#endif /* GROONGA_IN_H */
-
-#include "db.h"
-#include "hash.h"
+#include "grn.h"
+#include "grn_db.h"
+#include "grn_hash.h"
#ifdef __cplusplus
extern "C" {
diff --git a/storage/mroonga/vendor/groonga/lib/plugin_in.h b/storage/mroonga/vendor/groonga/lib/grn_plugin.h
index 6f983089dc9..121c3143faf 100644
--- a/storage/mroonga/vendor/groonga/lib/plugin_in.h
+++ b/storage/mroonga/vendor/groonga/lib/grn_plugin.h
@@ -14,20 +14,12 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef GRN_PLUGIN_IN_H
-#define GRN_PLUGIN_IN_H
+#ifndef GRN_PLUGIN_H
+#define GRN_PLUGIN_H
-#ifndef GROONGA_IN_H
-#include "groonga_in.h"
-#endif /* GROONGA_IN_H */
-
-#ifndef GRN_CTX_H
-#include "ctx.h"
-#endif /* GRN_CTX_H */
-
-#ifndef GRN_STORE_H
-#include "store.h"
-#endif /* GRN_STORE_H */
+#include "grn.h"
+#include "grn_ctx.h"
+#include "grn_store.h"
#ifdef __cplusplus
extern "C" {
@@ -60,9 +52,10 @@ grn_rc grn_plugin_close(grn_ctx *ctx, grn_id id);
grn_id grn_plugin_reference(grn_ctx *ctx, const char *filename);
const char *grn_plugin_path(grn_ctx *ctx, grn_id id);
char *grn_plugin_find_path(grn_ctx *ctx, const char *name);
+void grn_plugin_ensure_registered(grn_ctx *ctx, grn_obj *proc);
#ifdef __cplusplus
}
#endif
-#endif /* GRN_PLUGIN_IN_H */
+#endif /* GRN_PLUGIN_H */
diff --git a/storage/mroonga/vendor/groonga/lib/proc.h b/storage/mroonga/vendor/groonga/lib/grn_proc.h
index 1f7f81d5d97..fb01698ea69 100644
--- a/storage/mroonga/vendor/groonga/lib/proc.h
+++ b/storage/mroonga/vendor/groonga/lib/grn_proc.h
@@ -17,9 +17,7 @@
#ifndef GRN_PROC_H
#define GRN_PROC_H
-#ifndef GROONGA_IN_H
-#include "groonga_in.h"
-#endif /* GROONGA_IN_H */
+#include "grn.h"
#ifdef __cplusplus
extern "C" {
diff --git a/storage/mroonga/vendor/groonga/lib/grn_request_canceler.h b/storage/mroonga/vendor/groonga/lib/grn_request_canceler.h
new file mode 100644
index 00000000000..4c77ea5246e
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/grn_request_canceler.h
@@ -0,0 +1,31 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef GRN_REQUEST_CANCELER_H
+#define GRN_REQUEST_CANCELER_H
+
+#include "grn.h"
+
+grn_bool grn_request_canceler_init(void);
+void grn_request_canceler_fin(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRN_REQUEST_CANCELER_H */
diff --git a/storage/mroonga/vendor/groonga/lib/grn_rset.h b/storage/mroonga/vendor/groonga/lib/grn_rset.h
new file mode 100644
index 00000000000..4fa0d08355a
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/grn_rset.h
@@ -0,0 +1,115 @@
+/* -*- c-basic-offset: 2 -*- */
+/* Copyright(C) 2009-2015 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#ifndef GRN_RSET_H
+#define GRN_RSET_H
+
+#include "grn.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ double score;
+ int n_subrecs;
+ int subrecs[1];
+} grn_rset_recinfo;
+
+typedef struct {
+ grn_id rid;
+ uint32_t sid;
+ uint32_t pos;
+} grn_rset_posinfo;
+
+#define GRN_RSET_UTIL_BIT (0x80000000)
+
+#define GRN_RSET_N_SUBRECS_SIZE (sizeof(int))
+#define GRN_RSET_MAX_SIZE (sizeof(int64_t))
+#define GRN_RSET_MIN_SIZE (sizeof(int64_t))
+#define GRN_RSET_SUM_SIZE (sizeof(int64_t))
+#define GRN_RSET_AVG_SIZE (sizeof(double))
+
+#define GRN_RSET_SCORE_SIZE (sizeof(double))
+
+#define GRN_RSET_N_SUBRECS(ri) ((ri)->n_subrecs & ~GRN_RSET_UTIL_BIT)
+
+#define GRN_RSET_SUBREC_SIZE(subrec_size) \
+ (GRN_RSET_SCORE_SIZE + subrec_size)
+#define GRN_RSET_SUBRECS_CMP(a,b,dir) (((a) - (b))*(dir))
+#define GRN_RSET_SUBRECS_NTH(subrecs,size,n) \
+ ((double *)((byte *)subrecs + n * GRN_RSET_SUBREC_SIZE(size)))
+#define GRN_RSET_SUBRECS_COPY(subrecs,size,n,src) \
+ (memcpy(GRN_RSET_SUBRECS_NTH(subrecs, size, n), src, GRN_RSET_SUBREC_SIZE(size)))
+#define GRN_RSET_SUBRECS_SIZE(subrec_size,n) \
+ (GRN_RSET_SUBREC_SIZE(subrec_size) * n)
+
+uint32_t grn_rset_recinfo_calc_values_size(grn_ctx *ctx,
+ grn_table_group_flags flags);
+void grn_rset_recinfo_update_calc_values(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table,
+ grn_obj *value);
+
+int64_t *grn_rset_recinfo_get_max_(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table);
+int64_t grn_rset_recinfo_get_max(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table);
+void grn_rset_recinfo_set_max(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table,
+ int64_t max);
+
+int64_t *grn_rset_recinfo_get_min_(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table);
+int64_t grn_rset_recinfo_get_min(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table);
+void grn_rset_recinfo_set_min(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table,
+ int64_t min);
+
+int64_t *grn_rset_recinfo_get_sum_(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table);
+int64_t grn_rset_recinfo_get_sum(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table);
+void grn_rset_recinfo_set_sum(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table,
+ int64_t sum);
+
+double *grn_rset_recinfo_get_avg_(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table);
+double grn_rset_recinfo_get_avg(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table);
+void grn_rset_recinfo_set_avg(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table,
+ double avg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRN_RSET_H */
diff --git a/storage/mroonga/vendor/groonga/lib/grn_scorer.h b/storage/mroonga/vendor/groonga/lib/grn_scorer.h
new file mode 100644
index 00000000000..898a83366b0
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/grn_scorer.h
@@ -0,0 +1,49 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2015 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#ifndef GRN_SCORER_H
+#define GRN_SCORER_H
+
+#include "grn_ctx.h"
+#include "grn_db.h"
+
+#include <groonga/scorer.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct _grn_scorer_matched_record {
+ grn_obj *table;
+ grn_obj *lexicon;
+ grn_id id;
+ grn_obj terms;
+ grn_obj term_weights;
+ uint32_t total_term_weights;
+ uint64_t n_documents;
+ uint32_t n_occurrences;
+ uint64_t n_candidates;
+ uint32_t n_tokens;
+ int weight;
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRN_SCORER_H */
diff --git a/storage/mroonga/vendor/groonga/lib/grn_scorers.h b/storage/mroonga/vendor/groonga/lib/grn_scorers.h
new file mode 100644
index 00000000000..ed6c18c211a
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/grn_scorers.h
@@ -0,0 +1,33 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2015 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#ifndef GRN_SCORERS_H
+#define GRN_SCORERS_H
+
+#include "grn_ctx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+grn_rc grn_db_init_builtin_scorers(grn_ctx *ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRN_SCORERS_H */
diff --git a/storage/mroonga/vendor/groonga/lib/snip.h b/storage/mroonga/vendor/groonga/lib/grn_snip.h
index 7a252921b3a..7c123e0c5f4 100644
--- a/storage/mroonga/vendor/groonga/lib/snip.h
+++ b/storage/mroonga/vendor/groonga/lib/grn_snip.h
@@ -17,15 +17,15 @@
#ifndef GRN_SNIP_H
#define GRN_SNIP_H
-#ifndef GROONGA_IN_H
-#include "groonga_in.h"
-#endif /* GROONGA_IN_H */
+#ifndef GRN_H
+#include "grn.h"
+#endif /* GRN_H */
#ifndef GRN_STR_H
-#include "str.h"
+#include "grn_str.h"
#endif /* GRN_STR_H */
-#include "db.h"
+#include "grn_db.h"
#define ASIZE 256U
#define MAX_SNIP_TAG_COUNT 512U
diff --git a/storage/mroonga/vendor/groonga/lib/store.h b/storage/mroonga/vendor/groonga/lib/grn_store.h
index 719fe775bd9..742d11341fc 100644
--- a/storage/mroonga/vendor/groonga/lib/store.h
+++ b/storage/mroonga/vendor/groonga/lib/grn_store.h
@@ -17,21 +17,10 @@
#ifndef GRN_STORE_H
#define GRN_STORE_H
-#ifndef GROONGA_IN_H
-#include "groonga_in.h"
-#endif /* GROONGA_IN_H */
-
-#ifndef GRN_CTX_H
-#include "ctx.h"
-#endif /* GRN_CTX_H */
-
-#ifndef GRN_HASH_H
-#include "hash.h"
-#endif /* GRN_HASH_H */
-
-#ifndef GRN_IO_H
-#include "io.h"
-#endif /* GRN_IO_H */
+#include "grn.h"
+#include "grn_ctx.h"
+#include "grn_hash.h"
+#include "grn_io.h"
#ifdef __cplusplus
extern "C" {
diff --git a/storage/mroonga/vendor/groonga/lib/str.h b/storage/mroonga/vendor/groonga/lib/grn_str.h
index 069250a70d8..ade8c04053e 100644
--- a/storage/mroonga/vendor/groonga/lib/str.h
+++ b/storage/mroonga/vendor/groonga/lib/grn_str.h
@@ -17,13 +17,8 @@
#ifndef GRN_STR_H
#define GRN_STR_H
-#ifndef GROONGA_IN_H
-#include "groonga_in.h"
-#endif /* GROONGA_IN_H */
-
-#ifndef GRN_NFKC_H
+#include "grn.h"
#include <groonga/nfkc.h>
-#endif /* GRN_NFKC_H */
#ifdef __cplusplus
extern "C" {
@@ -82,7 +77,7 @@ GRN_API grn_str *grn_str_open_(grn_ctx *ctx, const char *str, unsigned int str_l
if (GRN_BULK_OUTP(buf)) {\
(buf)->u.b.curr += (len);\
} else {\
- (buf)->header.flags += (len);\
+ (buf)->header.flags += (grn_obj_flags)(len);\
}\
} while (0)
diff --git a/storage/mroonga/vendor/groonga/lib/string_in.h b/storage/mroonga/vendor/groonga/lib/grn_string.h
index 55e2cb2cbcb..bb5905c84f8 100644
--- a/storage/mroonga/vendor/groonga/lib/string_in.h
+++ b/storage/mroonga/vendor/groonga/lib/grn_string.h
@@ -20,21 +20,21 @@
#ifndef GRN_STRING_H
#define GRN_STRING_H
-#ifndef GROONGA_IN_H
-# include "groonga_in.h"
-#endif /* GROONGA_IN_H */
+#ifndef GRN_H
+# include "grn.h"
+#endif /* GRN_H */
#ifndef GRN_CTX_H
-# include "ctx.h"
+# include "grn_ctx.h"
#endif /* GRN_CTX_H */
#ifndef GRN_DB_H
-# include "db.h"
+# include "grn_db.h"
#endif /* GRN_DB_H */
#ifndef GRN_STR_H
-# include "str.h"
-#endif /* GRN_STR_IN_H */
+# include "grn_str.h"
+#endif /* GRN_STR_H */
#ifdef __cplusplus
extern "C" {
@@ -62,4 +62,4 @@ grn_rc grn_string_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *string);
}
#endif
-#endif /* GRN_STRING_IN_H */
+#endif /* GRN_STRING_H */
diff --git a/storage/mroonga/vendor/groonga/lib/token.h b/storage/mroonga/vendor/groonga/lib/grn_token_cursor.h
index 868930758ba..81175bc432f 100644
--- a/storage/mroonga/vendor/groonga/lib/token.h
+++ b/storage/mroonga/vendor/groonga/lib/grn_token_cursor.h
@@ -14,24 +14,11 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef GRN_TOKEN_H
-#define GRN_TOKEN_H
+#ifndef GRN_TOKEN_CURSOR_H
+#define GRN_TOKEN_CURSOR_H
-#ifndef GROONGA_IN_H
-#include "groonga_in.h"
-#endif /* GROONGA_IN_H */
-
-#ifndef GRN_CTX_H
-#include "ctx.h"
-#endif /* GRN_CTX_H */
-
-#ifndef GRN_DB_H
-#include "db.h"
-#endif /* GRN_DB_H */
-
-#ifndef GRN_STR_H
-#include "str.h"
-#endif /* GRN_STR_H */
+#include "grn_ctx.h"
+#include "grn_db.h"
#include <groonga/tokenizer.h>
@@ -40,15 +27,15 @@ extern "C" {
#endif
typedef enum {
- GRN_TOKEN_DOING = 0,
- GRN_TOKEN_DONE,
- GRN_TOKEN_DONE_SKIP,
- GRN_TOKEN_NOT_FOUND
-} grn_token_status;
+ GRN_TOKEN_CURSOR_DOING = 0,
+ GRN_TOKEN_CURSOR_DONE,
+ GRN_TOKEN_CURSOR_DONE_SKIP,
+ GRN_TOKEN_CURSOR_NOT_FOUND
+} grn_token_cursor_status;
struct _grn_token {
grn_obj data;
- grn_tokenizer_status status;
+ grn_token_status status;
};
typedef struct {
@@ -58,9 +45,9 @@ typedef struct {
uint32_t orig_blen;
uint32_t curr_size;
int32_t pos;
- grn_token_mode mode;
- grn_token_status status;
- uint8_t force_prefix;
+ grn_tokenize_mode mode;
+ grn_token_cursor_status status;
+ grn_bool force_prefix;
grn_obj_flags table_flags;
grn_encoding encoding;
grn_obj *tokenizer;
@@ -70,26 +57,18 @@ typedef struct {
grn_obj *nstr;
} grn_token_cursor;
-extern grn_obj *grn_token_uvector;
-
-grn_rc grn_token_init(void);
-grn_rc grn_token_fin(void);
-
-#define GRN_TOKEN_ENABLE_TOKENIZED_DELIMITER (0x01L<<0)
+#define GRN_TOKEN_CURSOR_ENABLE_TOKENIZED_DELIMITER (0x01L<<0)
GRN_API grn_token_cursor *grn_token_cursor_open(grn_ctx *ctx, grn_obj *table,
const char *str, size_t str_len,
- grn_token_mode mode,
+ grn_tokenize_mode mode,
unsigned int flags);
GRN_API grn_id grn_token_cursor_next(grn_ctx *ctx, grn_token_cursor *token_cursor);
GRN_API grn_rc grn_token_cursor_close(grn_ctx *ctx, grn_token_cursor *token_cursor);
-grn_rc grn_db_init_mecab_tokenizer(grn_ctx *ctx);
-grn_rc grn_db_init_builtin_tokenizers(grn_ctx *ctx);
-
#ifdef __cplusplus
}
#endif
-#endif /* GRN_TOKEN_H */
+#endif /* GRN_TOKEN_CURSOR_H */
diff --git a/storage/mroonga/vendor/groonga/lib/grn_tokenizers.h b/storage/mroonga/vendor/groonga/lib/grn_tokenizers.h
new file mode 100644
index 00000000000..fb85fb76a48
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/grn_tokenizers.h
@@ -0,0 +1,38 @@
+/* -*- c-basic-offset: 2 -*- */
+/* Copyright(C) 2009-2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#ifndef GRN_TOKENIZERS_H
+#define GRN_TOKENIZERS_H
+
+#include "grn_ctx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern grn_obj *grn_tokenizer_uvector;
+
+grn_rc grn_tokenizers_init(void);
+grn_rc grn_tokenizers_fin(void);
+
+grn_rc grn_db_init_mecab_tokenizer(grn_ctx *ctx);
+grn_rc grn_db_init_builtin_tokenizers(grn_ctx *ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRN_TOKENIZERS_H */
diff --git a/storage/mroonga/vendor/groonga/lib/grn_util.h b/storage/mroonga/vendor/groonga/lib/grn_util.h
new file mode 100644
index 00000000000..84aa357e4e3
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/grn_util.h
@@ -0,0 +1,36 @@
+/* -*- c-basic-offset: 2 -*- */
+/* Copyright(C) 2010-2011 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#ifndef GRN_UTIL_H
+#define GRN_UTIL_H
+
+#include "grn.h"
+#include "grn_ctx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+GRN_API grn_rc grn_normalize_offset_and_limit(grn_ctx *ctx, int size, int *offset, int *limit);
+
+GRN_API const char *grn_win32_base_dir(void);
+GRN_API char *grn_path_separator_to_system(char *dest, char *groonga_path);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRN_UTIL_H */
diff --git a/storage/mroonga/vendor/groonga/lib/hash.c b/storage/mroonga/vendor/groonga/lib/hash.c
index fa5854a6a93..22491c5fc8b 100644
--- a/storage/mroonga/vendor/groonga/lib/hash.c
+++ b/storage/mroonga/vendor/groonga/lib/hash.c
@@ -15,13 +15,13 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "hash.h"
-#include "output.h"
+#include "grn_hash.h"
+#include "grn_output.h"
#include <string.h>
#include <limits.h>
-#include "store.h"
-#include "normalizer_in.h"
+#include "grn_store.h"
+#include "grn_normalizer.h"
/* grn_tiny_array */
diff --git a/storage/mroonga/vendor/groonga/lib/ii.c b/storage/mroonga/vendor/groonga/lib/ii.c
index 5dc203865ad..3b5478f9ea7 100644
--- a/storage/mroonga/vendor/groonga/lib/ii.c
+++ b/storage/mroonga/vendor/groonga/lib/ii.c
@@ -1,5 +1,5 @@
/* -*- c-basic-offset: 2 -*- */
-/* Copyright(C) 2009-2014 Brazil
+/* Copyright(C) 2009-2015 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -14,25 +14,34 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "groonga_in.h"
+#include "grn.h"
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
-#include "ii.h"
-#include "ctx_impl.h"
-#include "token.h"
-#include "pat.h"
-#include "db.h"
-#include "output.h"
-#include "util.h"
+#include "grn_ii.h"
+#include "grn_ctx_impl.h"
+#include "grn_token_cursor.h"
+#include "grn_pat.h"
+#include "grn_db.h"
+#include "grn_output.h"
+#include "grn_scorer.h"
+#include "grn_util.h"
+
+#ifdef GRN_WITH_ONIGMO
+# define GRN_II_SELECT_ENABLE_SEQUENTIAL_SEARCH
+#endif
+
+#ifdef GRN_II_SELECT_ENABLE_SEQUENTIAL_SEARCH
+# include "grn_string.h"
+# include <oniguruma.h>
+#endif
#define MAX_PSEG 0x20000
#define S_CHUNK (1 << GRN_II_W_CHUNK)
#define W_SEGMENT 18
#define S_SEGMENT (1 << W_SEGMENT)
-#define N_CHUNKS_PER_FILE (GRN_IO_FILE_SIZE >> W_SEGMENT)
#define W_ARRAY_ELEMENT 3
#define S_ARRAY_ELEMENT (1 << W_ARRAY_ELEMENT)
#define W_ARRAY (W_SEGMENT - W_ARRAY_ELEMENT)
@@ -230,11 +239,11 @@ typedef struct {
uint32_t recs[N_GARBAGES];
} grn_ii_ginfo;
-#define WIN_MAP2(chunk,ctx,iw,seg,pos,size,mode)\
- grn_io_win_map2(chunk, ctx, iw,\
- ((seg) >> GRN_II_N_CHUNK_VARIATION),\
- (((seg) & ((1 << GRN_II_N_CHUNK_VARIATION) - 1)) << GRN_II_W_LEAST_CHUNK) + (pos),\
- size,mode)
+#define WIN_MAP(chunk,ctx,iw,seg,pos,size,mode)\
+ grn_io_win_map(chunk, ctx, iw,\
+ ((seg) >> GRN_II_N_CHUNK_VARIATION),\
+ (((seg) & ((1 << GRN_II_N_CHUNK_VARIATION) - 1)) << GRN_II_W_LEAST_CHUNK) + (pos),\
+ size,mode)
/*
static int new_histogram[32];
static int free_histogram[32];
@@ -285,10 +294,10 @@ chunk_new(grn_ctx *ctx, grn_ii *ii, uint32_t *res, uint32_t size)
iw_.addr = NULL;
gseg = &ii->header->garbages[m - GRN_II_W_LEAST_CHUNK];
while (*gseg != NOT_ASSIGNED) {
- ginfo = WIN_MAP2(ii->chunk, ctx, &iw, *gseg, 0, S_GARBAGE, grn_io_rdwr);
+ ginfo = WIN_MAP(ii->chunk, ctx, &iw, *gseg, 0, S_GARBAGE, grn_io_rdwr);
//GRN_IO_SEG_MAP2(ii->chunk, *gseg, ginfo);
if (!ginfo) {
- if (iw_.addr) { grn_io_win_unmap2(&iw_); }
+ if (iw_.addr) { grn_io_win_unmap(&iw_); }
return GRN_NO_MEMORY_AVAILABLE;
}
if (ginfo->next != NOT_ASSIGNED || ginfo->nrecs > N_GARBAGES_TH) {
@@ -300,15 +309,15 @@ chunk_new(grn_ctx *ctx, grn_ii *ii, uint32_t *res, uint32_t size)
HEADER_CHUNK_OFF(ii, *gseg);
*gseg = ginfo->next;
}
- if (iw_.addr) { grn_io_win_unmap2(&iw_); }
- grn_io_win_unmap2(&iw);
+ if (iw_.addr) { grn_io_win_unmap(&iw_); }
+ grn_io_win_unmap(&iw);
return GRN_SUCCESS;
}
- if (iw_.addr) { grn_io_win_unmap2(&iw_); }
+ if (iw_.addr) { grn_io_win_unmap(&iw_); }
iw_ = iw;
gseg = &ginfo->next;
}
- if (iw_.addr) { grn_io_win_unmap2(&iw_); }
+ if (iw_.addr) { grn_io_win_unmap(&iw_); }
}
vp = &ii->header->free_chunks[m - GRN_II_W_LEAST_CHUNK];
if (*vp == NOT_ASSIGNED) {
@@ -358,24 +367,24 @@ chunk_free(grn_ctx *ctx, grn_ii *ii, uint32_t offset, uint32_t dummy, uint32_t s
gseg = &ii->header->garbages[m - GRN_II_W_LEAST_CHUNK];
iw_.addr = NULL;
while (*gseg != NOT_ASSIGNED) {
- ginfo = WIN_MAP2(ii->chunk, ctx, &iw, *gseg, 0, S_GARBAGE, grn_io_rdwr);
+ ginfo = WIN_MAP(ii->chunk, ctx, &iw, *gseg, 0, S_GARBAGE, grn_io_rdwr);
// GRN_IO_SEG_MAP2(ii->chunk, *gseg, ginfo);
if (!ginfo) {
- if (iw_.addr) { grn_io_win_unmap2(&iw_); }
+ if (iw_.addr) { grn_io_win_unmap(&iw_); }
return GRN_NO_MEMORY_AVAILABLE;
}
if (ginfo->nrecs < N_GARBAGES) { break; }
- if (iw_.addr) { grn_io_win_unmap2(&iw_); }
+ if (iw_.addr) { grn_io_win_unmap(&iw_); }
iw_ = iw;
gseg = &ginfo->next;
}
if (*gseg == NOT_ASSIGNED) {
grn_rc rc;
if ((rc = chunk_new(ctx, ii, gseg, S_GARBAGE))) {
- if (iw_.addr) { grn_io_win_unmap2(&iw_); }
+ if (iw_.addr) { grn_io_win_unmap(&iw_); }
return rc;
}
- ginfo = WIN_MAP2(ii->chunk, ctx, &iw, *gseg, 0, S_GARBAGE, grn_io_rdwr);
+ ginfo = WIN_MAP(ii->chunk, ctx, &iw, *gseg, 0, S_GARBAGE, grn_io_rdwr);
/*
uint32_t i = 0;
while (HEADER_CHUNK_AT(ii, i)) {
@@ -386,7 +395,7 @@ chunk_free(grn_ctx *ctx, grn_ii *ii, uint32_t offset, uint32_t dummy, uint32_t s
GRN_IO_SEG_MAP2(ii->chunk, *gseg, ginfo);
*/
if (!ginfo) {
- if (iw_.addr) { grn_io_win_unmap2(&iw_); }
+ if (iw_.addr) { grn_io_win_unmap(&iw_); }
return GRN_NO_MEMORY_AVAILABLE;
}
ginfo->head = 0;
@@ -394,50 +403,15 @@ chunk_free(grn_ctx *ctx, grn_ii *ii, uint32_t offset, uint32_t dummy, uint32_t s
ginfo->nrecs = 0;
ginfo->next = NOT_ASSIGNED;
}
- if (iw_.addr) { grn_io_win_unmap2(&iw_); }
+ if (iw_.addr) { grn_io_win_unmap(&iw_); }
ginfo->recs[ginfo->head] = offset;
if (++ginfo->head == N_GARBAGES) { ginfo->head = 0; }
ginfo->nrecs++;
- grn_io_win_unmap2(&iw);
+ grn_io_win_unmap(&iw);
ii->header->ngarbages[m - GRN_II_W_LEAST_CHUNK]++;
return GRN_SUCCESS;
}
-/*
-inline static grn_rc
-chunk_new(grn_ii *ii, uint32_t *res, uint32_t size)
-{
- int i, j;
- uint32_t n = (size + S_CHUNK - 1) >> GRN_II_W_CHUNK;
- uint32_t base_seg = grn_io_base_seg(ii->chunk);
- for (i = 0, j = -1; i < GRN_II_MAX_CHUNK; i++) {
- if (HEADER_CHUNK_AT(ii, i)) {
- j = i;
- } else {
- if (i == j + n) {
- j++;
- if (res) { *res = j; }
- for (; j <= i; j++) { HEADER_CHUNK_ON(ii, j); }
- return GRN_SUCCESS;
- }
- // todo : cut off
- if ((i + base_seg)/ N_CHUNKS_PER_FILE !=
- (i + base_seg + 1) / N_CHUNKS_PER_FILE) { j = i; }
- }
- }
- GRN_LOG(ctx, GRN_LOG_CRIT, "index full.");
- return GRN_NO_MEMORY_AVAILABLE;
-}
-
-static void
-chunk_free(grn_ii *ii, int offset, uint32_t size1, uint32_t size2)
-{
- uint32_t i = offset + ((size1 + S_CHUNK - 1) >> GRN_II_W_CHUNK);
- uint32_t n = offset + ((size2 + S_CHUNK - 1) >> GRN_II_W_CHUNK);
- for (; i < n; i++) { HEADER_CHUNK_OFF(ii, i); }
-}
-*/
-
#define UNIT_SIZE 0x80
#define UNIT_MASK (UNIT_SIZE - 1)
@@ -2487,21 +2461,25 @@ typedef struct {
static grn_rc
chunk_flush(grn_ctx *ctx, grn_ii *ii, chunk_info *cinfo, uint8_t *enc, uint32_t encsize)
{
- grn_rc rc;
+ grn_rc rc = GRN_SUCCESS;
uint8_t *dc;
uint32_t dcn;
grn_io_win dw;
- if (!(rc = chunk_new(ctx, ii, &dcn, encsize))) {
- if ((dc = WIN_MAP2(ii->chunk, ctx, &dw, dcn, 0, encsize, grn_io_wronly))) {
- memcpy(dc, enc, encsize);
- grn_io_win_unmap2(&dw);
- cinfo->segno = dcn;
- cinfo->size = encsize;
- rc = GRN_SUCCESS;
- } else {
- chunk_free(ctx, ii, dcn, 0, encsize);
- rc = GRN_NO_MEMORY_AVAILABLE;
+ if (encsize) {
+ if (!(rc = chunk_new(ctx, ii, &dcn, encsize))) {
+ if ((dc = WIN_MAP(ii->chunk, ctx, &dw, dcn, 0, encsize, grn_io_wronly))) {
+ memcpy(dc, enc, encsize);
+ grn_io_win_unmap(&dw);
+ cinfo->segno = dcn;
+ cinfo->size = encsize;
+ } else {
+ chunk_free(ctx, ii, dcn, 0, encsize);
+ rc = GRN_NO_MEMORY_AVAILABLE;
+ }
}
+ } else {
+ cinfo->segno = 0;
+ cinfo->size = 0;
}
return rc;
}
@@ -2517,7 +2495,7 @@ chunk_merge(grn_ctx *ctx, grn_ii *ii, buffer *sb, buffer_term *bt,
uint32_t segno = cinfo->segno, size = cinfo->size, sdf = 0, ndf = 0;
uint32_t *ridp = NULL, *sidp = NULL, *tfp, *weightp = NULL, *posp = NULL;
docinfo cid = {0, 0, 0, 0, 0}, lid = {0, 0, 0, 0, 0}, bid = *bidp;
- uint8_t *scp = WIN_MAP2(ii->chunk, ctx, &sw, segno, 0, size, grn_io_rdonly);
+ uint8_t *scp = WIN_MAP(ii->chunk, ctx, &sw, segno, 0, size, grn_io_rdonly);
if (scp) {
uint16_t nextb = *nextbp;
uint32_t snn = 0, *srp, *ssp = NULL, *stp, *sop = NULL, *snp;
@@ -2558,7 +2536,7 @@ chunk_merge(grn_ctx *ctx, grn_ii *ii, buffer *sb, buffer_term *bt,
ndf = ridp - dv[0].data;
}
datavec_fin(ctx, rdv);
- grn_io_win_unmap2(&sw);
+ grn_io_win_unmap(&sw);
} else {
rc = GRN_NO_MEMORY_AVAILABLE;
}
@@ -2621,6 +2599,7 @@ buffer_merge(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h,
uint64_t spos = 0;
int32_t balance = 0;
uint32_t *ridp, *sidp = NULL, *tfp, *weightp = NULL, *posp, nchunks = 0;
+ uint32_t nvchunks = 0;
chunk_info *cinfo = NULL;
grn_id crid = GRN_ID_NIL;
docinfo cid = {0, 0, 0, 0, 0}, lid = {0, 0, 0, 0, 0}, bid = {0, 0};
@@ -2667,6 +2646,12 @@ buffer_merge(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h,
return rc;
}
}
+ if (cinfo[i].size) {
+ nvchunks++;
+ } else {
+ crid -= cinfo[i].dgap;
+ cinfo[i + 1].dgap += cinfo[i].dgap;
+ }
}
}
if (sce > scp) {
@@ -2739,21 +2724,21 @@ buffer_merge(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h,
memset(bt, 0, sizeof(buffer_term));
nterms_void++;
} else {
- if (!ndf && !nchunks) {
+ if (!ndf && !nvchunks) {
a[0] = 0;
a[1] = 0;
lexicon_delete(ctx, ii, tid, h);
memset(bt, 0, sizeof(buffer_term));
nterms_void++;
} else if ((ii->header->flags & GRN_OBJ_WITH_SECTION)
- && !nchunks && ndf == 1 && lid.rid < 0x100000 &&
+ && !nvchunks && ndf == 1 && lid.rid < 0x100000 &&
lid.sid < 0x800 && lid.tf == 1 && lid.weight == 0) {
a[0] = (lid.rid << 12) + (lid.sid << 1) + 1;
a[1] = (ii->header->flags & GRN_OBJ_WITH_POSITION) ? posp[-1] : 0;
memset(bt, 0, sizeof(buffer_term));
nterms_void++;
} else if (!(ii->header->flags & GRN_OBJ_WITH_SECTION)
- && !nchunks && ndf == 1 && lid.tf == 1 && lid.weight == 0) {
+ && !nvchunks && ndf == 1 && lid.tf == 1 && lid.weight == 0) {
a[0] = (lid.rid << 1) + 1;
a[1] = (ii->header->flags & GRN_OBJ_WITH_POSITION) ? posp[-1] : 0;
memset(bt, 0, sizeof(buffer_term));
@@ -2779,13 +2764,15 @@ buffer_merge(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h,
}
dcp0 = dcp;
a[1] = (bt->size_in_chunk ? a[1] : 0) + (ndf - sdf) + balance;
- if (nchunks) {
+ if (nvchunks) {
int i;
- GRN_B_ENC(nchunks, dcp);
+ GRN_B_ENC(nvchunks, dcp);
for (i = 0; i < nchunks; i++) {
- GRN_B_ENC(cinfo[i].segno, dcp);
- GRN_B_ENC(cinfo[i].size, dcp);
- GRN_B_ENC(cinfo[i].dgap, dcp);
+ if (cinfo[i].size) {
+ GRN_B_ENC(cinfo[i].segno, dcp);
+ GRN_B_ENC(cinfo[i].size, dcp);
+ GRN_B_ENC(cinfo[i].dgap, dcp);
+ }
}
}
encsize = grn_p_encv(ctx, dv, ii->n_elements, dcp);
@@ -2830,18 +2817,23 @@ buffer_merge(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h,
!chunk_flush(ctx, ii, &cinfo[nchunks], dcp, encsize)) {
int i;
cinfo[nchunks].dgap = lid.rid - crid;
- nchunks++;
+ nvchunks++;
dcp = dcp0;
- GRN_B_ENC(nchunks, dcp);
- for (i = 0; i < nchunks; i++) {
- GRN_B_ENC(cinfo[i].segno, dcp);
- GRN_B_ENC(cinfo[i].size, dcp);
- GRN_B_ENC(cinfo[i].dgap, dcp);
+ GRN_B_ENC(nvchunks, dcp);
+ for (i = 0; i <= nchunks; i++) {
+ if (cinfo[i].size) {
+ GRN_B_ENC(cinfo[i].segno, dcp);
+ GRN_B_ENC(cinfo[i].size, dcp);
+ GRN_B_ENC(cinfo[i].dgap, dcp);
+ }
}
GRN_LOG(ctx, GRN_LOG_NOTICE, "split (%d) encsize=%d", tid, encsize);
bt->tid |= CHUNK_SPLIT;
} else {
dcp += encsize;
+ if (!nvchunks) {
+ bt->tid &= ~CHUNK_SPLIT;
+ }
}
bt->pos_in_chunk = (uint32_t)(dcp0 - dc);
bt->size_in_chunk = (uint32_t)(dcp - dcp0);
@@ -2863,7 +2855,7 @@ buffer_merge(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h,
}
static void
-fake_map2(grn_ctx *ctx, grn_io *io, grn_io_win *iw, void *addr, uint32_t seg, uint32_t size)
+fake_map(grn_ctx *ctx, grn_io *io, grn_io_win *iw, void *addr, uint32_t seg, uint32_t size)
{
iw->ctx = ctx;
iw->diff = 0;
@@ -2894,8 +2886,8 @@ buffer_flush(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h)
uint32_t max_dest_chunk_size = sb->header.chunk_size + S_SEGMENT;
if ((dc = GRN_MALLOC(max_dest_chunk_size * 2))) {
if ((scn = sb->header.chunk) == NOT_ASSIGNED ||
- (sc = WIN_MAP2(ii->chunk, ctx, &sw, scn, 0,
- sb->header.chunk_size, grn_io_rdonly))) {
+ (sc = WIN_MAP(ii->chunk, ctx, &sw, scn, 0,
+ sb->header.chunk_size, grn_io_rdonly))) {
uint16_t n = sb->header.nterms;
memset(db, 0, S_SEGMENT);
memcpy(db->terms, sb->terms, n * sizeof(buffer_term));
@@ -2908,12 +2900,12 @@ buffer_flush(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h)
}
if (!actual_chunk_size || !(rc = chunk_new(ctx, ii, &dcn, actual_chunk_size))) {
db->header.chunk = actual_chunk_size ? dcn : NOT_ASSIGNED;
- fake_map2(ctx, ii->chunk, &dw, dc, dcn, actual_chunk_size);
- if (!(rc = grn_io_win_unmap2(&dw))) {
+ fake_map(ctx, ii->chunk, &dw, dc, dcn, actual_chunk_size);
+ if (!(rc = grn_io_win_unmap(&dw))) {
buffer_segment_update(ii, seg, ds);
ii->header->total_chunk_size += actual_chunk_size;
if (scn != NOT_ASSIGNED) {
- grn_io_win_unmap2(&sw);
+ grn_io_win_unmap(&sw);
chunk_free(ctx, ii, scn, 0, sb->header.chunk_size);
ii->header->total_chunk_size -= sb->header.chunk_size;
}
@@ -2922,15 +2914,15 @@ buffer_flush(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h)
if (actual_chunk_size) {
chunk_free(ctx, ii, dcn, 0, actual_chunk_size);
}
- if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); }
+ if (scn != NOT_ASSIGNED) { grn_io_win_unmap(&sw); }
}
} else {
GRN_FREE(dc);
- if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); }
+ if (scn != NOT_ASSIGNED) { grn_io_win_unmap(&sw); }
}
} else {
GRN_FREE(dc);
- if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); }
+ if (scn != NOT_ASSIGNED) { grn_io_win_unmap(&sw); }
}
} else {
GRN_FREE(dc);
@@ -2991,7 +2983,7 @@ grn_ii_buffer_check(grn_ctx *ctx, grn_ii *ii, uint32_t seg)
GRN_OUTPUT_CSTR("void chunk size");
GRN_OUTPUT_INT64(sb->header.chunk_size);
} else {
- if ((sc = WIN_MAP2(ii->chunk, ctx, &sw, scn, 0, sb->header.chunk_size, grn_io_rdonly))) {
+ if ((sc = WIN_MAP(ii->chunk, ctx, &sw, scn, 0, sb->header.chunk_size, grn_io_rdonly))) {
GRN_OUTPUT_CSTR("chunk size");
GRN_OUTPUT_INT64(sb->header.chunk_size);
} else {
@@ -3133,7 +3125,7 @@ grn_ii_buffer_check(grn_ctx *ctx, grn_ii *ii, uint32_t seg)
}
GRN_OUTPUT_MAP_CLOSE();
datavec_fin(ctx, rdv);
- if (sc) { grn_io_win_unmap2(&sw); }
+ if (sc) { grn_io_win_unmap(&sw); }
buffer_close(ctx, ii, pseg);
}
@@ -3236,8 +3228,8 @@ buffer_split(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h)
if ((dc0 = GRN_MALLOC(max_dest_chunk_size * 2))) {
if ((dc1 = GRN_MALLOC(max_dest_chunk_size * 2))) {
if ((scn = sb->header.chunk) == NOT_ASSIGNED ||
- (sc = WIN_MAP2(ii->chunk, ctx, &sw, scn, 0,
- sb->header.chunk_size, grn_io_rdonly))) {
+ (sc = WIN_MAP(ii->chunk, ctx, &sw, scn, 0,
+ sb->header.chunk_size, grn_io_rdonly))) {
term_split(ctx, ii->lexicon, sb, db0, db1);
if (!(rc = buffer_merge(ctx, ii, seg, h, sb, sc, db0, dc0))) {
actual_db0_chunk_size = db0->header.chunk_size;
@@ -3249,8 +3241,8 @@ buffer_split(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h)
if (!actual_db0_chunk_size ||
!(rc = chunk_new(ctx, ii, &dcn0, actual_db0_chunk_size))) {
db0->header.chunk = actual_db0_chunk_size ? dcn0 : NOT_ASSIGNED;
- fake_map2(ctx, ii->chunk, &dw0, dc0, dcn0, actual_db0_chunk_size);
- if (!(rc = grn_io_win_unmap2(&dw0))) {
+ fake_map(ctx, ii->chunk, &dw0, dc0, dcn0, actual_db0_chunk_size);
+ if (!(rc = grn_io_win_unmap(&dw0))) {
if (!(rc = buffer_merge(ctx, ii, seg, h, sb, sc, db1, dc1))) {
actual_db1_chunk_size = db1->header.chunk_size;
if (actual_db1_chunk_size >= max_dest_chunk_size) {
@@ -3260,8 +3252,8 @@ buffer_split(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h)
}
if (!actual_db1_chunk_size ||
!(rc = chunk_new(ctx, ii, &dcn1, actual_db1_chunk_size))) {
- fake_map2(ctx, ii->chunk, &dw1, dc1, dcn1, actual_db1_chunk_size);
- if (!(rc = grn_io_win_unmap2(&dw1))) {
+ fake_map(ctx, ii->chunk, &dw1, dc1, dcn1, actual_db1_chunk_size);
+ if (!(rc = grn_io_win_unmap(&dw1))) {
db1->header.chunk = actual_db1_chunk_size ? dcn1 : NOT_ASSIGNED;
buffer_segment_update(ii, dls0, dps0);
buffer_segment_update(ii, dls1, dps1);
@@ -3271,7 +3263,7 @@ buffer_split(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h)
ii->header->total_chunk_size += actual_db0_chunk_size;
ii->header->total_chunk_size += actual_db1_chunk_size;
if (scn != NOT_ASSIGNED) {
- grn_io_win_unmap2(&sw);
+ grn_io_win_unmap(&sw);
chunk_free(ctx, ii, scn, 0, sb->header.chunk_size);
ii->header->total_chunk_size -= sb->header.chunk_size;
}
@@ -3283,21 +3275,21 @@ buffer_split(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h)
chunk_free(ctx, ii, dcn0, 0, actual_db0_chunk_size);
}
GRN_FREE(dc1);
- if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); }
+ if (scn != NOT_ASSIGNED) { grn_io_win_unmap(&sw); }
}
} else {
if (actual_db0_chunk_size) {
chunk_free(ctx, ii, dcn0, 0, actual_db0_chunk_size);
}
GRN_FREE(dc1);
- if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); }
+ if (scn != NOT_ASSIGNED) { grn_io_win_unmap(&sw); }
}
} else {
if (actual_db0_chunk_size) {
chunk_free(ctx, ii, dcn0, 0, actual_db0_chunk_size);
}
GRN_FREE(dc1);
- if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); }
+ if (scn != NOT_ASSIGNED) { grn_io_win_unmap(&sw); }
}
} else {
if (actual_db0_chunk_size) {
@@ -3305,17 +3297,17 @@ buffer_split(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h)
}
GRN_FREE(dc1);
GRN_FREE(dc0);
- if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); }
+ if (scn != NOT_ASSIGNED) { grn_io_win_unmap(&sw); }
}
} else {
GRN_FREE(dc1);
GRN_FREE(dc0);
- if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); }
+ if (scn != NOT_ASSIGNED) { grn_io_win_unmap(&sw); }
}
} else {
GRN_FREE(dc1);
GRN_FREE(dc0);
- if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); }
+ if (scn != NOT_ASSIGNED) { grn_io_win_unmap(&sw); }
}
} else {
GRN_FREE(dc1);
@@ -3984,16 +3976,16 @@ chunk_is_reused(grn_ctx *ctx, grn_ii *ii, grn_ii_cursor *c, uint32_t offset, uin
gseg = ii->header->garbages[m - GRN_II_W_LEAST_CHUNK];
while (gseg != NOT_ASSIGNED) {
grn_io_win iw;
- grn_ii_ginfo *ginfo = WIN_MAP2(ii->chunk, ctx, &iw, gseg, 0, S_GARBAGE, grn_io_rdwr);
+ grn_ii_ginfo *ginfo = WIN_MAP(ii->chunk, ctx, &iw, gseg, 0, S_GARBAGE, grn_io_rdwr);
if (!ginfo) { break; }
for (i = 0; i < ginfo->nrecs; i++) {
if (ginfo->recs[i] == offset) {
- grn_io_win_unmap2(&iw);
+ grn_io_win_unmap(&iw);
return 0;
}
}
gseg = ginfo->next;
- grn_io_win_unmap2(&iw);
+ grn_io_win_unmap(&iw);
}
return 1;
}
@@ -4047,8 +4039,8 @@ grn_ii_cursor_open(grn_ctx *ctx, grn_ii *ii, grn_id tid,
}
c->ppseg = &ii->header->binfo[LSEG(pos)];
if (bt->size_in_chunk && (chunk = c->buf->header.chunk) != NOT_ASSIGNED) {
- if (!(c->cp = WIN_MAP2(ii->chunk, ctx, &c->iw, chunk, bt->pos_in_chunk,
- bt->size_in_chunk, grn_io_rdonly))) {
+ if (!(c->cp = WIN_MAP(ii->chunk, ctx, &c->iw, chunk, bt->pos_in_chunk,
+ bt->size_in_chunk, grn_io_rdonly))) {
buffer_close(ctx, ii, c->buffer_pseg);
GRN_FREE(c);
c = NULL;
@@ -4069,7 +4061,7 @@ grn_ii_cursor_open(grn_ctx *ctx, grn_ii *ii, grn_id tid,
}
if (!(c->cinfo = GRN_MALLOCN(chunk_info, c->nchunks))) {
buffer_close(ctx, ii, c->buffer_pseg);
- grn_io_win_unmap2(&c->iw);
+ grn_io_win_unmap(&c->iw);
GRN_FREE(c);
c = NULL;
goto exit;
@@ -4162,11 +4154,11 @@ grn_ii_cursor_next(grn_ctx *ctx, grn_ii_cursor *c)
uint8_t *cp;
grn_io_win iw;
uint32_t size = c->cinfo[c->curr_chunk].size;
- if (size && (cp = WIN_MAP2(c->ii->chunk, ctx, &iw,
- c->cinfo[c->curr_chunk].segno, 0,
- size, grn_io_rdonly))) {
+ if (size && (cp = WIN_MAP(c->ii->chunk, ctx, &iw,
+ c->cinfo[c->curr_chunk].segno, 0,
+ size, grn_io_rdonly))) {
grn_p_decv(ctx, cp, size, c->rdv, c->ii->n_elements);
- grn_io_win_unmap2(&iw);
+ grn_io_win_unmap(&iw);
if (chunk_is_reused(ctx, c->ii, c,
c->cinfo[c->curr_chunk].segno, size)) {
GRN_LOG(ctx, GRN_LOG_WARNING,
@@ -4340,7 +4332,7 @@ grn_ii_cursor_close(grn_ctx *ctx, grn_ii_cursor *c)
datavec_fin(ctx, c->rdv);
if (c->cinfo) { GRN_FREE(c->cinfo); }
if (c->buf) { buffer_close(ctx, c->ii, c->buffer_pseg); }
- if (c->cp) { grn_io_win_unmap2(&c->iw); }
+ if (c->cp) { grn_io_win_unmap(&c->iw); }
GRN_FREE(c);
return GRN_SUCCESS;
}
@@ -4670,6 +4662,7 @@ inline static grn_rc
index_del(grn_ctx *ctx, grn_id rid, grn_obj *lexicon, grn_ii *ii, grn_vgram *vgram,
const char *value, size_t value_len)
{
+ grn_rc rc = GRN_SUCCESS;
grn_hash *h;
unsigned int token_flags = 0;
grn_token_cursor *token_cursor;
@@ -4702,12 +4695,16 @@ index_del(grn_ctx *ctx, grn_id rid, grn_obj *lexicon, grn_ii *ii, grn_vgram *vgr
grn_token_cursor_close(ctx, token_cursor);
GRN_HASH_EACH(ctx, h, id, &tp, NULL, &u, {
if (*tp) {
- grn_ii_delete_one(ctx, ii, *tp, *u, NULL);
+ grn_rc r;
+ r = grn_ii_delete_one(ctx, ii, *tp, *u, NULL);
+ if (r) {
+ rc = r;
+ }
}
grn_ii_updspec_close(ctx, *u);
});
grn_hash_close(ctx, h);
- return GRN_SUCCESS;
+ return rc;
}
grn_rc
@@ -4842,7 +4839,11 @@ grn_ii_update(grn_ctx *ctx, grn_ii *ii, grn_id rid, grn_vgram *vgram, unsigned i
grn_hash_delete_by_id(ctx, new, eid, NULL);
}
} else {
- grn_ii_delete_one(ctx, ii, *tp, *u, new);
+ grn_rc r;
+ r = grn_ii_delete_one(ctx, ii, *tp, *u, new);
+ if (r) {
+ rc = r;
+ }
}
grn_ii_updspec_close(ctx, *u);
});
@@ -4867,7 +4868,8 @@ exit :
static grn_rc
grn_vector2updspecs(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section,
- grn_obj *in, grn_obj *out, grn_token_mode mode, grn_obj *posting)
+ grn_obj *in, grn_obj *out, grn_tokenize_mode mode,
+ grn_obj *posting)
{
int j;
grn_id tid;
@@ -4911,8 +4913,65 @@ grn_vector2updspecs(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section,
}
static grn_rc
-grn_uvector2updspecs(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section,
- grn_obj *in, grn_obj *out)
+grn_uvector2updspecs_data(grn_ctx *ctx, grn_ii *ii, grn_id rid,
+ unsigned int section, grn_obj *in, grn_obj *out,
+ grn_tokenize_mode mode, grn_obj *posting)
+{
+ int i, n;
+ grn_hash *h = (grn_hash *)out;
+ grn_obj *lexicon = ii->lexicon;
+ unsigned int element_size;
+
+ n = grn_uvector_size(ctx, in);
+ element_size = grn_uvector_element_size(ctx, in);
+ for (i = 0; i < n; i++) {
+ grn_token_cursor *token_cursor;
+ unsigned int token_flags = 0;
+ const char *element;
+
+ element = GRN_BULK_HEAD(in) + (element_size * i);
+ token_cursor = grn_token_cursor_open(ctx, lexicon,
+ element, element_size,
+ mode, token_flags);
+ if (!token_cursor) {
+ continue;
+ }
+
+ while (!token_cursor->status) {
+ grn_id tid;
+ if ((tid = grn_token_cursor_next(ctx, token_cursor))) {
+ grn_ii_updspec **u;
+
+ if (posting) { GRN_RECORD_PUT(ctx, posting, tid); }
+ if (!grn_hash_add(ctx, h, &tid, sizeof(grn_id), (void **)&u, NULL)) {
+ break;
+ }
+ if (!*u) {
+ if (!(*u = grn_ii_updspec_open(ctx, rid, section))) {
+ GRN_LOG(ctx, GRN_LOG_ALERT,
+ "grn_ii_updspec_open on grn_uvector2updspecs_data failed!");
+ grn_token_cursor_close(ctx, token_cursor);
+ return GRN_NO_MEMORY_AVAILABLE;
+ }
+ }
+ if (grn_ii_updspec_add(ctx, *u, token_cursor->pos, 0)) {
+ GRN_LOG(ctx, GRN_LOG_ALERT,
+ "grn_ii_updspec_add on grn_uvector2updspecs failed!");
+ grn_token_cursor_close(ctx, token_cursor);
+ return GRN_NO_MEMORY_AVAILABLE;
+ }
+ }
+ }
+
+ grn_token_cursor_close(ctx, token_cursor);
+ }
+
+ return GRN_SUCCESS;
+}
+
+static grn_rc
+grn_uvector2updspecs_id(grn_ctx *ctx, grn_ii *ii, grn_id rid,
+ unsigned int section, grn_obj *in, grn_obj *out)
{
int i, n;
grn_ii_updspec **u;
@@ -4941,6 +5000,19 @@ grn_uvector2updspecs(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section,
return GRN_SUCCESS;
}
+static grn_rc
+grn_uvector2updspecs(grn_ctx *ctx, grn_ii *ii, grn_id rid,
+ unsigned int section, grn_obj *in, grn_obj *out,
+ grn_tokenize_mode mode, grn_obj *posting)
+{
+ if (in->header.domain < GRN_N_RESERVED_TYPES) {
+ return grn_uvector2updspecs_data(ctx, ii, rid, section, in, out,
+ mode, posting);
+ } else {
+ return grn_uvector2updspecs_id(ctx, ii, rid, section, in, out);
+ }
+}
+
grn_rc
grn_ii_column_update(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section,
grn_obj *oldvalue, grn_obj *newvalue, grn_obj *posting)
@@ -5001,7 +5073,8 @@ grn_ii_column_update(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section,
rc = GRN_NO_MEMORY_AVAILABLE;
} else {
if (new_->header.type == GRN_UVECTOR) {
- rc = grn_uvector2updspecs(ctx, ii, rid, section, new_, new);
+ rc = grn_uvector2updspecs(ctx, ii, rid, section, new_, new,
+ GRN_TOKEN_ADD, post);
} else {
grn_obj uvector;
unsigned int weight = 0;
@@ -5010,7 +5083,8 @@ grn_ii_column_update(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section,
uvector.header.impl_flags |= GRN_OBJ_WITH_WEIGHT;
}
grn_uvector_add_element(ctx, &uvector, GRN_RECORD_VALUE(new_), weight);
- rc = grn_uvector2updspecs(ctx, ii, rid, section, &uvector, new);
+ rc = grn_uvector2updspecs(ctx, ii, rid, section, &uvector, new,
+ GRN_TOKEN_ADD, post);
GRN_OBJ_FIN(ctx, &uvector);
}
}
@@ -5095,7 +5169,8 @@ grn_ii_column_update(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section,
rc = GRN_NO_MEMORY_AVAILABLE;
} else {
if (old_->header.type == GRN_UVECTOR) {
- rc = grn_uvector2updspecs(ctx, ii, rid, section, old_, old);
+ rc = grn_uvector2updspecs(ctx, ii, rid, section, old_, old,
+ GRN_TOKEN_DEL, NULL);
} else {
grn_obj uvector;
unsigned int weight = 0;
@@ -5104,7 +5179,8 @@ grn_ii_column_update(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section,
uvector.header.impl_flags |= GRN_OBJ_WITH_WEIGHT;
}
grn_uvector_add_element(ctx, &uvector, GRN_RECORD_VALUE(old_), weight);
- rc = grn_uvector2updspecs(ctx, ii, rid, section, &uvector, old);
+ rc = grn_uvector2updspecs(ctx, ii, rid, section, &uvector, old,
+ GRN_TOKEN_DEL, NULL);
GRN_OBJ_FIN(ctx, &uvector);
}
}
@@ -5130,7 +5206,11 @@ grn_ii_column_update(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section,
grn_hash_delete_by_id(ctx, n, eid, NULL);
}
} else {
- grn_ii_delete_one(ctx, ii, *tp, *u, n);
+ grn_rc r;
+ r = grn_ii_delete_one(ctx, ii, *tp, *u, n);
+ if (r) {
+ rc = r;
+ }
}
grn_ii_updspec_close(ctx, *u);
});
@@ -5362,7 +5442,7 @@ token_info_build(grn_ctx *ctx, grn_obj *lexicon, grn_ii *ii, const char *string,
const char *key;
uint32_t size;
grn_rc rc = GRN_END_OF_DATA;
- unsigned int token_flags = GRN_TOKEN_ENABLE_TOKENIZED_DELIMITER;
+ unsigned int token_flags = GRN_TOKEN_CURSOR_ENABLE_TOKENIZED_DELIMITER;
grn_token_cursor *token_cursor = grn_token_cursor_open(ctx, lexicon,
string, string_len,
GRN_TOKEN_GET,
@@ -5394,11 +5474,11 @@ token_info_build(grn_ctx *ctx, grn_obj *lexicon, grn_ii *ii, const char *string,
tid = grn_token_cursor_next(ctx, token_cursor);
if (token_cursor->force_prefix) { ef |= EX_PREFIX; }
switch (token_cursor->status) {
- case GRN_TOKEN_DOING :
+ case GRN_TOKEN_CURSOR_DOING :
key = _grn_table_key(ctx, lexicon, tid, &size);
ti = token_info_open(ctx, lexicon, ii, key, size, token_cursor->pos, ef & EX_SUFFIX);
break;
- case GRN_TOKEN_DONE :
+ case GRN_TOKEN_CURSOR_DONE :
ti = token_info_open(ctx, lexicon, ii, (const char *)token_cursor->curr,
token_cursor->curr_size, 0, ef);
/*
@@ -5408,11 +5488,11 @@ token_info_build(grn_ctx *ctx, grn_obj *lexicon, grn_ii *ii, const char *string,
token_cursor->orig_blen, token_cursor->pos, ef);
*/
break;
- case GRN_TOKEN_NOT_FOUND :
+ case GRN_TOKEN_CURSOR_NOT_FOUND :
ti = token_info_open(ctx, lexicon, ii, (char *)token_cursor->orig,
token_cursor->orig_blen, 0, ef);
break;
- case GRN_TOKEN_DONE_SKIP :
+ case GRN_TOKEN_CURSOR_DONE_SKIP :
*only_skip_token = GRN_TRUE;
goto exit;
default :
@@ -5420,16 +5500,17 @@ token_info_build(grn_ctx *ctx, grn_obj *lexicon, grn_ii *ii, const char *string,
}
if (!ti) { goto exit ; }
tis[(*n)++] = ti;
- while (token_cursor->status == GRN_TOKEN_DOING) {
+ while (token_cursor->status == GRN_TOKEN_CURSOR_DOING) {
tid = grn_token_cursor_next(ctx, token_cursor);
+ if (token_cursor->force_prefix) { ef |= EX_PREFIX; }
switch (token_cursor->status) {
- case GRN_TOKEN_DONE_SKIP :
+ case GRN_TOKEN_CURSOR_DONE_SKIP :
continue;
- case GRN_TOKEN_DOING :
+ case GRN_TOKEN_CURSOR_DOING :
key = _grn_table_key(ctx, lexicon, tid, &size);
ti = token_info_open(ctx, lexicon, ii, key, size, token_cursor->pos, EX_NONE);
break;
- case GRN_TOKEN_DONE :
+ case GRN_TOKEN_CURSOR_DONE :
if (tid) {
key = _grn_table_key(ctx, lexicon, tid, &size);
ti = token_info_open(ctx, lexicon, ii, key, size, token_cursor->pos, ef & EX_PREFIX);
@@ -5460,7 +5541,7 @@ token_info_clear_offset(token_info **tis, uint32_t n)
/* select */
inline static void
-res_add(grn_ctx *ctx, grn_hash *s, grn_rset_posinfo *pi, uint32_t score,
+res_add(grn_ctx *ctx, grn_hash *s, grn_rset_posinfo *pi, double score,
grn_operator op)
{
grn_rset_recinfo *ri;
@@ -5619,7 +5700,7 @@ typedef enum {
grn_wv_constant
} grn_wv_mode;
-inline static int
+inline static double
get_weight(grn_ctx *ctx, grn_hash *s, grn_id rid, int sid,
grn_wv_mode wvm, grn_select_optarg *optarg)
{
@@ -5656,7 +5737,7 @@ grn_ii_similar_search(grn_ctx *ctx, grn_ii *ii,
grn_rc rc = GRN_SUCCESS;
grn_hash *h;
grn_token_cursor *token_cursor;
- unsigned int token_flags = GRN_TOKEN_ENABLE_TOKENIZED_DELIMITER;
+ unsigned int token_flags = GRN_TOKEN_CURSOR_ENABLE_TOKENIZED_DELIMITER;
grn_obj *lexicon = ii->lexicon;
if (!lexicon || !ii || !string || !string_len || !s || !optarg) { return GRN_INVALID_ARGUMENT; }
if (!(h = grn_hash_create(ctx, NULL, sizeof(grn_id), sizeof(int), 0))) {
@@ -5668,8 +5749,8 @@ grn_ii_similar_search(grn_ctx *ctx, grn_ii *ii,
return GRN_NO_MEMORY_AVAILABLE;
}
if (!(max_size = optarg->max_size)) { max_size = 1048576; }
- while (token_cursor->status != GRN_TOKEN_DONE &&
- token_cursor->status != GRN_TOKEN_DONE_SKIP) {
+ while (token_cursor->status != GRN_TOKEN_CURSOR_DONE &&
+ token_cursor->status != GRN_TOKEN_CURSOR_DONE_SKIP) {
if ((tid = grn_token_cursor_next(ctx, token_cursor))) {
if (grn_hash_add(ctx, h, &tid, sizeof(grn_id), (void **)&w1, NULL)) { (*w1)++; }
}
@@ -5749,7 +5830,7 @@ grn_ii_similar_search(grn_ctx *ctx, grn_ii *ii,
if (rep) {
while (grn_ii_cursor_next(ctx, c)) {
pos = c->post;
- if ((w2 = get_weight(ctx, s, pos->rid, pos->sid, wvm, optarg))) {
+ if ((w2 = get_weight(ctx, s, pos->rid, pos->sid, wvm, optarg)) > 0) {
while (grn_ii_cursor_next_pos(ctx, c)) {
res_add(ctx, s, (grn_rset_posinfo *) pos, *w1 * w2 * (1 + pos->weight), op);
}
@@ -5758,7 +5839,7 @@ grn_ii_similar_search(grn_ctx *ctx, grn_ii *ii,
} else {
while (grn_ii_cursor_next(ctx, c)) {
pos = c->post;
- if ((w2 = get_weight(ctx, s, pos->rid, pos->sid, wvm, optarg))) {
+ if ((w2 = get_weight(ctx, s, pos->rid, pos->sid, wvm, optarg)) > 0) {
res_add(ctx, s, (grn_rset_posinfo *) pos, *w1 * w2 * (pos->tf + pos->weight), op);
}
}
@@ -5859,6 +5940,213 @@ grn_ii_term_extract(grn_ctx *ctx, grn_ii *ii, const char *string,
return rc;
}
+#ifdef GRN_II_SELECT_ENABLE_SEQUENTIAL_SEARCH
+static grn_bool
+grn_ii_select_sequential_search_should_use(grn_ctx *ctx,
+ grn_ii *ii,
+ const char *raw_query,
+ unsigned int raw_query_len,
+ grn_hash *result,
+ grn_operator op,
+ grn_wv_mode wvm,
+ grn_select_optarg *optarg,
+ token_info **token_infos,
+ uint32_t n_token_infos,
+ double too_many_index_match_ratio)
+{
+ int n_sources;
+
+ if (too_many_index_match_ratio < 0.0) {
+ return GRN_FALSE;
+ }
+
+ if (op != GRN_OP_AND) {
+ return GRN_FALSE;
+ }
+
+ if (optarg->mode != GRN_OP_EXACT) {
+ return GRN_FALSE;
+ }
+
+ n_sources = ii->obj.source_size / sizeof(grn_id);
+ if (n_sources == 0) {
+ return GRN_FALSE;
+ }
+
+ {
+ uint32_t i;
+ int n_existing_records;
+
+ n_existing_records = GRN_HASH_SIZE(result);
+ for (i = 0; i < n_token_infos; i++) {
+ token_info *info = token_infos[i];
+ if (n_existing_records <= (info->size * too_many_index_match_ratio)) {
+ return GRN_TRUE;
+ }
+ }
+ return GRN_FALSE;
+ }
+}
+
+static void
+grn_ii_select_sequential_search_body(grn_ctx *ctx,
+ grn_ii *ii,
+ grn_obj *normalizer,
+ grn_encoding encoding,
+ OnigRegex regex,
+ grn_hash *result,
+ grn_operator op,
+ grn_wv_mode wvm,
+ grn_select_optarg *optarg)
+{
+ int i, n_sources;
+ grn_id *source_ids = ii->obj.source;
+ grn_obj buffer;
+
+ GRN_TEXT_INIT(&buffer, 0);
+ n_sources = ii->obj.source_size / sizeof(grn_id);
+ for (i = 0; i < n_sources; i++) {
+ grn_id source_id = source_ids[i];
+ grn_obj *source;
+ char column_name[GRN_TABLE_MAX_KEY_SIZE];
+ int column_name_size;
+ grn_obj *accessor;
+
+ source = grn_ctx_at(ctx, source_id);
+ column_name_size = grn_column_name(ctx, source,
+ column_name,
+ GRN_TABLE_MAX_KEY_SIZE);
+ accessor = grn_obj_column(ctx, (grn_obj *)result, column_name,
+ column_name_size);
+ {
+ grn_hash_cursor *cursor;
+ grn_id id;
+ cursor = grn_hash_cursor_open(ctx, result, NULL, 0, NULL, 0, 0, -1, 0);
+ while ((id = grn_hash_cursor_next(ctx, cursor)) != GRN_ID_NIL) {
+ OnigPosition position;
+ grn_obj *value;
+ const char *normalized_value;
+ unsigned int normalized_value_length;
+
+ GRN_BULK_REWIND(&buffer);
+ grn_obj_get_value(ctx, accessor, id, &buffer);
+ value = grn_string_open_(ctx,
+ GRN_TEXT_VALUE(&buffer),
+ GRN_TEXT_LEN(&buffer),
+ normalizer, 0, encoding);
+ grn_string_get_normalized(ctx, value,
+ &normalized_value, &normalized_value_length,
+ NULL);
+ position = onig_search(regex,
+ normalized_value,
+ normalized_value + normalized_value_length,
+ normalized_value,
+ normalized_value + normalized_value_length,
+ NULL,
+ 0);
+ if (position != ONIG_MISMATCH) {
+ grn_rset_posinfo info;
+ double score;
+ info.rid = id;
+ info.sid = i + 1;
+ info.pos = 0;
+ score = get_weight(ctx, result, info.rid, info.sid, wvm, optarg);
+ res_add(ctx, result, &info, score, op);
+ }
+ grn_obj_unlink(ctx, value);
+ }
+ grn_hash_cursor_close(ctx, cursor);
+ }
+ grn_obj_unlink(ctx, accessor);
+ }
+ grn_obj_unlink(ctx, &buffer);
+}
+
+static grn_bool
+grn_ii_select_sequential_search(grn_ctx *ctx,
+ grn_ii *ii,
+ const char *raw_query,
+ unsigned int raw_query_len,
+ grn_hash *result,
+ grn_operator op,
+ grn_wv_mode wvm,
+ grn_select_optarg *optarg,
+ token_info **token_infos,
+ uint32_t n_token_infos)
+{
+ grn_bool processed = GRN_TRUE;
+
+ {
+ /* Disabled by default. */
+ double too_many_index_match_ratio = -1;
+ const char *too_many_index_match_ratio_env =
+ getenv("GRN_II_SELECT_TOO_MANY_INDEX_MATCH_RATIO");
+ if (too_many_index_match_ratio_env) {
+ too_many_index_match_ratio = atof(too_many_index_match_ratio_env);
+ }
+
+ if (!grn_ii_select_sequential_search_should_use(ctx,
+ ii,
+ raw_query,
+ raw_query_len,
+ result,
+ op,
+ wvm,
+ optarg,
+ token_infos,
+ n_token_infos,
+ too_many_index_match_ratio)) {
+ return GRN_FALSE;
+ }
+ }
+
+ {
+ grn_encoding encoding;
+ grn_obj *normalizer;
+ int nflags = 0;
+ grn_obj *query;
+ const char *normalized_query;
+ unsigned int normalized_query_length;
+
+ grn_table_get_info(ctx, ii->lexicon,
+ NULL, &encoding, NULL, &normalizer, NULL);
+ query = grn_string_open_(ctx, raw_query, raw_query_len,
+ normalizer, nflags, encoding);
+ grn_string_get_normalized(ctx, query,
+ &normalized_query, &normalized_query_length,
+ NULL);
+ {
+ OnigRegex regex;
+ int onig_result;
+ OnigErrorInfo error_info;
+ onig_result = onig_new(&regex,
+ normalized_query,
+ normalized_query + normalized_query_length,
+ ONIG_OPTION_NONE,
+ ONIG_ENCODING_UTF8,
+ ONIG_SYNTAX_ASIS,
+ &error_info);
+ if (onig_result == ONIG_NORMAL) {
+ grn_ii_select_sequential_search_body(ctx, ii, normalizer, encoding,
+ regex, result, op, wvm, optarg);
+ onig_free(regex);
+ } else {
+ char message[ONIG_MAX_ERROR_MESSAGE_LEN];
+ onig_error_code_to_str(message, onig_result, error_info);
+ GRN_LOG(ctx, GRN_LOG_WARNING,
+ "[ii][select][sequential] "
+ "failed to create regular expression object: %s",
+ message);
+ processed = GRN_FALSE;
+ }
+ }
+ grn_obj_unlink(ctx, query);
+ }
+
+ return processed;
+}
+#endif
+
grn_rc
grn_ii_select(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_len,
grn_hash *s, grn_operator op, grn_select_optarg *optarg)
@@ -5872,6 +6160,10 @@ grn_ii_select(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_
grn_operator mode = GRN_OP_EXACT;
grn_wv_mode wvm = grn_wv_none;
grn_obj *lexicon = ii->lexicon;
+ grn_scorer_score_func *score_func = NULL;
+ void *score_func_user_data = NULL;
+ grn_scorer_matched_record record;
+
if (!lexicon || !ii || !s) { return GRN_INVALID_ARGUMENT; }
if (optarg) {
mode = optarg->mode;
@@ -5938,6 +6230,30 @@ grn_ii_select(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_
goto exit;
}
*/
+#ifdef GRN_II_SELECT_ENABLE_SEQUENTIAL_SEARCH
+ if (grn_ii_select_sequential_search(ctx, ii, string, string_len,
+ s, op, wvm, optarg, tis, n)) {
+ goto exit;
+ }
+#endif
+
+ if (optarg && optarg->scorer) {
+ grn_proc *scorer = (grn_proc *)(optarg->scorer);
+ score_func = scorer->callbacks.scorer.score;
+ score_func_user_data = scorer->user_data;
+ record.table = grn_ctx_at(ctx, s->obj.header.domain);
+ record.lexicon = lexicon;
+ record.id = GRN_ID_NIL;
+ GRN_RECORD_INIT(&(record.terms), GRN_OBJ_VECTOR, lexicon->header.domain);
+ GRN_UINT32_INIT(&(record.term_weights), GRN_OBJ_VECTOR);
+ record.total_term_weights = 0;
+ record.n_documents = grn_table_size(ctx, record.table);
+ record.n_occurrences = 0;
+ record.n_candidates = 0;
+ record.n_tokens = 0;
+ record.weight = 0;
+ }
+
for (;;) {
rid = (*tis)->p->rid;
sid = (*tis)->p->sid;
@@ -5951,11 +6267,18 @@ grn_ii_select(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_
}
}
weight = get_weight(ctx, s, rid, sid, wvm, optarg);
- if (tip == tie && weight) {
+ if (tip == tie && weight > 0) {
grn_rset_posinfo pi = {rid, sid, 0};
if (orp || grn_hash_get(ctx, s, &pi, s->key_size, NULL)) {
int count = 0, noccur = 0, pos = 0, score = 0, tscore = 0, min, max;
+ if (score_func) {
+ GRN_BULK_REWIND(&(record.terms));
+ GRN_BULK_REWIND(&(record.term_weights));
+ record.n_candidates = 0;
+ record.n_tokens = 0;
+ }
+
#define SKIP_OR_BREAK(pos) {\
if (token_info_skip_pos(ctx, ti, rid, sid, pos)) { break; } \
if (ti->p->rid != rid || ti->p->sid != sid) { \
@@ -5967,6 +6290,13 @@ grn_ii_select(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_
if (n == 1 && !rep) {
noccur = (*tis)->p->tf;
tscore = (*tis)->p->weight;
+ if (score_func) {
+ GRN_RECORD_PUT(ctx, &(record.terms), (*tis)->cursors->bins[0]->id);
+ GRN_UINT32_PUT(ctx, &(record.term_weights), tscore);
+ record.n_occurrences = noccur;
+ record.n_candidates = (*tis)->size;
+ record.n_tokens = (*tis)->ntoken;
+ }
} else if (mode == GRN_OP_NEAR) {
bt_zap(bt);
for (tip = tis; tip < tie; tip++) {
@@ -6003,6 +6333,18 @@ grn_ii_select(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_
score += ti->p->weight; count++;
} else {
score = ti->p->weight; count = 1; pos = ti->pos;
+ if (noccur == 0 && score_func) {
+ GRN_BULK_REWIND(&(record.terms));
+ GRN_BULK_REWIND(&(record.term_weights));
+ record.n_candidates = 0;
+ record.n_tokens = 0;
+ }
+ }
+ if (noccur == 0 && score_func) {
+ GRN_RECORD_PUT(ctx, &(record.terms), ti->cursors->bins[0]->id);
+ GRN_UINT32_PUT(ctx, &(record.term_weights), ti->p->weight);
+ record.n_candidates += ti->size;
+ record.n_tokens += ti->ntoken;
}
if (count == n) {
if (rep) { pi.pos = pos; res_add(ctx, s, &pi, (score + 1) * weight, op); }
@@ -6012,13 +6354,29 @@ grn_ii_select(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_
}
}
}
- if (noccur && !rep) { res_add(ctx, s, &pi, (noccur + tscore) * weight, op); }
+ if (noccur && !rep) {
+ double record_score;
+ if (score_func) {
+ record.id = rid;
+ record.weight = weight;
+ record.n_occurrences = noccur;
+ record.total_term_weights = tscore;
+ record_score = score_func(ctx, &record) * weight;
+ } else {
+ record_score = (noccur + tscore) * weight;
+ }
+ res_add(ctx, s, &pi, record_score, op);
+ }
#undef SKIP_OR_BREAK
}
}
if (token_info_skip(ctx, *tis, nrid, nsid)) { goto exit; }
}
exit :
+ if (score_func) {
+ GRN_OBJ_FIN(ctx, &(record.terms));
+ GRN_OBJ_FIN(ctx, &(record.term_weights));
+ }
for (tip = tis; tip < tis + n; tip++) {
if (*tip) { token_info_close(ctx, *tip); }
}
@@ -6046,7 +6404,7 @@ grn_ii_sel(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_len
ERRCLR(ctx);
GRN_LOG(ctx, GRN_LOG_INFO, "grn_ii_sel > (%.*s)", string_len, string);
{
- grn_select_optarg arg = {GRN_OP_EXACT, 0, 0, NULL, 0, NULL, NULL, 0};
+ grn_select_optarg arg = {GRN_OP_EXACT, 0, 0, NULL, 0, NULL, NULL, 0, NULL};
if (!s) { return GRN_INVALID_ARGUMENT; }
if (optarg) {
switch (optarg->mode) {
@@ -6066,6 +6424,7 @@ grn_ii_sel(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_len
arg.weight_vector = optarg->weight_vector;
arg.vector_size = optarg->vector_size;
}
+ arg.scorer = optarg->scorer;
}
/* todo : support subrec
grn_rset_init(ctx, s, grn_rec_document, 0, grn_rec_none, 0, 0);
@@ -6198,11 +6557,11 @@ grn_ii_cursor_next_all(grn_ctx *ctx, grn_ii_cursor *c)
uint8_t *cp;
grn_io_win iw;
uint32_t size = c->cinfo[c->curr_chunk].size;
- if (size && (cp = WIN_MAP2(c->ii->chunk, ctx, &iw,
- c->cinfo[c->curr_chunk].segno, 0,
- size, grn_io_rdonly))) {
+ if (size && (cp = WIN_MAP(c->ii->chunk, ctx, &iw,
+ c->cinfo[c->curr_chunk].segno, 0,
+ size, grn_io_rdonly))) {
grn_p_decv(ctx, cp, size, c->rdv, c->ii->n_elements);
- grn_io_win_unmap2(&iw);
+ grn_io_win_unmap(&iw);
} else {
c->pc.rid = 0;
break;
@@ -6367,7 +6726,7 @@ grn_ii_cursor_inspect(grn_ctx *ctx, grn_ii_cursor *c, grn_obj *buf)
}
void
-grn_ii_inspect_elements(grn_ctx *ctx, grn_ii *ii, grn_obj *buf)
+grn_ii_inspect_values(grn_ctx *ctx, grn_ii *ii, grn_obj *buf)
{
grn_table_cursor *tc;
GRN_TEXT_PUTS(ctx, buf, "[");
@@ -6426,8 +6785,8 @@ typedef struct {
} ii_buffer_counter;
typedef struct {
- off_t head;
- off_t tail;
+ off64_t head;
+ off64_t tail;
uint32_t nextsize;
uint8_t *buffer;
uint32_t buffersize;
@@ -6450,7 +6809,7 @@ struct _grn_ii_buffer {
char tmpfpath[PATH_MAX];
uint64_t update_buffer_size;
// stuff for parsing
- off_t filepos;
+ off64_t filepos;
grn_id *block_buf;
size_t block_buf_size;
size_t block_pos;
@@ -6521,7 +6880,7 @@ allocate_outbuf(grn_ctx *ctx, grn_ii_buffer *ii_buffer)
bufsize_ = bufsize;
}
}
- GRN_LOG(ctx, GRN_LOG_INFO, "flushing:%d bufsize:%zu",
+ GRN_LOG(ctx, GRN_LOG_INFO, "flushing:%d bufsize:%" GRN_FMT_SIZE,
ii_buffer->nblocks, bufsize);
return (uint8_t *)GRN_MALLOC(bufsize);
}
@@ -6679,7 +7038,7 @@ grn_ii_buffer_flush(grn_ctx *ctx, grn_ii_buffer *ii_buffer)
size_t encsize;
uint8_t *outbuf;
ii_buffer_block *block;
- GRN_LOG(ctx, GRN_LOG_NOTICE, "flushing:%d npostings:%zu",
+ GRN_LOG(ctx, GRN_LOG_NOTICE, "flushing:%d npostings:%" GRN_FMT_SIZE,
ii_buffer->nblocks, ii_buffer->block_pos);
if (!(block = block_new(ctx, ii_buffer))) { return; }
if (!(outbuf = allocate_outbuf(ctx, ii_buffer))) { return; }
@@ -6701,7 +7060,7 @@ grn_ii_buffer_flush(grn_ctx *ctx, grn_ii_buffer *ii_buffer)
grn_table_size(ctx, ii_buffer->tmp_lexicon) *
sizeof(ii_buffer_counter));
grn_obj_close(ctx, ii_buffer->tmp_lexicon);
- GRN_LOG(ctx, GRN_LOG_NOTICE, "flushed: %d encsize:%zu",
+ GRN_LOG(ctx, GRN_LOG_NOTICE, "flushed: %d encsize:%" GRN_FMT_SIZE,
ii_buffer->nblocks, encsize);
ii_buffer->tmp_lexicon = NULL;
ii_buffer->nblocks++;
@@ -6719,9 +7078,10 @@ get_tmp_lexicon(grn_ctx *ctx, grn_ii_buffer *ii_buffer)
grn_obj *range = grn_ctx_at(ctx, DB_OBJ(ii_buffer->lexicon)->range);
grn_obj *tokenizer;
grn_obj *normalizer;
+ grn_obj *token_filters;
grn_obj_flags flags;
grn_table_get_info(ctx, ii_buffer->lexicon, &flags, NULL,
- &tokenizer, &normalizer, NULL);
+ &tokenizer, &normalizer, &token_filters);
flags &= ~GRN_OBJ_PERSISTENT;
tmp_lexicon = grn_table_create(ctx, NULL, 0, NULL, flags, domain, range);
if (tmp_lexicon) {
@@ -6730,6 +7090,8 @@ get_tmp_lexicon(grn_ctx *ctx, grn_ii_buffer *ii_buffer)
GRN_INFO_DEFAULT_TOKENIZER, tokenizer);
grn_obj_set_info(ctx, tmp_lexicon,
GRN_INFO_NORMALIZER, normalizer);
+ grn_obj_set_info(ctx, tmp_lexicon,
+ GRN_INFO_TOKEN_FILTERS, token_filters);
if ((flags & GRN_OBJ_TABLE_TYPE_MASK) == GRN_OBJ_TABLE_PAT_KEY) {
grn_pat_cache_enable(ctx, (grn_pat *)tmp_lexicon, PAT_CACHE_SIZE);
}
@@ -6857,8 +7219,8 @@ grn_ii_buffer_fetch(grn_ctx *ctx, grn_ii_buffer *ii_buffer,
return;
}
}
- if (lseek(ii_buffer->tmpfd, block->head, SEEK_SET) != block->head) {
- SERR("lseek");
+ if (grn_lseek(ii_buffer->tmpfd, block->head, SEEK_SET) != block->head) {
+ SERR("grn_lseek");
return;
}
if (read(ii_buffer->tmpfd, block->buffer, bytesize) != bytesize) {
@@ -6870,7 +7232,8 @@ grn_ii_buffer_fetch(grn_ctx *ctx, grn_ii_buffer *ii_buffer,
if (block->head >= block->tail) {
if (block->head > block->tail) {
GRN_LOG(ctx, GRN_LOG_WARNING,
- "fetch error: %jd > %jd", block->head, block->tail);
+ "fetch error: %" GRN_FMT_INT64D " > %" GRN_FMT_INT64D,
+ block->head, block->tail);
}
block->rest = block->nextsize;
block->nextsize = 0;
@@ -6899,11 +7262,11 @@ grn_ii_buffer_chunk_flush(grn_ctx *ctx, grn_ii_buffer *ii_buffer)
grn_io_win io_win;
uint32_t chunk_number;
chunk_new(ctx, ii_buffer->ii, &chunk_number, ii_buffer->packed_len);
- GRN_LOG(ctx, GRN_LOG_INFO, "chunk:%d, packed_len:%zu",
+ GRN_LOG(ctx, GRN_LOG_INFO, "chunk:%d, packed_len:%" GRN_FMT_SIZE,
chunk_number, ii_buffer->packed_len);
- fake_map2(ctx, ii_buffer->ii->chunk, &io_win, ii_buffer->packed_buf,
- chunk_number, ii_buffer->packed_len);
- grn_io_win_unmap2(&io_win);
+ fake_map(ctx, ii_buffer->ii->chunk, &io_win, ii_buffer->packed_buf,
+ chunk_number, ii_buffer->packed_len);
+ grn_io_win_unmap(&io_win);
ii_buffer->term_buffer->header.chunk = chunk_number;
ii_buffer->term_buffer->header.chunk_size = ii_buffer->packed_len;
ii_buffer->term_buffer->header.buffer_free =
@@ -7165,11 +7528,15 @@ grn_ii_buffer_open(grn_ctx *ctx, grn_ii *ii,
if (ii_buffer->counters) {
ii_buffer->block_buf = GRN_MALLOCN(grn_id, II_BUFFER_BLOCK_SIZE);
if (ii_buffer->block_buf) {
+ int open_flags = 0;
+#ifdef WIN32
+ open_flags |= O_BINARY;
+#endif
snprintf(ii_buffer->tmpfpath, PATH_MAX,
"%sXXXXXX", grn_io_path(ii->seg));
ii_buffer->block_buf_size = II_BUFFER_BLOCK_SIZE;
ii_buffer->tmpfd = GRN_MKOSTEMP(ii_buffer->tmpfpath,
- O_WRONLY|O_CREAT|O_TRUNC,
+ open_flags,
S_IRUSR|S_IWUSR);
if (ii_buffer->tmpfd != -1) {
grn_obj_flags flags;
@@ -7283,7 +7650,7 @@ grn_ii_buffer_commit(grn_ctx *ctx, grn_ii_buffer *ii_buffer)
}
datavec_fin(ctx, ii_buffer->data_vectors);
GRN_LOG(ctx, GRN_LOG_NOTICE,
- "tmpfile_size:%jd > total_chunk_size:%" GRN_FMT_INT64U,
+ "tmpfile_size:%" GRN_FMT_INT64D " > total_chunk_size:%" GRN_FMT_SIZE,
ii_buffer->filepos, ii_buffer->total_chunk_size);
GRN_CLOSE(ii_buffer->tmpfd);
unlink(ii_buffer->tmpfpath);
diff --git a/storage/mroonga/vendor/groonga/lib/io.c b/storage/mroonga/vendor/groonga/lib/io.c
index 067832ee77b..2ea581b8db7 100644
--- a/storage/mroonga/vendor/groonga/lib/io.c
+++ b/storage/mroonga/vendor/groonga/lib/io.c
@@ -1,5 +1,5 @@
/* -*- c-basic-offset: 2 -*- */
-/* Copyright(C) 2009-2012 Brazil
+/* Copyright(C) 2009-2015 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -15,25 +15,32 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "groonga_in.h"
+#include "grn.h"
+#include <stdlib.h>
#include <stdio.h>
-
-#ifndef __USE_GNU
-#define __USE_GNU /* O_DIRECT */
-#endif /* __USE_GNU */
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
-#include "ctx.h"
-#include "io.h"
-#include "plugin_in.h"
-#include "hash.h"
-#include "ctx_impl.h"
+#include "grn_ctx.h"
+#include "grn_io.h"
+#include "grn_plugin.h"
+#include "grn_hash.h"
+#include "grn_ctx_impl.h"
#define GRN_IO_IDSTR "GROONGA:IO:00001"
+#define GRN_IO_VERSION_DEFAULT 0
+
+#define GRN_IO_FILE_SIZE_V1 1073741824UL
+
+#ifdef WIN32
+# define GRN_IO_FILE_SIZE_V0 134217728L
+#else /* WIN32 */
+# define GRN_IO_FILE_SIZE_V0 GRN_IO_FILE_SIZE_V1
+#endif /* WIN32 */
+
#ifndef O_BINARY
# ifdef _O_BINARY
# define O_BINARY _O_BINARY
@@ -56,31 +63,42 @@ typedef struct _grn_io_fileinfo {
#define IO_HEADER_SIZE 64
-inline static grn_rc grn_open(grn_ctx *ctx, fileinfo *fi, const char *path, int flags, size_t maxsize);
+static uint32_t grn_io_version_default = GRN_IO_VERSION_DEFAULT;
+
+inline static grn_rc grn_open(grn_ctx *ctx, fileinfo *fi, const char *path, int flags);
inline static void grn_fileinfo_init(fileinfo *fis, int nfis);
inline static int grn_opened(fileinfo *fi);
inline static grn_rc grn_close(grn_ctx *ctx, fileinfo *fi);
-#if defined(WIN32) && defined(WIN32_FMO_EACH)
-inline static void * grn_mmap(grn_ctx *ctx, HANDLE *fmo, fileinfo *fi,
+#ifdef WIN32
+inline static void * grn_mmap(grn_ctx *ctx, grn_io *io,
+ HANDLE *fmo, fileinfo *fi,
off_t offset, size_t length);
-inline static int grn_munmap(grn_ctx *ctx, HANDLE *fmo, void *start, size_t length);
-#define GRN_MMAP(ctx,fmo,fi,offset,length)\
- (grn_mmap((ctx), (fmo), (fi), (offset), (length)))
-#define GRN_MUNMAP(ctx,fmo,start,length) (grn_munmap((ctx), (fmo), (start), (length)))
-#else /* defined(WIN32) && defined(WIN32_FMO_EACH) */
-inline static void * grn_mmap(grn_ctx *ctx, fileinfo *fi, off_t offset, size_t length);
-inline static int grn_munmap(grn_ctx *ctx, void *start, size_t length);
-#define GRN_MUNMAP(ctx,fmo,start,length) (grn_munmap((ctx), (start), (length)))
-#ifdef USE_FAIL_MALLOC
-inline static void * grn_fail_mmap(grn_ctx *ctx, fileinfo *fi,
+inline static int grn_munmap(grn_ctx *ctx, grn_io *io,
+ HANDLE *fmo, fileinfo *fi,
+ void *start, size_t length);
+# define GRN_MMAP(ctx,io,fmo,fi,offset,length)\
+ (grn_mmap((ctx), (io), (fmo), (fi), (offset), (length)))
+# define GRN_MUNMAP(ctx,io,fmo,fi,start,length)\
+ (grn_munmap((ctx), (io), (fmo), (fi), (start), (length)))
+#else /* WIN32 */
+inline static void * grn_mmap(grn_ctx *ctx, grn_io *io, fileinfo *fi,
+ off_t offset, size_t length);
+inline static int grn_munmap(grn_ctx *ctx, grn_io *io, fileinfo *fi,
+ void *start, size_t length);
+# define GRN_MUNMAP(ctx,io,fmo,fi,start,length) \
+ (grn_munmap((ctx), (io), (fi), (start), (length)))
+# ifdef USE_FAIL_MALLOC
+inline static void * grn_fail_mmap(grn_ctx *ctx, grn_io *io, fileinfo *fi,
off_t offset, size_t length,
const char* file, int line, const char *func);
-#define GRN_MMAP(ctx,fmo,fi,offset,length) \
- (grn_fail_mmap((ctx), (fi), (offset), (length), __FILE__, __LINE__, __FUNCTION__))
-#else /* USE_FAIL_MALLOC */
-#define GRN_MMAP(ctx,fmo,fi,offset,length) (grn_mmap((ctx), (fi), (offset), (length)))
-#endif /* USE_FAIL_MALLOC */
-#endif /* defined(WIN32) && defined(WIN32_FMO_EACH) */
+# define GRN_MMAP(ctx,io,fmo,fi,offset,length)\
+ (grn_fail_mmap((ctx), (io), (fi), (offset), (length),\
+ __FILE__, __LINE__, __FUNCTION__))
+# else /* USE_FAIL_MALLOC */
+# define GRN_MMAP(ctx,io,fmo,fi,offset,length)\
+ (grn_mmap((ctx), (io), (fi), (offset), (length)))
+# endif /* USE_FAIL_MALLOC */
+#endif /* WIN32 */
inline static int grn_msync(grn_ctx *ctx, void *start, size_t length);
inline static grn_rc grn_pread(grn_ctx *ctx, fileinfo *fi, void *buf, size_t count, off_t offset);
inline static grn_rc grn_pwrite(grn_ctx *ctx, fileinfo *fi, void *buf, size_t count, off_t offset);
@@ -88,6 +106,13 @@ inline static grn_rc grn_pwrite(grn_ctx *ctx, fileinfo *fi, void *buf, size_t co
grn_rc
grn_io_init(void)
{
+ const char *version_env;
+
+ version_env = getenv("GRN_IO_VERSION");
+ if (version_env) {
+ grn_io_version_default = atoi(version_env);
+ }
+
return GRN_SUCCESS;
}
@@ -97,17 +122,72 @@ grn_io_fin(void)
return GRN_SUCCESS;
}
+static inline uint32_t
+grn_io_compute_base(uint32_t header_size)
+{
+ uint32_t total_header_size;
+ total_header_size = IO_HEADER_SIZE + header_size;
+ return (total_header_size + grn_pagesize - 1) & ~(grn_pagesize - 1);
+}
+
+static inline uint32_t
+grn_io_compute_base_segment(uint32_t base, uint32_t segment_size)
+{
+ return (base + segment_size - 1) / segment_size;
+}
+
+static uint32_t
+grn_io_compute_max_n_files(uint32_t segment_size, uint32_t max_segment,
+ unsigned int base_segument, unsigned long file_size)
+{
+ uint64_t last_segment_end;
+ last_segment_end = ((uint64_t)segment_size) * (max_segment + base_segument);
+ return (uint32_t)((last_segment_end + file_size - 1) / file_size);
+}
+
+static inline unsigned long
+grn_io_compute_file_size(uint32_t version)
+{
+ if (version == 0) {
+ return GRN_IO_FILE_SIZE_V0;
+ } else {
+ return GRN_IO_FILE_SIZE_V1;
+ }
+}
+
+static inline uint32_t
+grn_io_max_segment(grn_io *io)
+{
+ if (io->header->segment_tail) {
+ return io->header->segment_tail;
+ } else {
+ return io->header->max_segment;
+ }
+}
+
+static uint32_t
+grn_io_max_n_files(grn_io *io)
+{
+ unsigned long file_size;
+
+ file_size = grn_io_compute_file_size(io->header->version);
+ return grn_io_compute_max_n_files(io->header->segment_size,
+ grn_io_max_segment(io),
+ io->base_seg,
+ file_size);
+}
+
grn_io *
grn_io_create_tmp(uint32_t header_size, uint32_t segment_size,
uint32_t max_segment, grn_io_mode mode, uint32_t flags)
{
grn_io *io;
- unsigned int b;
- uint32_t total_header_size;
+ uint32_t b;
struct _grn_io_header *header;
- total_header_size = IO_HEADER_SIZE + header_size;
- b = (total_header_size + grn_pagesize - 1) & ~(grn_pagesize - 1);
- if ((header = (struct _grn_io_header *)GRN_MMAP(&grn_gctx, NULL, NULL, 0, b))) {
+ b = grn_io_compute_base(header_size);
+ header = (struct _grn_io_header *)GRN_MMAP(&grn_gctx, NULL, NULL, NULL, 0, b);
+ if (header) {
+ header->version = grn_io_version_default;
header->header_size = header_size;
header->segment_size = segment_size;
header->max_segment = max_segment;
@@ -117,8 +197,7 @@ grn_io_create_tmp(uint32_t header_size, uint32_t segment_size,
memcpy(header->idstr, GRN_IO_IDSTR, 16);
if ((io = GRN_GMALLOCN(grn_io, 1))) {
grn_io_mapinfo *maps = NULL;
- if (((maps = GRN_GMALLOCN(grn_io_mapinfo, max_segment)) &&
- memset(maps, 0, sizeof(grn_io_mapinfo) * max_segment))) {
+ if ((maps = GRN_GCALLOC(sizeof(grn_io_mapinfo) * max_segment))) {
io->header = header;
io->user_header = (((byte *) header) + IO_HEADER_SIZE);
io->maps = maps;
@@ -138,7 +217,7 @@ grn_io_create_tmp(uint32_t header_size, uint32_t segment_size,
}
GRN_GFREE(io);
}
- GRN_MUNMAP(&grn_gctx, NULL, header, b);
+ GRN_MUNMAP(&grn_gctx, NULL, NULL, NULL, header, b);
}
return NULL;
}
@@ -187,23 +266,28 @@ grn_io_create(grn_ctx *ctx, const char *path, uint32_t header_size, uint32_t seg
{
grn_io *io;
fileinfo *fis;
- unsigned int b, max_nfiles;
- uint32_t bs, total_header_size;
+ uint32_t b, max_nfiles;
+ uint32_t bs;
struct _grn_io_header *header;
+ uint32_t version = grn_io_version_default;
+ unsigned long file_size;
+
if (!path) {
return grn_io_create_tmp(header_size, segment_size, max_segment, mode, flags);
}
if (!*path || (strlen(path) > PATH_MAX - 4)) { return NULL; }
- total_header_size = IO_HEADER_SIZE + header_size;
- b = (total_header_size + grn_pagesize - 1) & ~(grn_pagesize - 1);
- bs = (b + segment_size - 1) / segment_size;
- max_nfiles = (unsigned int)(
- ((uint64_t)segment_size * (max_segment + bs) + GRN_IO_FILE_SIZE - 1)
- / GRN_IO_FILE_SIZE);
+ b = grn_io_compute_base(header_size);
+ bs = grn_io_compute_base_segment(b, segment_size);
+ file_size = grn_io_compute_file_size(version);
+ max_nfiles = grn_io_compute_max_n_files(segment_size, max_segment,
+ bs, file_size);
if ((fis = GRN_GMALLOCN(fileinfo, max_nfiles))) {
grn_fileinfo_init(fis, max_nfiles);
- if (!grn_open(ctx, fis, path, O_RDWR|O_CREAT|O_EXCL, GRN_IO_FILE_SIZE)) {
- if ((header = (struct _grn_io_header *)GRN_MMAP(&grn_gctx, &fis->fmo, fis, 0, b))) {
+ if (!grn_open(ctx, fis, path, O_RDWR|O_CREAT|O_EXCL)) {
+ header = (struct _grn_io_header *)GRN_MMAP(&grn_gctx, NULL,
+ &fis->fmo, fis, 0, b);
+ if (header) {
+ header->version = version;
header->header_size = header_size;
header->segment_size = segment_size;
header->max_segment = max_segment;
@@ -214,8 +298,7 @@ grn_io_create(grn_ctx *ctx, const char *path, uint32_t header_size, uint32_t seg
grn_msync(ctx, header, b);
if ((io = GRN_GMALLOCN(grn_io, 1))) {
grn_io_mapinfo *maps = NULL;
- if (((maps = GRN_GMALLOCN(grn_io_mapinfo, max_segment)) &&
- memset(maps, 0, sizeof(grn_io_mapinfo) * max_segment))) {
+ if ((maps = GRN_GCALLOC(sizeof(grn_io_mapinfo) * max_segment))) {
strncpy(io->path, path, PATH_MAX);
io->header = header;
io->user_header = (((byte *) header) + IO_HEADER_SIZE);
@@ -236,7 +319,7 @@ grn_io_create(grn_ctx *ctx, const char *path, uint32_t header_size, uint32_t seg
}
GRN_GFREE(io);
}
- GRN_MUNMAP(&grn_gctx, &fis->fmo, header, b);
+ GRN_MUNMAP(&grn_gctx, NULL, &fis->fmo, fis, header, b);
}
grn_close(ctx, fis);
}
@@ -419,10 +502,9 @@ grn_io_open(grn_ctx *ctx, const char *path, grn_io_mode mode)
{
grn_io *io;
struct stat s;
- fileinfo *fis;
+ fileinfo fi;
uint32_t flags = 0;
- unsigned int b, max_nfiles;
- uint32_t total_header_size;
+ uint32_t b;
uint32_t header_size = 0, segment_size = 0, max_segment = 0, bs;
if (!path || !*path || (strlen(path) > PATH_MAX - 4)) { return NULL; }
{
@@ -444,17 +526,28 @@ grn_io_open(grn_ctx *ctx, const char *path, grn_io_mode mode)
GRN_CLOSE(fd);
if (!segment_size) { return NULL; }
}
- total_header_size = IO_HEADER_SIZE + header_size;
- b = (total_header_size + grn_pagesize - 1) & ~(grn_pagesize - 1);
- bs = (b + segment_size - 1) / segment_size;
- max_nfiles = (unsigned int)(
- ((uint64_t)segment_size * (max_segment + bs) + GRN_IO_FILE_SIZE - 1)
- / GRN_IO_FILE_SIZE);
- if (!(fis = GRN_GMALLOCN(fileinfo, max_nfiles))) { return NULL; }
- grn_fileinfo_init(fis, max_nfiles);
- if (!grn_open(ctx, fis, path, O_RDWR, GRN_IO_FILE_SIZE)) {
+ b = grn_io_compute_base(header_size);
+ bs = grn_io_compute_base_segment(b, segment_size);
+ grn_fileinfo_init(&fi, 1);
+ if (!grn_open(ctx, &fi, path, O_RDWR)) {
struct _grn_io_header *header;
- if ((header = GRN_MMAP(&grn_gctx, &fis->fmo, fis, 0, b))) {
+ header = GRN_MMAP(&grn_gctx, NULL, &(fi.fmo), &fi, 0, b);
+ if (header) {
+ unsigned long file_size;
+ unsigned int max_nfiles;
+ fileinfo *fis;
+
+ file_size = grn_io_compute_file_size(header->version);
+ max_nfiles = grn_io_compute_max_n_files(segment_size, max_segment,
+ bs, file_size);
+ fis = GRN_GMALLOCN(fileinfo, max_nfiles);
+ if (!fis) {
+ GRN_MUNMAP(&grn_gctx, NULL, &(fi.fmo), &fi, header, b);
+ grn_close(ctx, &fi);
+ return NULL;
+ }
+ grn_fileinfo_init(fis, max_nfiles);
+ memcpy(fis, &fi, sizeof(fileinfo));
if ((io = GRN_GMALLOC(sizeof(grn_io)))) {
grn_io_mapinfo *maps = NULL;
if ((maps = GRN_GCALLOC(sizeof(grn_io_mapinfo) * max_segment))) {
@@ -482,51 +575,57 @@ grn_io_open(grn_ctx *ctx, const char *path, grn_io_mode mode)
}
GRN_GFREE(io);
}
- GRN_MUNMAP(&grn_gctx, &fis->fmo, header, b);
+ GRN_GFREE(fis);
+ GRN_MUNMAP(&grn_gctx, NULL, &(fi.fmo), &fi, header, b);
}
- grn_close(ctx, fis);
+ grn_close(ctx, &fi);
}
- GRN_GFREE(fis);
return NULL;
}
grn_rc
grn_io_close(grn_ctx *ctx, grn_io *io)
{
- int i;
- grn_io_mapinfo *mi;
- fileinfo *fi;
- uint32_t bs = io->base_seg;
- uint32_t max_segment = io->header->segment_tail
- ? io->header->segment_tail : io->header->max_segment;
- uint32_t segment_size = io->header->segment_size;
- unsigned int max_nfiles = (unsigned int)(
- ((uint64_t)segment_size * (max_segment + bs) + GRN_IO_FILE_SIZE - 1)
- / GRN_IO_FILE_SIZE);
+ uint32_t max_nfiles;
+
+ max_nfiles = grn_io_max_n_files(io);
grn_io_unregister(io);
if (io->ainfo) { GRN_GFREE(io->ainfo); }
if (io->maps) {
- for (mi = io->maps, i = max_segment; i; mi++, i--) {
+ int i;
+ uint32_t max_segment;
+ uint32_t segment_size;
+ unsigned long file_size;
+ uint32_t segments_per_file;
+
+ max_segment = grn_io_max_segment(io);
+ segment_size = io->header->segment_size;
+ file_size = grn_io_compute_file_size(io->header->version);
+ segments_per_file = file_size / segment_size;
+ for (i = 0; i < max_segment; i++) {
+ grn_io_mapinfo *mi;
+ mi = &(io->maps[i]);
if (mi->map) {
+ fileinfo *fi = NULL;
/* if (atomic_read(mi->nref)) { return STILL_IN_USE ; } */
-#ifdef WIN32
- if ((io->flags & GRN_IO_TEMPORARY)) {
- GRN_GFREE(mi->map);
- } else
-#endif /* WIN32 */
- GRN_MUNMAP(&grn_gctx, &mi->fmo, mi->map, segment_size);
+ if (io->fis) {
+ uint32_t bseg = i + io->base_seg;
+ uint32_t fno = bseg / segments_per_file;
+ fi = &io->fis[fno];
+ }
+ GRN_MUNMAP(&grn_gctx, io, &mi->fmo, fi, mi->map, segment_size);
}
}
GRN_GFREE(io->maps);
}
-#ifdef WIN32
- if ((io->flags & GRN_IO_TEMPORARY)) {
- GRN_GFREE(io->header);
- } else
-#endif /* WIN32 */
- GRN_MUNMAP(&grn_gctx, &io->fis->fmo, io->header, io->base);
+ GRN_MUNMAP(&grn_gctx, io, (io->fis ? &io->fis->fmo : NULL),
+ io->fis, io->header, io->base);
if (io->fis) {
- for (fi = io->fis, i = max_nfiles; i; fi++, i--) { grn_close(ctx, fi); }
+ int i;
+ for (i = 0; i < max_nfiles; i++) {
+ fileinfo *fi = &(io->fis[i]);
+ grn_close(ctx, fi);
+ }
GRN_GFREE(io->fis);
}
GRN_GFREE(io);
@@ -590,14 +689,13 @@ grn_io_size(grn_ctx *ctx, grn_io *io, uint64_t *size)
uint64_t tsize = 0;
char buffer[PATH_MAX];
uint32_t nfiles;
+
if (io->header->curr_size) {
- nfiles = (uint32_t) ((io->header->curr_size + GRN_IO_FILE_SIZE - 1) / GRN_IO_FILE_SIZE);
+ unsigned long file_size;
+ file_size = grn_io_compute_file_size(io->header->version);
+ nfiles = (uint32_t) ((io->header->curr_size + file_size - 1) / file_size);
} else {
- uint32_t bs = io->base_seg;
- uint32_t max_segment = io->header->max_segment;
- uint32_t segment_size = io->header->segment_size;
- nfiles = (uint32_t) (((uint64_t)segment_size * (max_segment + bs) + GRN_IO_FILE_SIZE - 1)
- / GRN_IO_FILE_SIZE);
+ nfiles = grn_io_max_n_files(io);
}
for (fno = 0; fno < nfiles; fno++) {
gen_pathname(io->path, buffer, fno);
@@ -675,7 +773,8 @@ grn_io_read_ja(grn_io *io, grn_ctx *ctx, grn_io_ja_einfo *einfo, uint32_t epos,
{
uint32_t rest = 0, size = *value_len + sizeof(grn_io_ja_ehead);
uint32_t segment_size = io->header->segment_size;
- uint32_t segments_per_file = GRN_IO_FILE_SIZE / segment_size;
+ unsigned long file_size = grn_io_compute_file_size(io->header->version);
+ uint32_t segments_per_file = file_size / segment_size;
uint32_t bseg = segment + io->base_seg;
int fno = bseg / segments_per_file;
fileinfo *fi = &io->fis[fno];
@@ -687,14 +786,14 @@ grn_io_read_ja(grn_io *io, grn_ctx *ctx, grn_io_ja_einfo *einfo, uint32_t epos,
*value_len = 0;
return GRN_NO_MEMORY_AVAILABLE;
}
- if (pos + size > GRN_IO_FILE_SIZE) {
- rest = pos + size - GRN_IO_FILE_SIZE;
- size = GRN_IO_FILE_SIZE - pos;
+ if (pos + size > file_size) {
+ rest = pos + size - file_size;
+ size = file_size - pos;
}
if (!grn_opened(fi)) {
char path[PATH_MAX];
gen_pathname(io->path, path, fno);
- if (grn_open(ctx, fi, path, O_RDWR|O_CREAT, GRN_IO_FILE_SIZE)) {
+ if (grn_open(ctx, fi, path, O_RDWR|O_CREAT)) {
*value = NULL;
*value_len = 0;
GRN_FREE(v);
@@ -742,14 +841,14 @@ grn_io_read_ja(grn_io *io, grn_ctx *ctx, grn_io_ja_einfo *einfo, uint32_t epos,
if (!grn_opened(fi)) {
char path[PATH_MAX];
gen_pathname(io->path, path, fno);
- if (grn_open(ctx, fi, path, O_RDWR|O_CREAT, GRN_IO_FILE_SIZE)) {
+ if (grn_open(ctx, fi, path, O_RDWR|O_CREAT)) {
*value = NULL;
*value_len = 0;
GRN_FREE(v);
return ctx->rc;
}
}
- size = rest > GRN_IO_FILE_SIZE ? GRN_IO_FILE_SIZE : rest;
+ size = rest > file_size ? file_size : rest;
if (grn_pread(ctx, fi, vr, size, 0)) {
*value = NULL;
*value_len = 0;
@@ -771,20 +870,21 @@ grn_io_write_ja(grn_io *io, grn_ctx *ctx, uint32_t key,
grn_rc rc;
uint32_t rest = 0, size = value_len + sizeof(grn_io_ja_ehead);
uint32_t segment_size = io->header->segment_size;
- uint32_t segments_per_file = GRN_IO_FILE_SIZE / segment_size;
+ unsigned long file_size = grn_io_compute_file_size(io->header->version);
+ uint32_t segments_per_file = file_size / segment_size;
uint32_t bseg = segment + io->base_seg;
int fno = bseg / segments_per_file;
fileinfo *fi = &io->fis[fno];
off_t base = fno ? 0 : io->base - (uint64_t)segment_size * io->base_seg;
off_t pos = (uint64_t)segment_size * (bseg % segments_per_file) + offset + base;
- if (pos + size > GRN_IO_FILE_SIZE) {
- rest = pos + size - GRN_IO_FILE_SIZE;
- size = GRN_IO_FILE_SIZE - pos;
+ if (pos + size > file_size) {
+ rest = pos + size - file_size;
+ size = file_size - pos;
}
if (!grn_opened(fi)) {
char path[PATH_MAX];
gen_pathname(io->path, path, fno);
- if ((rc = grn_open(ctx, fi, path, O_RDWR|O_CREAT, GRN_IO_FILE_SIZE))) { return rc; }
+ if ((rc = grn_open(ctx, fi, path, O_RDWR|O_CREAT))) { return rc; }
}
if (value_len <= 256) {
ja_element je;
@@ -808,9 +908,9 @@ grn_io_write_ja(grn_io *io, grn_ctx *ctx, uint32_t key,
if (!grn_opened(fi)) {
char path[PATH_MAX];
gen_pathname(io->path, path, fno);
- if ((rc = grn_open(ctx, fi, path, O_RDWR|O_CREAT, GRN_IO_FILE_SIZE))) { return rc; }
+ if ((rc = grn_open(ctx, fi, path, O_RDWR|O_CREAT))) { return rc; }
}
- size = rest > GRN_IO_FILE_SIZE ? GRN_IO_FILE_SIZE : rest;
+ size = rest > file_size ? file_size : rest;
if ((rc = grn_pwrite(ctx, fi, vr, size, 0))) { return rc; }
vr += size;
rest -= size;
@@ -825,7 +925,8 @@ grn_io_write_ja_ehead(grn_io *io, grn_ctx *ctx, uint32_t key,
{
grn_rc rc;
uint32_t segment_size = io->header->segment_size;
- uint32_t segments_per_file = GRN_IO_FILE_SIZE / segment_size;
+ unsigned long file_size = grn_io_compute_file_size(io->header->version);
+ uint32_t segments_per_file = file_size / segment_size;
uint32_t bseg = segment + io->base_seg;
int fno = bseg / segments_per_file;
fileinfo *fi = &io->fis[fno];
@@ -834,7 +935,7 @@ grn_io_write_ja_ehead(grn_io *io, grn_ctx *ctx, uint32_t key,
if (!grn_opened(fi)) {
char path[PATH_MAX];
gen_pathname(io->path, path, fno);
- if ((rc = grn_open(ctx, fi, path, O_RDWR|O_CREAT, GRN_IO_FILE_SIZE))) { return rc; }
+ if ((rc = grn_open(ctx, fi, path, O_RDWR|O_CREAT))) { return rc; }
}
{
grn_io_ja_ehead eh;
@@ -848,148 +949,6 @@ void *
grn_io_win_map(grn_io *io, grn_ctx *ctx, grn_io_win *iw, uint32_t segment,
uint32_t offset, uint32_t size, grn_io_rw_mode mode)
{
- byte *p;
- off_t pos, base;
- int fno;
- uint32_t nseg, bseg;
- uint32_t segment_size = io->header->segment_size;
- uint32_t segments_per_file = GRN_IO_FILE_SIZE / segment_size;
- iw->ctx = ctx;
- iw->diff = 0;
- if (offset >= segment_size) {
- segment += offset / segment_size;
- offset = offset % segment_size;
- }
- nseg = (offset + size + segment_size - 1) / segment_size;
- bseg = segment + io->base_seg;
- fno = bseg / segments_per_file;
- base = fno ? 0 : io->base - (uint64_t)segment_size * io->base_seg;
- pos = (uint64_t)segment_size * (bseg % segments_per_file) + offset + base;
- if (!size || !io || segment + nseg > io->header->max_segment ||
- fno != (bseg + nseg - 1) / segments_per_file) {
- return NULL;
- }
- switch (mode) {
- case grn_io_rdonly:
- {
- fileinfo *fi = &io->fis[fno];
- if (!grn_opened(fi)) {
- char path[PATH_MAX];
- gen_pathname(io->path, path, fno);
- if (grn_open(ctx, fi, path, O_RDWR|O_CREAT, GRN_IO_FILE_SIZE)) {
- return NULL;
- }
- }
- if (!(p = GRN_MALLOC(size))) { return NULL; }
- if (grn_pread(ctx, fi, p, size, pos)) {
- GRN_FREE(p);
- return NULL;
- }
- iw->addr = p;
- }
- break;
- case grn_io_rdwr:
- // if (nseg > 1) { /* auto unmap is not implemented yet */
- if (nseg > 0) {
- fileinfo *fi = &io->fis[fno];
- if (!grn_opened(fi)) {
- char path[PATH_MAX];
- gen_pathname(io->path, path, fno);
- if (grn_open(ctx, fi, path, O_RDWR|O_CREAT, GRN_IO_FILE_SIZE)) {
- return NULL;
- }
- }
- if (!(p = GRN_MMAP(&grn_gctx, &iw->fmo, fi, pos, (uint64_t)segment_size * nseg))) {
- return NULL;
- }
- {
- uint64_t tail = io->base + (uint64_t)segment_size * segment + offset + size;
- if (tail > io->header->curr_size) { io->header->curr_size = tail; }
- }
- } else {
- GRN_LOG(ctx, GRN_LOG_ALERT, "nseg == 0! in grn_io_win_map(%p, %u, %u, %u)", io, segment, offset, size);
- // GRN_IO_SEG_REF(io, segment, p); if (!p) { return NULL; }
- return NULL;
- }
- iw->addr = p + offset;
- break;
- case grn_io_wronly:
- if (!(p = GRN_MALLOC(size))) { return NULL; }
- memset(p, 0, size);
- iw->cached = 0;
- iw->addr = p;
- break;
- default :
- return NULL;
- }
- iw->io = io;
- iw->mode = mode;
- iw->segment = segment;
- iw->offset = offset;
- iw->nseg = nseg;
- iw->size = size;
- iw->pos = pos;
- return iw->addr;
-}
-
-grn_rc
-grn_io_win_unmap(grn_io_win *iw)
-{
- grn_rc rc = GRN_SUCCESS;
- grn_io *io = iw->io;
- grn_ctx *ctx = iw->ctx;
- uint32_t segment_size = io->header->segment_size;
- uint32_t segments_per_file = GRN_IO_FILE_SIZE / segment_size;
- int nseg = iw->nseg;
- switch (iw->mode) {
- case grn_io_rdonly:
- if (iw->addr) { GRN_FREE(iw->addr); }
- iw->addr = NULL;
- break;
- case grn_io_rdwr:
- // if (nseg > 1) { /* auto unmap is not implemented yet */
- if (nseg > 0) {
- GRN_MUNMAP(&grn_gctx, &iw->fmo, ((byte *)iw->addr) - iw->offset, (uint64_t)segment_size * nseg);
- } else {
- if (iw->segment >= io->header->max_segment) {
- rc = GRN_INVALID_ARGUMENT;
- } else {
- //GRN_IO_SEG_UNREF(io, iw->segment);
- }
- }
- iw->addr = NULL;
- break;
- case grn_io_wronly:
- {
- int fno = (iw->segment + io->base_seg) / segments_per_file;
- fileinfo *fi = &io->fis[fno];
- if (!grn_opened(fi)) {
- char path[PATH_MAX];
- gen_pathname(io->path, path, fno);
- rc = grn_open(ctx, fi, path, O_RDWR|O_CREAT, GRN_IO_FILE_SIZE);
- }
- if (!rc) {
- if (!(rc = grn_pwrite(ctx, fi, iw->addr, iw->size, iw->pos))) {
- {
- uint64_t tail = io->base + (uint64_t)segment_size * iw->segment + iw->offset + iw->size;
- if (tail > io->header->curr_size) { io->header->curr_size = tail; }
- }
- if (!iw->cached) { GRN_FREE(iw->addr); }
- iw->addr = NULL;
- }
- }
- }
- break;
- default :
- rc = GRN_INVALID_ARGUMENT;
- }
- return rc;
-}
-
-void *
-grn_io_win_map2(grn_io *io, grn_ctx *ctx, grn_io_win *iw, uint32_t segment,
- uint32_t offset, uint32_t size, grn_io_rw_mode mode)
-{
uint32_t nseg, segment_size = io->header->segment_size;
if (offset >= segment_size) {
segment += offset / segment_size;
@@ -1043,7 +1002,7 @@ grn_io_win_map2(grn_io *io, grn_ctx *ctx, grn_io_win *iw, uint32_t segment,
}
grn_rc
-grn_io_win_unmap2(grn_io_win *iw)
+grn_io_win_unmap(grn_io_win *iw)
{
if (!iw || !iw->io ||!iw->ctx) { return GRN_INVALID_ARGUMENT; }
if (iw->cached) {
@@ -1081,7 +1040,7 @@ grn_io_win_unmap2(grn_io_win *iw)
}
#define DO_MAP(io,fmo,fi,pos,size,segno,res) do {\
- if (((res) = GRN_MMAP(&grn_gctx, (fmo), (fi), (pos), (size)))) {\
+ if (((res) = GRN_MMAP(&grn_gctx, (io), (fmo), (fi), (pos), (size)))) {\
uint32_t nmaps;\
if (io->max_map_seg < segno) { io->max_map_seg = segno; }\
GRN_ATOMIC_ADD_EX(&io->nmaps, 1, nmaps);\
@@ -1097,7 +1056,8 @@ grn_io_win_unmap2(grn_io_win *iw)
if ((io->flags & GRN_IO_TEMPORARY)) {\
DO_MAP(io, &info->fmo, NULL, 0, segment_size, segno, info->map);\
} else {\
- uint32_t segments_per_file = GRN_IO_FILE_SIZE / segment_size;\
+ unsigned long file_size = grn_io_compute_file_size(io->header->version);\
+ uint32_t segments_per_file = file_size / segment_size;\
uint32_t bseg = segno + io->base_seg;\
uint32_t fno = bseg / segments_per_file;\
off_t base = fno ? 0 : io->base - (uint64_t)segment_size * io->base_seg;\
@@ -1106,7 +1066,7 @@ grn_io_win_unmap2(grn_io_win *iw)
if (!grn_opened(fi)) {\
char path[PATH_MAX];\
gen_pathname(io->path, path, fno);\
- if (!grn_open(ctx, fi, path, O_RDWR|O_CREAT, GRN_IO_FILE_SIZE)) { \
+ if (!grn_open(ctx, fi, path, O_RDWR|O_CREAT)) { \
DO_MAP(io, &info->fmo, fi, pos, segment_size, segno, info->map);\
}\
} else {\
@@ -1151,7 +1111,9 @@ grn_io_seg_expire(grn_ctx *ctx, grn_io *io, uint32_t segno, uint32_t nretry)
}
} else {
uint32_t nmaps;
- GRN_MUNMAP(&grn_gctx, &info->fmo, info->map, io->header->segment_size);
+ fileinfo *fi = &(io->fis[segno]);
+ GRN_MUNMAP(&grn_gctx, io, &info->fmo, fi,
+ info->map, io->header->segment_size);
info->map = NULL;
GRN_ATOMIC_ADD_EX(pnref, -(GRN_IO_MAX_REF + 1), nref);
GRN_ATOMIC_ADD_EX(&io->nmaps, -1, nmaps);
@@ -1174,20 +1136,27 @@ grn_io_expire(grn_ctx *ctx, grn_io *io, int count_thresh, uint32_t limit)
uint32_t nref, nmaps, *pnref = &io->nref;
GRN_ATOMIC_ADD_EX(pnref, 1, nref);
if (!nref && grn_gtick - io->count > count_thresh) {
- uint32_t i = io->header->n_arrays;
- grn_io_mapinfo *info = io->maps;
- grn_io_array_spec *array_specs = (grn_io_array_spec *)io->user_header;
- while (i--) {
- memset(io->ainfo[i].addrs, 0, sizeof(void *) * array_specs[i].max_n_segments);
+ {
+ uint32_t i = io->header->n_arrays;
+ grn_io_array_spec *array_specs = (grn_io_array_spec *)io->user_header;
+ while (i--) {
+ memset(io->ainfo[i].addrs, 0, sizeof(void *) * array_specs[i].max_n_segments);
+ }
}
- for (m = io->max_map_seg; m; info++, m--) {
- if (info->map) {
- GRN_MUNMAP(&grn_gctx, &info->fmo, info->map, io->header->segment_size);
- info->map = NULL;
- info->nref = 0;
- info->count = grn_gtick;
- GRN_ATOMIC_ADD_EX(&io->nmaps, -1, nmaps);
- n++;
+ {
+ uint32_t fno;
+ for (fno = 0; fno < io->max_map_seg; fno++) {
+ grn_io_mapinfo *info = &(io->maps[fno]);
+ if (info->map) {
+ fileinfo *fi = &(io->fis[fno]);
+ GRN_MUNMAP(&grn_gctx, io, &info->fmo, fi,
+ info->map, io->header->segment_size);
+ info->map = NULL;
+ info->nref = 0;
+ info->count = grn_gtick;
+ GRN_ATOMIC_ADD_EX(&io->nmaps, -1, nmaps);
+ n++;
+ }
}
}
}
@@ -1207,7 +1176,8 @@ grn_io_expire(grn_ctx *ctx, grn_io *io, int count_thresh, uint32_t limit)
uint32_t nmaps, nref, *pnref = &info->nref;
GRN_ATOMIC_ADD_EX(pnref, 1, nref);
if (!nref && info->map && (grn_gtick - info->count) > count_thresh) {
- GRN_MUNMAP(&grn_gctx, &info->fmo, info->map, io->header->segment_size);
+ GRN_MUNMAP(&grn_gctx, io, &info->fmo, NULL,
+ info->map, io->header->segment_size);
GRN_ATOMIC_ADD_EX(&io->nmaps, -1, nmaps);
info->map = NULL;
info->count = grn_gtick;
@@ -1265,17 +1235,13 @@ grn_expire(grn_ctx *ctx, int count_thresh, uint32_t limit)
void *
grn_io_anon_map(grn_ctx *ctx, grn_io_mapinfo *mi, size_t length)
{
- return (mi->map = GRN_MMAP(ctx, &mi->fmo, NULL, 0, length));
+ return (mi->map = GRN_MMAP(ctx, NULL, &mi->fmo, NULL, 0, length));
}
void
grn_io_anon_unmap(grn_ctx *ctx, grn_io_mapinfo *mi, size_t length)
{
- /* support WIN32 */
-#ifdef WIN32
- return GRN_FREE(mi->map);
-#endif
- GRN_MUNMAP(ctx, &mi->fmo, mi->map, length);
+ GRN_MUNMAP(ctx, NULL, &mi->fmo, NULL, mi->map, length);
}
grn_rc
@@ -1345,59 +1311,25 @@ static size_t mmap_size = 0;
#ifdef WIN32
-#ifdef WIN32_FMO_EACH
-
inline static grn_rc
-grn_open(grn_ctx *ctx, fileinfo *fi, const char *path, int flags, size_t maxsize)
+grn_open_v1(grn_ctx *ctx, fileinfo *fi, const char *path, int flags)
{
- if ((flags & O_CREAT)) {
- DWORD dwCreationDisposition;
- if (flags & O_EXCL) {
- dwCreationDisposition = CREATE_NEW;
- } else {
- dwCreationDisposition = OPEN_ALWAYS;
- }
- fi->fh = CreateFile(path, GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
- dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, 0);
- if (fi->fh == INVALID_HANDLE_VALUE) {
- SERR("CreateFile");
- return ctx->rc;
- }
- goto exit;
- }
- if ((flags & O_TRUNC)) {
- CloseHandle(fi->fh);
- fi->fh = CreateFile(path, GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
- TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
- if (fi->fh == INVALID_HANDLE_VALUE) {
- SERR("CreateFile");
- return ctx->rc;
- }
- goto exit;
- }
- /* O_RDWR only */
- fi->fh = CreateFile(path, GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
- if (fi->fh == INVALID_HANDLE_VALUE) {
- SERR("CreateFile");
- return ctx->rc;
- }
-exit:
CRITICAL_SECTION_INIT(fi->cs);
return GRN_SUCCESS;
}
inline static void *
-grn_mmap(grn_ctx *ctx, HANDLE *fmo, fileinfo *fi, off_t offset, size_t length)
+grn_mmap_v1(grn_ctx *ctx, HANDLE *fmo, fileinfo *fi, off_t offset, size_t length)
{
void *res;
if (!fi) {
- if(fmo) {
- *fmo = (HANDLE)0;
+ if (fmo) {
+ *fmo = NULL;
}
+ /* TODO: Try to support VirtualAlloc() as anonymous mmap in POSIX.
+ * If VirtualAlloc() provides better performance rather than malloc(),
+ * we'll use it.
+ */
return GRN_GCALLOC(length);
}
/* CRITICAL_SECTION_ENTER(fi->cs); */
@@ -1406,7 +1338,10 @@ grn_mmap(grn_ctx *ctx, HANDLE *fmo, fileinfo *fi, off_t offset, size_t length)
if (!*fmo) { return NULL; }
res = MapViewOfFile(*fmo, FILE_MAP_WRITE, 0, (DWORD)offset, (SIZE_T)length);
if (!res) {
- MERR("MapViewOfFile failed #%d <%zu>", GetLastError(), mmap_size);
+ SERR("MapViewOfFile");
+ GRN_LOG(ctx, GRN_LOG_ERROR,
+ "MapViewOfFile(%lu,%" GRN_FMT_SIZE ") failed <%" GRN_FMT_SIZE ">",
+ (DWORD)offset, length, mmap_size);
return NULL;
}
/* CRITICAL_SECTION_LEAVE(fi->cs); */
@@ -1415,87 +1350,48 @@ grn_mmap(grn_ctx *ctx, HANDLE *fmo, fileinfo *fi, off_t offset, size_t length)
}
inline static int
-grn_munmap(grn_ctx *ctx, HANDLE *fmo, void *start, size_t length)
+grn_munmap_v1(grn_ctx *ctx, HANDLE *fmo, fileinfo *fi,
+ void *start, size_t length)
{
int r = 0;
+
+ if (!fi) {
+ GRN_GFREE(start);
+ return r;
+ }
+
if (!fmo) {
- GRN_FREE(start);
+ GRN_GFREE(start);
+ return r;
}
+
if (*fmo) {
if (UnmapViewOfFile(start)) {
mmap_size -= length;
} else {
SERR("UnmapViewOfFile");
- GRN_LOG(ctx, GRN_LOG_ERROR, "UnmapViewOfFile(%p,%d) failed <%zu>", start, length, mmap_size);
+ GRN_LOG(ctx, GRN_LOG_ERROR,
+ "UnmapViewOfFile(%p,%" GRN_FMT_SIZE ") failed <%" GRN_FMT_SIZE ">",
+ start, length, mmap_size);
r = -1;
}
if (!CloseHandle(*fmo)) {
SERR("CloseHandle");
- GRN_LOG(ctx, GRN_LOG_ERROR, "CloseHandle(%p,%d) failed <%zu>", start, length, mmap_size);
+ GRN_LOG(ctx, GRN_LOG_ERROR,
+ "CloseHandle(%p,%" GRN_FMT_SIZE ") failed <%" GRN_FMT_SIZE ">",
+ start, length, mmap_size);
}
*fmo = NULL;
} else {
- GRN_FREE(start);
+ GRN_GFREE(start);
}
- return r;
-}
-inline static grn_rc
-grn_close(grn_ctx *ctx, fileinfo *fi)
-{
- if (fi->fmo != NULL) {
- GRN_LOG(ctx, GRN_LOG_ALERT, "file mapping object exists");
- }
- if (fi->fh != INVALID_HANDLE_VALUE) {
- CloseHandle(fi->fh);
- CRITICAL_SECTION_FIN(fi->cs);
- fi->fh = INVALID_HANDLE_VALUE;
- }
- return GRN_SUCCESS;
+ return r;
}
-#else /* WIN32_FMO_EACH */
inline static grn_rc
-grn_open(grn_ctx *ctx, fileinfo *fi, const char *path, int flags, size_t maxsize)
+grn_open_v0(grn_ctx *ctx, fileinfo *fi, const char *path, int flags)
{
- /* may be wrong if flags is just only O_RDWR */
- if ((flags & O_CREAT)) {
- DWORD dwCreationDisposition;
- if (flags & O_EXCL) {
- dwCreationDisposition = CREATE_NEW;
- } else {
- dwCreationDisposition = OPEN_ALWAYS;
- }
- fi->fh = CreateFile(path, GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
- dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, 0);
- if (fi->fh == INVALID_HANDLE_VALUE) {
- SERR("CreateFile");
- return ctx->rc;
- }
- goto exit;
- }
- if ((flags & O_TRUNC)) {
- CloseHandle(fi->fh);
- /* unable to assign OPEN_ALWAYS and TRUNCATE_EXISTING at once */
- fi->fh = CreateFile(path, GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
- TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
- if (fi->fh == INVALID_HANDLE_VALUE) {
- SERR("CreateFile");
- return ctx->rc;
- }
- goto exit;
- }
- /* O_RDWR only */
- fi->fh = CreateFile(path, GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
- if (fi->fh == INVALID_HANDLE_VALUE) {
- SERR("CreateFile");
- return ctx->rc;
- }
-exit:
/* signature may be wrong.. */
fi->fmo = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, NULL);
/* open failed */
@@ -1506,20 +1402,21 @@ exit:
/* failed again */
if (fi->fmo == NULL) {
/* try to create fmo */
- fi->fmo = CreateFileMapping(fi->fh, NULL, PAGE_READWRITE, 0, GRN_IO_FILE_SIZE, NULL);
+ fi->fmo = CreateFileMapping(fi->fh, NULL, PAGE_READWRITE, 0, GRN_IO_FILE_SIZE_V0, NULL);
}
// funlock
}
if (fi->fmo != NULL) {
- if (GetLastError() != ERROR_ALREADY_EXISTS ) {
+ if (GetLastError() != ERROR_ALREADY_EXISTS) {
CRITICAL_SECTION_INIT(fi->cs);
return GRN_SUCCESS;
} else {
- GRN_LOG(ctx, GRN_LOG_ERROR, "fmo object already exists! handle=%d", fi->fh);
+ GRN_LOG(ctx, GRN_LOG_ERROR, "fmo object already exists! handle=%p", fi->fh);
CloseHandle(fi->fmo);
}
} else {
- GRN_LOG(ctx, GRN_LOG_ALERT, "failed to get FileMappingObject #%d", GetLastError());
+ GRN_LOG(ctx, GRN_LOG_ALERT,
+ "failed to get FileMappingObject #%lu", GetLastError());
}
CloseHandle(fi->fh);
SERR("OpenFileMapping");
@@ -1527,11 +1424,11 @@ exit:
}
inline static void *
-grn_mmap(grn_ctx *ctx, fileinfo *fi, off_t offset, size_t length)
+grn_mmap_v0(grn_ctx *ctx, fileinfo *fi, off_t offset, size_t length)
{
void *res;
if (!fi) { return GRN_GCALLOC(length); }
- /* file must be exceeded to GRN_IO_FILE_SIZE when FileMappingObject created.
+ /* file must be exceeded to GRN_IO_FILE_SIZE_V0 when FileMappingObject created.
and, after fmo created, it's not allowed to expand the size of file.
DWORD tail = (DWORD)(offset + length);
DWORD filesize = GetFileSize(fi->fh, NULL);
@@ -1549,7 +1446,8 @@ grn_mmap(grn_ctx *ctx, fileinfo *fi, off_t offset, size_t length)
*/
res = MapViewOfFile(fi->fmo, FILE_MAP_WRITE, 0, (DWORD)offset, (SIZE_T)length);
if (!res) {
- MERR("MapViewOfFile failed #%d <%zu>", GetLastError(), mmap_size);
+ MERR("MapViewOfFile failed: <%" GRN_FMT_SIZE ">: %s",
+ mmap_size, grn_current_error_message());
return NULL;
}
mmap_size += length;
@@ -1557,19 +1455,149 @@ grn_mmap(grn_ctx *ctx, fileinfo *fi, off_t offset, size_t length)
}
inline static int
-grn_munmap(grn_ctx *ctx, void *start, size_t length)
+grn_munmap_v0(grn_ctx *ctx, fileinfo *fi, void *start, size_t length)
{
+ if (!fi) {
+ GRN_GFREE(start);
+ return 0;
+ }
+
if (UnmapViewOfFile(start)) {
mmap_size -= length;
return 0;
} else {
SERR("UnmapViewOfFile");
- GRN_LOG(ctx, GRN_LOG_ERROR, "UnmapViewOfFile(%p,%d) failed <%zu>", start, length, mmap_size);
+ GRN_LOG(ctx, GRN_LOG_ERROR,
+ "UnmapViewOfFile(%p,%" GRN_FMT_SIZE ") failed <%" GRN_FMT_SIZE ">",
+ start, length, mmap_size);
return -1;
}
}
inline static grn_rc
+grn_open_common(grn_ctx *ctx, fileinfo *fi, const char *path, int flags)
+{
+ /* may be wrong if flags is just only O_RDWR */
+ if ((flags & O_CREAT)) {
+ DWORD dwCreationDisposition;
+ if (flags & O_EXCL) {
+ dwCreationDisposition = CREATE_NEW;
+ } else {
+ dwCreationDisposition = OPEN_ALWAYS;
+ }
+ fi->fh = CreateFile(path, GRN_IO_FILE_CREATE_MODE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, 0);
+ if (fi->fh == INVALID_HANDLE_VALUE) {
+ SERR("CreateFile");
+ goto exit;
+ }
+ goto exit;
+ }
+ if ((flags & O_TRUNC)) {
+ CloseHandle(fi->fh);
+ /* unable to assign OPEN_ALWAYS and TRUNCATE_EXISTING at once */
+ fi->fh = CreateFile(path, GRN_IO_FILE_CREATE_MODE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+ if (fi->fh == INVALID_HANDLE_VALUE) {
+ SERR("CreateFile");
+ goto exit;
+ }
+ goto exit;
+ }
+ /* O_RDWR only */
+ fi->fh = CreateFile(path, GRN_IO_FILE_CREATE_MODE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+ if (fi->fh == INVALID_HANDLE_VALUE) {
+ SERR("CreateFile");
+ goto exit;
+ }
+
+exit :
+ return ctx->rc;
+}
+
+inline static grn_rc
+grn_open(grn_ctx *ctx, fileinfo *fi, const char *path, int flags)
+{
+ grn_rc rc;
+ struct _grn_io_header io_header;
+ DWORD header_size;
+ DWORD read_bytes;
+ int version = grn_io_version_default;
+
+ rc = grn_open_common(ctx, fi, path, flags);
+ if (rc != GRN_SUCCESS) {
+ return rc;
+ }
+
+ if (!(flags & O_CREAT)) {
+ header_size = sizeof(struct _grn_io_header);
+ ReadFile(fi->fh, &io_header, header_size, &read_bytes, NULL);
+ if (read_bytes == header_size) {
+ version = io_header.version;
+ }
+ SetFilePointer(fi->fh, 0, NULL, FILE_BEGIN);
+ }
+
+ if (version == 0) {
+ return grn_open_v0(ctx, fi, path, flags);
+ } else {
+ return grn_open_v1(ctx, fi, path, flags);
+ }
+}
+
+inline static int
+grn_guess_io_version(grn_ctx *ctx, grn_io *io, fileinfo *fi)
+{
+ if (io) {
+ return io->header->version;
+ }
+
+ if (fi) {
+ if (fi->fmo) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+
+ return grn_io_version_default;
+}
+
+inline static void *
+grn_mmap(grn_ctx *ctx, grn_io *io, HANDLE *fmo,
+ fileinfo *fi, off_t offset, size_t length)
+{
+ int version;
+
+ version = grn_guess_io_version(ctx, io, fi);
+
+ if (version == 0) {
+ return grn_mmap_v0(ctx, fi, offset, length);
+ } else {
+ return grn_mmap_v1(ctx, fmo, fi, offset, length);
+ }
+}
+
+inline static int
+grn_munmap(grn_ctx *ctx, grn_io *io,
+ HANDLE *fmo, fileinfo *fi, void *start, size_t length)
+{
+ int version;
+
+ version = grn_guess_io_version(ctx, io, fi);
+
+ if (version == 0) {
+ return grn_munmap_v0(ctx, fi, start, length);
+ } else {
+ return grn_munmap_v1(ctx, fmo, fi, start, length);
+ }
+}
+
+inline static grn_rc
grn_close(grn_ctx *ctx, fileinfo *fi)
{
if (fi->fmo != NULL) {
@@ -1583,7 +1611,6 @@ grn_close(grn_ctx *ctx, fileinfo *fi)
}
return GRN_SUCCESS;
}
-#endif /* WIN32_FMO_EACH */
inline static void
grn_fileinfo_init(fileinfo *fis, int nfis)
@@ -1620,7 +1647,9 @@ grn_pread(grn_ctx *ctx, fileinfo *fi, void *buf, size_t count, off_t offset)
SERR("ReadFile");
} else if (len != count) {
/* todo : should retry ? */
- ERR(GRN_INPUT_OUTPUT_ERROR, "ReadFile %d != %d", count, len);
+ ERR(GRN_INPUT_OUTPUT_ERROR,
+ "ReadFile %" GRN_FMT_SIZE " != %lu",
+ count, len);
}
}
CRITICAL_SECTION_LEAVE(fi->cs);
@@ -1640,7 +1669,9 @@ grn_pwrite(grn_ctx *ctx, fileinfo *fi, void *buf, size_t count, off_t offset)
SERR("WriteFile");
} else if (len != count) {
/* todo : should retry ? */
- ERR(GRN_INPUT_OUTPUT_ERROR, "WriteFile %d != %d", count, len);
+ ERR(GRN_INPUT_OUTPUT_ERROR,
+ "WriteFile %" GRN_FMT_SIZE " != %lu",
+ count, len);
}
}
CRITICAL_SECTION_LEAVE(fi->cs);
@@ -1650,10 +1681,10 @@ grn_pwrite(grn_ctx *ctx, fileinfo *fi, void *buf, size_t count, off_t offset)
#else /* WIN32 */
inline static grn_rc
-grn_open(grn_ctx *ctx, fileinfo *fi, const char *path, int flags, size_t maxsize)
+grn_open(grn_ctx *ctx, fileinfo *fi, const char *path, int flags)
{
struct stat st;
- if ((fi->fd = GRN_OPEN(path, flags, 0666)) == -1) {
+ if ((fi->fd = GRN_OPEN(path, flags, GRN_IO_FILE_CREATE_MODE)) == -1) {
SERR(path);
return ctx->rc;
}
@@ -1698,7 +1729,7 @@ grn_close(grn_ctx *ctx, fileinfo *fi)
#include <sys/mman.h>
inline static void *
-grn_mmap(grn_ctx *ctx, fileinfo *fi, off_t offset, size_t length)
+grn_mmap(grn_ctx *ctx, grn_io *io, fileinfo *fi, off_t offset, size_t length)
{
void *res;
int fd, flags;
@@ -1728,13 +1759,15 @@ grn_mmap(grn_ctx *ctx, fileinfo *fi, off_t offset, size_t length)
#ifdef USE_FAIL_MALLOC
inline static void *
-grn_fail_mmap(grn_ctx *ctx, fileinfo *fi, off_t offset, size_t length,
+grn_fail_mmap(grn_ctx *ctx, grn_io *io, fileinfo *fi,
+ off_t offset, size_t length,
const char* file, int line, const char *func)
{
if (grn_fail_malloc_check(length, file, line, func)) {
return grn_mmap(ctx, fi, offset, length);
} else {
- MERR("fail_mmap(%zu,%d,%" GRN_FMT_LLU ") (%s:%d@%s) <%zu>",
+ MERR("fail_mmap(%" GRN_FMT_SIZE ",%d,%" GRN_FMT_LLU ") "
+ "(%s:%d@%s) <%" GRN_FMT_SIZE ">",
length, fi ? fi->fd : 0, offset, file, line, func, mmap_size);
return NULL;
}
@@ -1750,7 +1783,7 @@ grn_msync(grn_ctx *ctx, void *start, size_t length)
}
inline static int
-grn_munmap(grn_ctx *ctx, void *start, size_t length)
+grn_munmap(grn_ctx *ctx, grn_io *io, fileinfo *fi, void *start, size_t length)
{
int res;
res = munmap(start, length);
diff --git a/storage/mroonga/vendor/groonga/lib/mrb.c b/storage/mroonga/vendor/groonga/lib/mrb.c
index f05949cef98..4d1e4b5a218 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb.c
+++ b/storage/mroonga/vendor/groonga/lib/mrb.c
@@ -16,8 +16,9 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "mrb.h"
-#include "ctx_impl.h"
+#include "grn_mrb.h"
+#include "grn_ctx_impl.h"
+#include "grn_util.h"
#ifdef GRN_WITH_MRUBY
# include <mruby/proc.h>
@@ -25,19 +26,21 @@
# include <mruby/string.h>
#endif
+#include <ctype.h>
+
#define BUFFER_SIZE 2048
+#define E_LOAD_ERROR (mrb_class_get(mrb, "LoadError"))
#ifdef GRN_WITH_MRUBY
-#ifdef WIN32
+# ifdef WIN32
static char *win32_ruby_scripts_dir = NULL;
static char win32_ruby_scripts_dir_buffer[PATH_MAX];
static const char *
-grn_mrb_get_system_ruby_scripts_dir(void)
+grn_mrb_get_default_system_ruby_scripts_dir(void)
{
if (!win32_ruby_scripts_dir) {
const char *base_dir;
const char *relative_path = GRN_RELATIVE_RUBY_SCRIPTS_DIR;
- char *path;
size_t base_dir_length;
base_dir = grn_win32_base_dir();
@@ -50,13 +53,40 @@ grn_mrb_get_system_ruby_scripts_dir(void)
return win32_ruby_scripts_dir;
}
-#else /* WIN32 */
+# else /* WIN32 */
static const char *
-grn_mrb_get_system_ruby_scripts_dir(void)
+grn_mrb_get_default_system_ruby_scripts_dir(void)
{
return GRN_RUBY_SCRIPTS_DIR;
}
-#endif /* WIN32 */
+# endif /* WIN32 */
+
+const char *
+grn_mrb_get_system_ruby_scripts_dir(grn_ctx *ctx)
+{
+ const char *ruby_scripts_dir;
+
+ ruby_scripts_dir = getenv("GRN_RUBY_SCRIPTS_DIR");
+ if (!ruby_scripts_dir) {
+ ruby_scripts_dir = grn_mrb_get_default_system_ruby_scripts_dir();
+ }
+
+ return ruby_scripts_dir;
+}
+
+static grn_bool
+grn_mrb_is_absolute_path(const char *path)
+{
+ if (path[0] == '/') {
+ return GRN_TRUE;
+ }
+
+ if (isalpha(path[0]) && path[1] == ':' && path[2] == '/') {
+ return GRN_TRUE;
+ }
+
+ return GRN_FALSE;
+}
static grn_bool
grn_mrb_expand_script_path(grn_ctx *ctx, const char *path, char *expanded_path)
@@ -65,13 +95,13 @@ grn_mrb_expand_script_path(grn_ctx *ctx, const char *path, char *expanded_path)
char dir_last_char;
int path_length, max_path_length;
- if (path[0] == '/') {
+ if (grn_mrb_is_absolute_path(path)) {
expanded_path[0] = '\0';
+ } else if (path[0] == '.' && path[1] == '/') {
+ strcpy(expanded_path, ctx->impl->mrb.base_directory);
+ strcat(expanded_path, "/");
} else {
- ruby_scripts_dir = getenv("GRN_RUBY_SCRIPTS_DIR");
- if (!ruby_scripts_dir) {
- ruby_scripts_dir = grn_mrb_get_system_ruby_scripts_dir();
- }
+ ruby_scripts_dir = grn_mrb_get_system_ruby_scripts_dir(ctx);
strcpy(expanded_path, ruby_scripts_dir);
dir_last_char = ruby_scripts_dir[strlen(expanded_path) - 1];
@@ -120,25 +150,39 @@ grn_mrb_load(grn_ctx *ctx, const char *path)
snprintf(message, BUFFER_SIZE - 1,
"fopen: failed to open mruby script file: <%s>", expanded_path);
SERR(message);
- exception = mrb_exc_new(mrb, E_ARGUMENT_ERROR,
+ exception = mrb_exc_new(mrb, E_LOAD_ERROR,
ctx->errbuf, strlen(ctx->errbuf));
mrb->exc = mrb_obj_ptr(exception);
return mrb_nil_value();
}
- parser = mrb_parser_new(mrb);
- mrb_parser_set_filename(parser, expanded_path);
- parser->s = parser->send = NULL;
- parser->f = file;
- mrb_parser_parse(parser, NULL);
- fclose(file);
-
{
- struct RProc *proc;
- proc = mrb_generate_code(mrb, parser);
- result = mrb_toplevel_run(mrb, proc);
+ char current_base_directory[PATH_MAX];
+ char *last_directory;
+
+ strcpy(current_base_directory, data->base_directory);
+ strcpy(data->base_directory, expanded_path);
+ last_directory = strrchr(data->base_directory, '/');
+ if (last_directory) {
+ last_directory[0] = '\0';
+ }
+
+ parser = mrb_parser_new(mrb);
+ mrb_parser_set_filename(parser, expanded_path);
+ parser->s = parser->send = NULL;
+ parser->f = file;
+ mrb_parser_parse(parser, NULL);
+ fclose(file);
+
+ {
+ struct RProc *proc;
+ proc = mrb_generate_code(mrb, parser);
+ result = mrb_toplevel_run(mrb, proc);
+ }
+ mrb_parser_free(parser);
+
+ strcpy(data->base_directory, current_base_directory);
}
- mrb_parser_free(parser);
return result;
}
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.c
index a350c6b04f3..bd288af8491 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.c
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.c
@@ -16,7 +16,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "../ctx_impl.h"
+#include "../grn_ctx_impl.h"
#ifdef GRN_WITH_MRUBY
#include <mruby.h>
@@ -24,7 +24,7 @@
#include <mruby/variable.h>
#include <mruby/data.h>
-#include "../db.h"
+#include "../grn_db.h"
#include "mrb_accessor.h"
static struct mrb_data_type mrb_grn_accessor_type = {
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.h
index 2aaf32f48f9..7b27e6375ec 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.h
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.h
@@ -19,8 +19,8 @@
#ifndef GRN_MRB_ACCESSOR_H
#define GRN_MRB_ACCESSOR_H
-#include "../ctx.h"
-#include "../db.h"
+#include "../grn_ctx.h"
+#include "../grn_db.h"
#ifdef __cplusplus
extern "C" {
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_array.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_array.c
new file mode 100644
index 00000000000..f19bcfa9563
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_array.c
@@ -0,0 +1,60 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "../grn_ctx_impl.h"
+
+#ifdef GRN_WITH_MRUBY
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/data.h>
+
+#include "mrb_array.h"
+
+static struct mrb_data_type mrb_grn_array_type = {
+ "Groonga::Array",
+ NULL
+};
+
+static mrb_value
+mrb_grn_array_initialize(mrb_state *mrb, mrb_value self)
+{
+ mrb_value mrb_array_ptr;
+
+ mrb_get_args(mrb, "o", &mrb_array_ptr);
+ DATA_TYPE(self) = &mrb_grn_array_type;
+ DATA_PTR(self) = mrb_cptr(mrb_array_ptr);
+ return self;
+}
+
+void
+grn_mrb_array_init(grn_ctx *ctx)
+{
+ grn_mrb_data *data = &(ctx->impl->mrb);
+ mrb_state *mrb = data->state;
+ struct RClass *module = data->module;
+ struct RClass *table_class;
+ struct RClass *klass;
+
+ table_class = mrb_class_get_under(mrb, module, "Table");
+ klass = mrb_define_class_under(mrb, module, "Array", table_class);
+ MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA);
+
+ mrb_define_method(mrb, klass, "initialize",
+ mrb_grn_array_initialize, MRB_ARGS_REQ(1));
+}
+#endif
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_array.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_array.h
new file mode 100644
index 00000000000..062281684ee
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_array.h
@@ -0,0 +1,34 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef GRN_MRB_ARRAY_H
+#define GRN_MRB_ARRAY_H
+
+#include "../grn_ctx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void grn_mrb_array_init(grn_ctx *ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRN_MRB_ARRAY_H */
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.c
index ad428ea5bde..2a304b68781 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.c
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.c
@@ -16,7 +16,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "../ctx_impl.h"
+#include "../grn_ctx_impl.h"
#ifdef GRN_WITH_MRUBY
#include <mruby.h>
@@ -24,8 +24,9 @@
#include <mruby/variable.h>
#include <mruby/data.h>
#include <mruby/numeric.h>
+#include <mruby/string.h>
-#include "../db.h"
+#include "../grn_db.h"
#include "mrb_bulk.h"
static struct mrb_data_type mrb_grn_bulk_type = {
@@ -33,33 +34,62 @@ static struct mrb_data_type mrb_grn_bulk_type = {
NULL
};
-static mrb_value
-mrb_grn_bulk_initialize(mrb_state *mrb, mrb_value self)
+grn_obj *
+grn_mrb_value_to_bulk(mrb_state *mrb, mrb_value mrb_value_, grn_obj *bulk)
{
- mrb_value mrb_bulk_ptr;
-
- mrb_get_args(mrb, "o", &mrb_bulk_ptr);
- DATA_TYPE(self) = &mrb_grn_bulk_type;
- DATA_PTR(self) = mrb_cptr(mrb_bulk_ptr);
- return self;
-}
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+
+ switch (mrb_type(mrb_value_)) {
+ case MRB_TT_FALSE :
+ if (mrb_nil_p(mrb_value_)) {
+ grn_obj_reinit(ctx, bulk, GRN_DB_VOID, 0);
+ } else {
+ grn_obj_reinit(ctx, bulk, GRN_DB_BOOL, 0);
+ GRN_BOOL_SET(ctx, bulk, GRN_FALSE);
+ }
+ break;
+ case MRB_TT_TRUE :
+ grn_obj_reinit(ctx, bulk, GRN_DB_BOOL, 0);
+ GRN_BOOL_SET(ctx, bulk, GRN_TRUE);
+ break;
+ case MRB_TT_FIXNUM :
+ grn_obj_reinit(ctx, bulk, GRN_DB_INT64, 0);
+ GRN_INT64_SET(ctx, bulk, mrb_fixnum(mrb_value_));
+ break;
+ case MRB_TT_SYMBOL :
+ {
+ const char *name;
+ mrb_int name_length;
-static mrb_value
-mrb_grn_bulk_get_domain(mrb_state *mrb, mrb_value self)
-{
- grn_obj *bulk;
+ grn_obj_reinit(ctx, bulk, GRN_DB_TEXT, 0);
+ name = mrb_sym2name_len(mrb, mrb_symbol(mrb_value_), &name_length);
+ GRN_TEXT_SET(ctx, bulk, name, name_length);
+ }
+ break;
+ case MRB_TT_FLOAT :
+ grn_obj_reinit(ctx, bulk, GRN_DB_FLOAT, 0);
+ GRN_FLOAT_SET(ctx, bulk, mrb_float(mrb_value_));
+ break;
+ case MRB_TT_STRING :
+ grn_obj_reinit(ctx, bulk, GRN_DB_TEXT, 0);
+ GRN_TEXT_SET(ctx, bulk, RSTRING_PTR(mrb_value_), RSTRING_LEN(mrb_value_));
+ break;
+ default :
+ mrb_raisef(mrb, E_ARGUMENT_ERROR,
+ "unsupported object to convert to bulk: %S",
+ mrb_value_);
+ break;
+ }
- bulk = DATA_PTR(self);
- return mrb_fixnum_value(bulk->header.domain);
+ return bulk;
}
-static mrb_value
-mrb_grn_bulk_get_value(mrb_state *mrb, mrb_value self)
+mrb_value
+grn_mrb_value_from_bulk(mrb_state *mrb, grn_obj *bulk)
{
- grn_obj *bulk;
mrb_value mrb_value_;
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
- bulk = DATA_PTR(self);
switch (bulk->header.domain) {
case GRN_DB_INT32 :
{
@@ -81,11 +111,26 @@ mrb_grn_bulk_get_value(mrb_state *mrb, mrb_value self)
mrb_value_ = mrb_fixnum_value(value);
}
break;
+ case GRN_DB_TIME :
+ {
+ int64_t value;
+ int32_t sec;
+ int32_t usec;
+
+ value = GRN_TIME_VALUE(bulk);
+ GRN_TIME_UNPACK(value, sec, usec);
+ mrb_value_ = mrb_funcall(mrb,
+ mrb_obj_value(ctx->impl->mrb.builtin.time_class),
+ "at",
+ 2,
+ mrb_fixnum_value(sec),
+ mrb_fixnum_value(usec));
+ }
+ break;
default :
{
#define MESSAGE_SIZE 4096
char message[MESSAGE_SIZE];
- grn_ctx *ctx = (grn_ctx *)mrb->ud;
grn_obj *domain;
char domain_name[GRN_TABLE_MAX_KEY_SIZE];
int domain_name_size;
@@ -114,6 +159,32 @@ mrb_grn_bulk_get_value(mrb_state *mrb, mrb_value self)
}
static mrb_value
+mrb_grn_bulk_initialize(mrb_state *mrb, mrb_value self)
+{
+ mrb_value mrb_bulk_ptr;
+
+ mrb_get_args(mrb, "o", &mrb_bulk_ptr);
+ DATA_TYPE(self) = &mrb_grn_bulk_type;
+ DATA_PTR(self) = mrb_cptr(mrb_bulk_ptr);
+ return self;
+}
+
+static mrb_value
+mrb_grn_bulk_get_domain(mrb_state *mrb, mrb_value self)
+{
+ grn_obj *bulk;
+
+ bulk = DATA_PTR(self);
+ return mrb_fixnum_value(bulk->header.domain);
+}
+
+static mrb_value
+mrb_grn_bulk_get_value(mrb_state *mrb, mrb_value self)
+{
+ return grn_mrb_value_from_bulk(mrb, DATA_PTR(self));
+}
+
+static mrb_value
mrb_grn_bulk_equal(mrb_state *mrb, mrb_value self)
{
mrb_value mrb_other;
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.h
index 3be86584dc6..e85b81568da 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.h
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.h
@@ -1,6 +1,6 @@
/* -*- c-basic-offset: 2 -*- */
/*
- Copyright(C) 2014 Brazil
+ Copyright(C) 2014-2015 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -19,8 +19,8 @@
#ifndef GRN_MRB_BULK_H
#define GRN_MRB_BULK_H
-#include "../ctx.h"
-#include "../db.h"
+#include "../grn_ctx.h"
+#include "../grn_db.h"
#ifdef __cplusplus
extern "C" {
@@ -28,6 +28,11 @@ extern "C" {
void grn_mrb_bulk_init(grn_ctx *ctx);
+mrb_value grn_mrb_value_from_bulk(mrb_state *mrb, grn_obj *bulk);
+grn_obj *grn_mrb_value_to_bulk(mrb_state *mrb,
+ mrb_value mrb_value_,
+ grn_obj *bulk);
+
#ifdef __cplusplus
}
#endif
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_column.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_column.c
index 545f070d91c..1d3bbb69422 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_column.c
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_column.c
@@ -1,6 +1,6 @@
/* -*- c-basic-offset: 2 -*- */
/*
- Copyright(C) 2013 Brazil
+ Copyright(C) 2013-2014 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -16,13 +16,42 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "../ctx_impl.h"
+#include "../grn_ctx_impl.h"
#ifdef GRN_WITH_MRUBY
#include <mruby.h>
#include <mruby/class.h>
+#include <mruby/data.h>
+#include "mrb_ctx.h"
#include "mrb_column.h"
+#include "mrb_converter.h"
+
+static mrb_value
+mrb_grn_column_is_locked(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ unsigned int is_locked;
+
+ is_locked = grn_obj_is_locked(ctx, DATA_PTR(self));
+ grn_mrb_ctx_check(mrb);
+
+ return mrb_bool_value(is_locked != 0);
+}
+
+static mrb_value
+mrb_grn_column_get_table(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ grn_obj *table;
+
+ table = grn_column_table(ctx, DATA_PTR(self));
+ if (!table) {
+ return mrb_nil_value();
+ }
+
+ return grn_mrb_value_from_grn_obj(mrb, table);
+}
void
grn_mrb_column_init(grn_ctx *ctx)
@@ -35,5 +64,11 @@ grn_mrb_column_init(grn_ctx *ctx)
klass = mrb_define_class_under(mrb, module, "Column", object_class);
MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA);
+
+ mrb_define_method(mrb, klass, "locked?",
+ mrb_grn_column_is_locked, MRB_ARGS_NONE());
+
+ mrb_define_method(mrb, klass, "table",
+ mrb_grn_column_get_table, MRB_ARGS_NONE());
}
#endif
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_column.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_column.h
index 77e0dab82fd..abb99915fa5 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_column.h
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_column.h
@@ -19,7 +19,7 @@
#ifndef GRN_MRB_COLUMN_H
#define GRN_MRB_COLUMN_H
-#include "../ctx.h"
+#include "../grn_ctx.h"
#ifdef __cplusplus
extern "C" {
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_command.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command.c
new file mode 100644
index 00000000000..0ff3a0d5b69
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command.c
@@ -0,0 +1,180 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2015 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "../grn_ctx_impl.h"
+#include <groonga/command.h>
+
+#ifdef GRN_WITH_MRUBY
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/data.h>
+#include <mruby/value.h>
+#include <mruby/string.h>
+
+#include "mrb_ctx.h"
+#include "mrb_command.h"
+
+static struct mrb_data_type mrb_grn_command_type = {
+ "Groonga::Command",
+ NULL
+};
+
+mrb_value
+mrb_grn_command_instantiate(grn_ctx *ctx, grn_obj *command)
+{
+ grn_mrb_data *data = &(ctx->impl->mrb);
+ mrb_state *mrb = data->state;
+ struct RClass *module = data->module;
+ char name[GRN_TABLE_MAX_KEY_SIZE];
+ int name_size;
+ mrb_value mrb_name;
+ struct RClass *command_class;
+ struct RClass *target_command_class;
+ mrb_value mrb_target_command_class;
+ mrb_value mrb_arguments[1];
+
+ name_size = grn_obj_name(ctx, command, name, GRN_TABLE_MAX_KEY_SIZE);
+ mrb_name = mrb_str_new(mrb, name, name_size);
+
+ command_class = mrb_class_get_under(mrb, module, "Command");
+ mrb_target_command_class = mrb_funcall(mrb,
+ mrb_obj_value(command_class),
+ "find_class", 1, mrb_name);
+ if (mrb_nil_p(mrb_target_command_class)) {
+ target_command_class = command_class;
+ } else {
+ target_command_class = mrb_class_ptr(mrb_target_command_class);
+ }
+ mrb_arguments[0] = mrb_cptr_value(mrb, command);
+ return mrb_obj_new(mrb, target_command_class, 1, mrb_arguments);
+}
+
+static void
+mrb_grn_command_run_wrapper(grn_ctx *ctx,
+ grn_obj *command,
+ grn_command_input *input,
+ void *user_data)
+{
+ grn_mrb_data *data = &(ctx->impl->mrb);
+ mrb_state *mrb = data->state;
+ struct RClass *module = data->module;
+ int arena_index;
+ mrb_value mrb_command;
+ mrb_value mrb_input;
+
+ arena_index = mrb_gc_arena_save(mrb);
+ mrb_command = mrb_grn_command_instantiate(ctx, command);
+ {
+ struct RClass *command_input_class;
+ mrb_value mrb_arguments[1];
+ command_input_class = mrb_class_get_under(mrb, module, "CommandInput");
+ mrb_arguments[0] = mrb_cptr_value(mrb, input);
+ mrb_input = mrb_obj_new(mrb, command_input_class, 1, mrb_arguments);
+ }
+ mrb_funcall(mrb, mrb_command, "run_internal", 1, mrb_input);
+ mrb_gc_arena_restore(mrb, arena_index);
+}
+
+static mrb_value
+mrb_grn_command_singleton_register(mrb_state *mrb, mrb_value klass)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ mrb_value mrb_name;
+ mrb_value *mrb_arguments;
+ mrb_int n_arguments;
+
+ mrb_get_args(mrb, "Sa", &mrb_name, &mrb_arguments, &n_arguments);
+
+ {
+ grn_expr_var *vars;
+ mrb_int i;
+
+ for (i = 0; i < n_arguments; i++) {
+ mrb_arguments[i] = mrb_convert_type(mrb, mrb_arguments[i],
+ MRB_TT_STRING, "String", "to_str");
+ }
+ vars = GRN_MALLOCN(grn_expr_var, n_arguments);
+ for (i = 0; i < n_arguments; i++) {
+ mrb_value mrb_argument = mrb_arguments[i];
+ grn_expr_var *var = &vars[i];
+ var->name = RSTRING_PTR(mrb_argument);
+ var->name_size = RSTRING_LEN(mrb_argument);
+ GRN_TEXT_INIT(&(var->value), 0);
+ }
+
+ grn_command_register(ctx,
+ RSTRING_PTR(mrb_name),
+ RSTRING_LEN(mrb_name),
+ mrb_grn_command_run_wrapper,
+ vars,
+ n_arguments,
+ NULL);
+
+ for (i = 0; i < n_arguments; i++) {
+ grn_expr_var *var = &vars[i];
+ GRN_OBJ_FIN(ctx, &(var->value));
+ }
+ GRN_FREE(vars);
+ }
+
+ grn_mrb_ctx_check(mrb);
+
+ {
+ grn_mrb_data *data = &(ctx->impl->mrb);
+ struct RClass *command_class;
+ command_class = mrb_class_get_under(mrb, data->module, "Command");
+ mrb_funcall(mrb,
+ mrb_obj_value(command_class),
+ "register_class", 2, mrb_name, klass);
+ }
+
+ return mrb_nil_value();
+}
+
+static mrb_value
+mrb_grn_command_initialize(mrb_state *mrb, mrb_value self)
+{
+ mrb_value mrb_command_ptr;
+
+ mrb_get_args(mrb, "o", &mrb_command_ptr);
+ DATA_TYPE(self) = &mrb_grn_command_type;
+ DATA_PTR(self) = mrb_cptr(mrb_command_ptr);
+ return self;
+}
+
+void
+grn_mrb_command_init(grn_ctx *ctx)
+{
+ grn_mrb_data *data = &(ctx->impl->mrb);
+ mrb_state *mrb = data->state;
+ struct RClass *module = data->module;
+ struct RClass *procedure_class;
+ struct RClass *klass;
+
+ procedure_class = mrb_class_get_under(mrb, module, "Procedure");
+ klass = mrb_define_class_under(mrb, module, "Command", procedure_class);
+ MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA);
+
+ mrb_define_singleton_method(mrb, (struct RObject *)klass, "register",
+ mrb_grn_command_singleton_register,
+ MRB_ARGS_REQ(2));
+
+ mrb_define_method(mrb, klass, "initialize",
+ mrb_grn_command_initialize, MRB_ARGS_REQ(1));
+}
+#endif
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_command.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command.h
new file mode 100644
index 00000000000..2b899df3a6d
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command.h
@@ -0,0 +1,36 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2015 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef GRN_MRB_COMMAND_H
+#define GRN_MRB_COMMAND_H
+
+#include "../grn_ctx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void grn_mrb_command_init(grn_ctx *ctx);
+
+mrb_value grn_mrb_command_instantiate(grn_ctx *ctx, grn_obj *command);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRN_MRB_COMMAND_H */
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_command_input.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command_input.c
new file mode 100644
index 00000000000..f39202398d1
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command_input.c
@@ -0,0 +1,122 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2015 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "../grn_ctx_impl.h"
+#include <groonga/command.h>
+
+#ifdef GRN_WITH_MRUBY
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/data.h>
+#include <mruby/value.h>
+#include <mruby/string.h>
+
+#include "mrb_ctx.h"
+#include "mrb_command_input.h"
+
+static struct mrb_data_type mrb_grn_command_input_type = {
+ "Groonga::CommandInput",
+ NULL
+};
+
+static mrb_value
+mrb_grn_command_input_initialize(mrb_state *mrb, mrb_value self)
+{
+ mrb_value mrb_command_input_ptr;
+
+ mrb_get_args(mrb, "o", &mrb_command_input_ptr);
+ DATA_TYPE(self) = &mrb_grn_command_input_type;
+ DATA_PTR(self) = mrb_cptr(mrb_command_input_ptr);
+ return self;
+}
+
+static mrb_value
+mrb_grn_command_input_array_reference(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ grn_command_input *input;
+ mrb_value mrb_key_or_offset;
+ grn_obj *argument;
+
+ input = DATA_PTR(self);
+ mrb_get_args(mrb, "o", &mrb_key_or_offset);
+
+ switch (mrb_type(mrb_key_or_offset)) {
+ case MRB_TT_FIXNUM :
+ {
+ mrb_int offset = mrb_fixnum(mrb_key_or_offset);
+ argument = grn_command_input_at(ctx, input, offset);
+ }
+ break;
+ case MRB_TT_SYMBOL :
+ {
+ mrb_sym mrb_key_symbol;
+ const char *key;
+ mrb_int key_length;
+
+ mrb_key_symbol = mrb_symbol(mrb_key_or_offset);
+ key = mrb_sym2name_len(mrb, mrb_key_symbol, &key_length);
+ argument = grn_command_input_get(ctx, input, key, key_length);
+ }
+ break;
+ case MRB_TT_STRING :
+ {
+ mrb_value mrb_key = mrb_key_or_offset;
+ argument = grn_command_input_get(ctx, input,
+ RSTRING_PTR(mrb_key),
+ RSTRING_LEN(mrb_key));
+ }
+ break;
+ default :
+ mrb_raisef(mrb, E_ARGUMENT_ERROR,
+ "must be offset (as integer) or key (as symbol or string): %S",
+ mrb_key_or_offset);
+ break;
+ }
+
+ if (!argument) {
+ return mrb_nil_value();
+ }
+
+ if (GRN_TEXT_LEN(argument) == 0) {
+ return mrb_nil_value();
+ }
+
+ return mrb_str_new_static(mrb,
+ GRN_TEXT_VALUE(argument),
+ GRN_TEXT_LEN(argument));
+}
+
+void
+grn_mrb_command_input_init(grn_ctx *ctx)
+{
+ grn_mrb_data *data = &(ctx->impl->mrb);
+ mrb_state *mrb = data->state;
+ struct RClass *module = data->module;
+ struct RClass *klass;
+
+ klass = mrb_define_class_under(mrb, module, "CommandInput", mrb->object_class);
+ MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA);
+
+ mrb_define_method(mrb, klass, "initialize",
+ mrb_grn_command_input_initialize, MRB_ARGS_REQ(1));
+
+ mrb_define_method(mrb, klass, "[]",
+ mrb_grn_command_input_array_reference, MRB_ARGS_REQ(1));
+}
+#endif
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_command_input.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command_input.h
new file mode 100644
index 00000000000..a4eb09779d1
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command_input.h
@@ -0,0 +1,34 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2015 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef GRN_MRB_COMMAND_INPUT_H
+#define GRN_MRB_COMMAND_INPUT_H
+
+#include "../grn_ctx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void grn_mrb_command_input_init(grn_ctx *ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRN_MRB_COMMAND_INPUT_H */
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.c
index 2e7c41edbdf..9686feb8bc9 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.c
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.c
@@ -16,7 +16,8 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "../ctx_impl.h"
+#include "../grn_ctx_impl.h"
+#include "../grn_db.h"
#ifdef GRN_WITH_MRUBY
#include <mruby.h>
@@ -24,6 +25,7 @@
#include <mruby/data.h>
#include "mrb_converter.h"
+#include "mrb_bulk.h"
struct RClass *
grn_mrb_class_from_grn_obj(mrb_state *mrb, grn_obj *object)
@@ -34,12 +36,12 @@ grn_mrb_class_from_grn_obj(mrb_state *mrb, grn_obj *object)
data = &(ctx->impl->mrb);
switch (object->header.type) {
- case GRN_ACCESSOR :
- klass = mrb_class_get_under(mrb, data->module, "Accessor");
- break;
case GRN_BULK :
klass = mrb_class_get_under(mrb, data->module, "Bulk");
break;
+ case GRN_ACCESSOR :
+ klass = mrb_class_get_under(mrb, data->module, "Accessor");
+ break;
case GRN_COLUMN_FIX_SIZE :
klass = mrb_class_get_under(mrb, data->module, "FixedSizeColumn");
break;
@@ -49,12 +51,30 @@ grn_mrb_class_from_grn_obj(mrb_state *mrb, grn_obj *object)
case GRN_COLUMN_INDEX :
klass = mrb_class_get_under(mrb, data->module, "IndexColumn");
break;
- case GRN_EXPR :
- klass = mrb_class_get_under(mrb, data->module, "Expression");
+ case GRN_TYPE :
+ klass = mrb_class_get_under(mrb, data->module, "Type");
break;
case GRN_PROC :
klass = mrb_class_get_under(mrb, data->module, "Procedure");
break;
+ case GRN_EXPR :
+ klass = mrb_class_get_under(mrb, data->module, "Expression");
+ break;
+ case GRN_TABLE_NO_KEY :
+ klass = mrb_class_get_under(mrb, data->module, "Array");
+ break;
+ case GRN_TABLE_HASH_KEY :
+ klass = mrb_class_get_under(mrb, data->module, "HashTable");
+ break;
+ case GRN_TABLE_PAT_KEY :
+ klass = mrb_class_get_under(mrb, data->module, "PatriciaTrie");
+ break;
+ case GRN_TABLE_DAT_KEY :
+ klass = mrb_class_get_under(mrb, data->module, "DoubleArrayTrie");
+ break;
+ case GRN_DB :
+ klass = mrb_class_get_under(mrb, data->module, "Database");
+ break;
case GRN_VOID :
klass = mrb_class_get_under(mrb, data->module, "Void");
break;
@@ -90,4 +110,76 @@ grn_mrb_value_from_grn_obj(mrb_state *mrb, grn_obj *object)
mrb_object = mrb_obj_new(mrb, mrb_class, 1, mrb_new_arguments);
return mrb_object;
}
+
+grn_id
+grn_mrb_class_to_type(mrb_state *mrb, struct RClass *klass)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ grn_id type = GRN_DB_VOID;
+
+ if (klass == mrb->nil_class) {
+ type = GRN_DB_VOID;
+ } else if (klass == mrb->true_class ||
+ klass == mrb->false_class) {
+ type = GRN_DB_BOOL;
+ } else if (klass == mrb->symbol_class) {
+ type = GRN_DB_TEXT;
+ } else if (klass == mrb->fixnum_class) {
+ type = GRN_DB_INT64;
+ } else if (klass == mrb->float_class) {
+ type = GRN_DB_FLOAT;
+ } else if (klass == mrb->string_class) {
+ type = GRN_DB_TEXT;
+ } else if (klass == ctx->impl->mrb.builtin.time_class) {
+ type = GRN_DB_TIME;
+ } else {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR,
+ "unsupported class: %S", mrb_obj_value(klass));
+ }
+
+ return type;
+}
+
+static mrb_value
+mrb_grn_converter_singleton_convert(mrb_state *mrb, mrb_value klass)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ grn_obj *from = &(ctx->impl->mrb.buffer.from);
+ grn_obj *to = &(ctx->impl->mrb.buffer.to);
+ mrb_value mrb_from;
+ mrb_value mrb_to_class;
+ grn_id to_type;
+
+ mrb_get_args(mrb, "oC", &mrb_from, &mrb_to_class);
+
+ grn_mrb_value_to_bulk(mrb, mrb_from, from);
+ to_type = grn_mrb_class_to_type(mrb, mrb_class_ptr(mrb_to_class));
+ grn_obj_reinit(ctx, to, to_type, 0);
+ {
+ grn_rc rc;
+ rc = grn_obj_cast(ctx, from, to, GRN_FALSE);
+ if (rc != GRN_SUCCESS) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR,
+ "failed to convert to %S: %S",
+ mrb_to_class,
+ from);
+ }
+ }
+
+ return grn_mrb_value_from_bulk(mrb, to);
+}
+
+void
+grn_mrb_converter_init(grn_ctx *ctx)
+{
+ grn_mrb_data *data = &(ctx->impl->mrb);
+ mrb_state *mrb = data->state;
+ struct RClass *module;
+
+ module = mrb_define_module_under(mrb, data->module, "Converter");
+
+ mrb_define_singleton_method(mrb, (struct RObject *)module, "convert",
+ mrb_grn_converter_singleton_convert,
+ MRB_ARGS_REQ(2));
+}
#endif
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.h
index 27223a8c0bf..3dfe5e5a01a 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.h
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.h
@@ -19,16 +19,19 @@
#ifndef GRN_MRB_CONVERTER_H
#define GRN_MRB_CONVERTER_H
-#include "../ctx.h"
+#include "../grn_ctx.h"
#ifdef __cplusplus
extern "C" {
#endif
-#ifdef GRN_WITH_MRUBY
+void grn_mrb_converter_init(grn_ctx *ctx);
+
struct RClass *grn_mrb_class_from_grn_obj(mrb_state *mrb, grn_obj *object);
mrb_value grn_mrb_value_from_grn_obj(mrb_state *mrb, grn_obj *object);
-#endif
+
+grn_id grn_mrb_class_to_grn_type(mrb_state *mrb, struct RClass *klass);
+grn_id grn_mrb_value_to_grn_type(mrb_state *mrb, mrb_value value);
#ifdef __cplusplus
}
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.c
index 3f7bc36202d..f52342ae18e 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.c
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.c
@@ -1,6 +1,6 @@
/* -*- c-basic-offset: 2 -*- */
/*
- Copyright(C) 2013-2014 Brazil
+ Copyright(C) 2013-2015 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -16,7 +16,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "../ctx_impl.h"
+#include "../grn_ctx_impl.h"
#ifdef GRN_WITH_MRUBY
#include <mruby.h>
@@ -25,7 +25,7 @@
#include <mruby/variable.h>
#include <mruby/string.h>
-#include "../mrb.h"
+#include "../grn_mrb.h"
#include "mrb_ctx.h"
#include "mrb_converter.h"
@@ -53,12 +53,22 @@ static mrb_value
ctx_array_reference(mrb_state *mrb, mrb_value self)
{
grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ mrb_value mrb_id_or_name;
grn_obj *object;
- char *name;
- int name_length;
- mrb_get_args(mrb, "s", &name, &name_length);
- object = grn_ctx_get(ctx, name, name_length);
+ mrb_get_args(mrb, "o", &mrb_id_or_name);
+
+ if (mrb_fixnum_p(mrb_id_or_name)) {
+ grn_id id = mrb_fixnum(mrb_id_or_name);
+ object = grn_ctx_at(ctx, id);
+ } else {
+ mrb_value mrb_name;
+ mrb_name = mrb_convert_type(mrb, mrb_id_or_name,
+ MRB_TT_STRING, "String", "to_str");
+ object = grn_ctx_get(ctx,
+ RSTRING_PTR(mrb_name),
+ RSTRING_LEN(mrb_name));
+ }
return grn_mrb_value_from_grn_obj(mrb, object);
}
@@ -187,6 +197,14 @@ ctx_set_error_message(mrb_state *mrb, mrb_value self)
return error_message;
}
+static mrb_value
+ctx_get_database(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+
+ return grn_mrb_value_from_grn_obj(mrb, grn_ctx_db(ctx));
+}
+
void
grn_mrb_ctx_check(mrb_state *mrb)
{
@@ -568,10 +586,10 @@ grn_mrb_ctx_check(mrb_state *mrb)
"zlib error: <%s>(%d)",
ctx->errbuf, ctx->rc);
break;
- case GRN_LZO_ERROR:
- error_class = mrb_class_get_under(mrb, module, "LzoError");
+ case GRN_LZ4_ERROR:
+ error_class = mrb_class_get_under(mrb, module, "LZ4Error");
snprintf(message, MESSAGE_SIZE,
- "LZO error: <%s>(%d)",
+ "LZ4 error: <%s>(%d)",
ctx->errbuf, ctx->rc);
break;
case GRN_STACK_OVER_FLOW:
@@ -690,8 +708,7 @@ grn_mrb_ctx_init(grn_ctx *ctx)
mrb_define_method(mrb, klass, "error_message=", ctx_set_error_message,
MRB_ARGS_REQ(1));
- grn_mrb_load(ctx, "context/error_level.rb");
- grn_mrb_load(ctx, "context/rc.rb");
- grn_mrb_load(ctx, "context.rb");
+ mrb_define_method(mrb, klass, "database", ctx_get_database,
+ MRB_ARGS_NONE());
}
#endif
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.h
index 5068d0d75e2..aa527bfec51 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.h
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.h
@@ -19,16 +19,14 @@
#ifndef GRN_MRB_CTX_H
#define GRN_MRB_CTX_H
-#include "../ctx.h"
+#include "../grn_ctx.h"
#ifdef __cplusplus
extern "C" {
#endif
void grn_mrb_ctx_init(grn_ctx *ctx);
-#ifdef GRN_WITH_MRUBY
void grn_mrb_ctx_check(mrb_state *mrb);
-#endif
#ifdef __cplusplus
}
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_database.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_database.c
new file mode 100644
index 00000000000..22994104add
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_database.c
@@ -0,0 +1,124 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "../grn_ctx_impl.h"
+
+#ifdef GRN_WITH_MRUBY
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/data.h>
+
+#include "mrb_ctx.h"
+#include "mrb_database.h"
+
+static struct mrb_data_type mrb_grn_database_type = {
+ "Groonga::Database",
+ NULL
+};
+
+static mrb_value
+mrb_grn_database_initialize(mrb_state *mrb, mrb_value self)
+{
+ mrb_value mrb_database_ptr;
+
+ mrb_get_args(mrb, "o", &mrb_database_ptr);
+ DATA_TYPE(self) = &mrb_grn_database_type;
+ DATA_PTR(self) = mrb_cptr(mrb_database_ptr);
+ return self;
+}
+
+static mrb_value
+mrb_grn_database_singleton_open(mrb_state *mrb, mrb_value klass)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ grn_obj *database;
+ char *path;
+
+ mrb_get_args(mrb, "z", &path);
+
+ database = grn_db_open(ctx, path);
+ grn_mrb_ctx_check(mrb);
+
+ return mrb_funcall(mrb, klass, "new", 1, mrb_cptr_value(mrb, database));
+}
+
+static mrb_value
+mrb_grn_database_singleton_create(mrb_state *mrb, mrb_value klass)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ grn_obj *database;
+ char *path;
+
+ mrb_get_args(mrb, "z", &path);
+
+ database = grn_db_create(ctx, path, NULL);
+ grn_mrb_ctx_check(mrb);
+
+ return mrb_funcall(mrb, klass, "new", 1, mrb_cptr_value(mrb, database));
+}
+
+static mrb_value
+mrb_grn_database_recover(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+
+ grn_db_recover(ctx, DATA_PTR(self));
+ grn_mrb_ctx_check(mrb);
+
+ return mrb_nil_value();
+}
+
+static mrb_value
+mrb_grn_database_is_locked(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ unsigned int is_locked;
+
+ is_locked = grn_obj_is_locked(ctx, DATA_PTR(self));
+ grn_mrb_ctx_check(mrb);
+
+ return mrb_bool_value(is_locked != 0);
+}
+
+void
+grn_mrb_database_init(grn_ctx *ctx)
+{
+ grn_mrb_data *data = &(ctx->impl->mrb);
+ mrb_state *mrb = data->state;
+ struct RClass *module = data->module;
+ struct RClass *object_class = data->object_class;
+ struct RClass *klass;
+
+ klass = mrb_define_class_under(mrb, module, "Database", object_class);
+ MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA);
+
+ mrb_define_singleton_method(mrb, (struct RObject *)klass, "open",
+ mrb_grn_database_singleton_open,
+ MRB_ARGS_REQ(1));
+ mrb_define_singleton_method(mrb, (struct RObject *)klass, "create",
+ mrb_grn_database_singleton_create,
+ MRB_ARGS_REQ(1));
+
+ mrb_define_method(mrb, klass, "initialize",
+ mrb_grn_database_initialize, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, klass, "recover",
+ mrb_grn_database_recover, MRB_ARGS_NONE());
+ mrb_define_method(mrb, klass, "locked?",
+ mrb_grn_database_is_locked, MRB_ARGS_NONE());
+}
+#endif
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_database.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_database.h
new file mode 100644
index 00000000000..fd319c55fd1
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_database.h
@@ -0,0 +1,34 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef GRN_MRB_DATABASE_H
+#define GRN_MRB_DATABASE_H
+
+#include "../grn_ctx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void grn_mrb_database_init(grn_ctx *ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRN_MRB_DATABASE_H */
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_double_array_trie.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_double_array_trie.c
new file mode 100644
index 00000000000..5c034090b29
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_double_array_trie.c
@@ -0,0 +1,60 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "../grn_ctx_impl.h"
+
+#ifdef GRN_WITH_MRUBY
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/data.h>
+
+#include "mrb_double_array_trie.h"
+
+static struct mrb_data_type mrb_grn_double_array_trie_type = {
+ "Groonga::DoubleArrayTrie",
+ NULL
+};
+
+static mrb_value
+mrb_grn_double_array_trie_initialize(mrb_state *mrb, mrb_value self)
+{
+ mrb_value mrb_double_array_trie_ptr;
+
+ mrb_get_args(mrb, "o", &mrb_double_array_trie_ptr);
+ DATA_TYPE(self) = &mrb_grn_double_array_trie_type;
+ DATA_PTR(self) = mrb_cptr(mrb_double_array_trie_ptr);
+ return self;
+}
+
+void
+grn_mrb_double_array_trie_init(grn_ctx *ctx)
+{
+ grn_mrb_data *data = &(ctx->impl->mrb);
+ mrb_state *mrb = data->state;
+ struct RClass *module = data->module;
+ struct RClass *table_class;
+ struct RClass *klass;
+
+ table_class = mrb_class_get_under(mrb, module, "Table");
+ klass = mrb_define_class_under(mrb, module, "DoubleArrayTrie", table_class);
+ MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA);
+
+ mrb_define_method(mrb, klass, "initialize",
+ mrb_grn_double_array_trie_initialize, MRB_ARGS_REQ(1));
+}
+#endif
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_double_array_trie.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_double_array_trie.h
new file mode 100644
index 00000000000..a69a94e556e
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_double_array_trie.h
@@ -0,0 +1,34 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef GRN_MRB_DOUBLE_ARRAY_TRIE_H
+#define GRN_MRB_DOUBLE_ARRAY_TRIE_H
+
+#include "../grn_ctx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void grn_mrb_double_array_trie_init(grn_ctx *ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRN_MRB_DOUBLE_ARRAY_TRIE_H */
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_error.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_error.c
index 2f45cfc736e..a3513be1118 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_error.c
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_error.c
@@ -16,12 +16,12 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "../ctx_impl.h"
+#include "../grn_ctx_impl.h"
#ifdef GRN_WITH_MRUBY
#include <mruby.h>
-#include "../mrb.h"
+#include "../grn_mrb.h"
#include "mrb_error.h"
void
@@ -31,155 +31,164 @@ grn_mrb_error_init(grn_ctx *ctx)
mrb_state *mrb = data->state;
struct RClass *module = data->module;
struct RClass *error_class;
+ struct RClass *groonga_error_class;
error_class = mrb_define_class_under(mrb, module, "Error",
mrb->eStandardError_class);
+ groonga_error_class = mrb_define_class_under(mrb, module, "GroongaError",
+ error_class);
mrb_define_class_under(mrb, module, "EndOfData",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "UnknownError",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "OperationNotPermitted",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "NoSuchFileOrDirectory",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "NoSuchProcess",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "InterruptedFunctionCall",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "InputOutputError",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "NoSuchDeviceOrAddress",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "ArgListTooLong",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "ExecFormatError",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "BadFileDescriptor",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "NoChildProcesses",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "ResourceTemporarilyUnavailable",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "NotEnoughSpace",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "PermissionDenied",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "BadAddress",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "ResourceBusy",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "FileExists",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "ImproperLink",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "NoSuchDevice",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "NotDirectory",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "IsDirectory",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "InvalidArgument",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "TooManyOpenFilesInSystem",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "TooManyOpenFiles",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "InappropriateIOControlOperation",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "FileTooLarge",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "NoSpaceLeftOnDevice",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "InvalidSeek",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "ReadOnlyFileSystem",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "TooManyLinks",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "BrokenPipe",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "DomainError",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "ResultTooLarge",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "ResourceDeadlockAvoided",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "NoMemoryAvailable",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "FilenameTooLong",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "NoLocksAvailable",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "FunctionNotImplemented",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "DirectoryNotEmpty",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "IllegalByteSequence",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "SocketNotInitialized",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "OperationWouldBlock",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "AddressIsNotAvailable",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "NetworkIsDown",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "NoBuffer",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "SocketIsAlreadyConnected",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "SocketIsNotConnected",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "SocketIsAlreadyShutdowned",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "OperationTimeout",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "ConnectionRefused",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "RangeError",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "TokenizerError",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "FileCorrupt",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "InvalidFormat",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "ObjectCorrupt",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "TooManySymbolicLinks",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "NotSocket",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "OperationNotSupported",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "AddressIsInUse",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "ZlibError",
- error_class);
- mrb_define_class_under(mrb, module, "LzoError",
- error_class);
+ groonga_error_class);
+ mrb_define_class_under(mrb, module, "LZ4Error",
+ groonga_error_class);
mrb_define_class_under(mrb, module, "StackOverFlow",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "SyntaxError",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "RetryMax",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "IncompatibleFileFormat",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "UpdateNotAllowed",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "TooSmallOffset",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "TooLargeOffset",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "TooSmallLimit",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "CASError",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "UnsupportedCommandVersion",
- error_class);
+ groonga_error_class);
mrb_define_class_under(mrb, module, "NormalizerError",
- error_class);
+ groonga_error_class);
+ mrb_define_class_under(mrb, module, "TokenFilterError",
+ groonga_error_class);
+ mrb_define_class_under(mrb, module, "CommandError",
+ groonga_error_class);
+ mrb_define_class_under(mrb, module, "PluginError",
+ groonga_error_class);
}
#endif
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_error.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_error.h
index c59fabc12af..c68c58fa273 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_error.h
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_error.h
@@ -19,7 +19,7 @@
#ifndef GRN_MRB_ERROR_H
#define GRN_MRB_ERROR_H
-#include "../ctx.h"
+#include "../grn_ctx.h"
#ifdef __cplusplus
extern "C" {
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.c
index 3d0499c6b5c..df86d5579e4 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.c
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.c
@@ -1,6 +1,6 @@
/* -*- c-basic-offset: 2 -*- */
/*
- Copyright(C) 2013-2014 Brazil
+ Copyright(C) 2013-2015 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -16,7 +16,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "../ctx_impl.h"
+#include "../grn_ctx_impl.h"
#ifdef GRN_WITH_MRUBY
#include <mruby.h>
@@ -25,10 +25,11 @@
#include <mruby/data.h>
#include <mruby/string.h>
#include <mruby/array.h>
+#include <mruby/hash.h>
-#include "../expr.h"
-#include "../util.h"
-#include "../mrb.h"
+#include "../grn_expr.h"
+#include "../grn_util.h"
+#include "../grn_mrb.h"
#include "mrb_accessor.h"
#include "mrb_ctx.h"
#include "mrb_expr.h"
@@ -256,6 +257,33 @@ mrb_grn_scan_info_get_similarity_threshold(mrb_state *mrb, mrb_value self)
}
static mrb_value
+mrb_grn_scan_info_set_scorer(mrb_state *mrb, mrb_value self)
+{
+ scan_info *si;
+ mrb_value mrb_scorer;
+
+ mrb_get_args(mrb, "o", &mrb_scorer);
+ si = DATA_PTR(self);
+ if (mrb_nil_p(mrb_scorer)) {
+ grn_scan_info_set_scorer(si, NULL);
+ } else {
+ grn_scan_info_set_scorer(si, DATA_PTR(mrb_scorer));
+ }
+ return self;
+}
+
+static mrb_value
+mrb_grn_scan_info_get_scorer(mrb_state *mrb, mrb_value self)
+{
+ scan_info *si;
+ grn_obj *scorer;
+
+ si = DATA_PTR(self);
+ scorer = grn_scan_info_get_scorer(si);
+ return grn_mrb_value_from_grn_obj(mrb, scorer);
+}
+
+static mrb_value
mrb_grn_scan_info_get_arg(mrb_state *mrb, mrb_value self)
{
grn_ctx *ctx = (grn_ctx *)mrb->ud;
@@ -322,6 +350,41 @@ mrb_grn_expr_code_get_flags(mrb_state *mrb, mrb_value self)
}
static mrb_value
+mrb_grn_expression_singleton_create(mrb_state *mrb, mrb_value klass)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ mrb_value mrb_expr;
+ mrb_value mrb_table;
+ mrb_value mrb_new_arguments[1];
+ grn_obj *expr, *variable = NULL;
+
+ mrb_get_args(mrb, "o", &mrb_table);
+ if (mrb_nil_p(mrb_table)) {
+ expr = grn_expr_create(ctx, NULL, 0);
+ } else {
+ grn_obj *table = DATA_PTR(mrb_table);
+ GRN_EXPR_CREATE_FOR_QUERY(ctx, table, expr, variable);
+ }
+
+ if (!expr) {
+ grn_mrb_ctx_check(mrb);
+ return mrb_nil_value();
+ }
+
+ mrb_new_arguments[0] = mrb_cptr_value(mrb, expr);
+ mrb_expr = mrb_obj_new(mrb, mrb_class_ptr(klass), 1, mrb_new_arguments);
+ {
+ mrb_value mrb_variable = mrb_nil_value();
+ if (variable) {
+ mrb_variable = grn_mrb_value_from_grn_obj(mrb, variable);
+ }
+ mrb_iv_set(mrb, mrb_expr, mrb_intern_lit(mrb, "@variable"), mrb_variable);
+ }
+
+ return mrb_expr;
+}
+
+static mrb_value
mrb_grn_expression_initialize(mrb_state *mrb, mrb_value self)
{
mrb_value mrb_expression_ptr;
@@ -409,6 +472,170 @@ mrb_grn_expression_allocate_constant(mrb_state *mrb, mrb_value self)
return grn_mrb_value_from_grn_obj(mrb, grn_object);
}
+static mrb_value
+mrb_grn_expression_parse(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ grn_obj *expr;
+ char *query;
+ mrb_int query_size;
+ grn_obj *default_column = NULL;
+ grn_operator default_mode = GRN_OP_MATCH;
+ grn_operator default_operator = GRN_OP_AND;
+ grn_expr_flags flags = GRN_EXPR_SYNTAX_SCRIPT;
+ mrb_value mrb_options = mrb_nil_value();
+
+ expr = DATA_PTR(self);
+ mrb_get_args(mrb, "s|H", &query, &query_size, &mrb_options);
+
+ if (!mrb_nil_p(mrb_options)) {
+ mrb_value mrb_flags;
+
+ mrb_flags = mrb_hash_get(mrb, mrb_options,
+ mrb_symbol_value(mrb_intern_lit(mrb, "flags")));
+ if (!mrb_nil_p(mrb_flags)) {
+ flags = mrb_fixnum(mrb_flags);
+ }
+ }
+
+ grn_expr_parse(ctx, expr, query, query_size, default_column,
+ default_mode, default_operator, flags);
+ grn_mrb_ctx_check(mrb);
+
+ return mrb_nil_value();
+}
+
+static mrb_value
+mrb_grn_expression_append_object(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ grn_obj *expr;
+ mrb_value mrb_object;
+ grn_obj *object;
+ grn_operator op;
+ int n_args;
+
+ expr = DATA_PTR(self);
+ mrb_get_args(mrb, "oii", &mrb_object, &op, &n_args);
+
+ object = DATA_PTR(mrb_object);
+ grn_expr_append_obj(ctx, expr, object, op, n_args);
+ grn_mrb_ctx_check(mrb);
+
+ return mrb_nil_value();
+}
+
+static mrb_value
+mrb_grn_expression_append_constant(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ grn_obj *expr;
+ mrb_value mrb_constant;
+ grn_operator op;
+ int n_args;
+
+ expr = DATA_PTR(self);
+ mrb_get_args(mrb, "oii", &mrb_constant, &op, &n_args);
+
+ switch (mrb_type(mrb_constant)) {
+ case MRB_TT_FALSE :
+ if (mrb_nil_p(mrb_constant)) {
+ grn_obj constant;
+ GRN_VOID_INIT(&constant);
+ grn_expr_append_const(ctx, expr, &constant, op, n_args);
+ GRN_OBJ_FIN(ctx, &constant);
+ } else {
+ grn_obj constant;
+ GRN_BOOL_INIT(&constant, 0);
+ GRN_BOOL_SET(ctx, &constant, GRN_FALSE);
+ grn_expr_append_const(ctx, expr, &constant, op, n_args);
+ GRN_OBJ_FIN(ctx, &constant);
+ }
+ break;
+ case MRB_TT_TRUE :
+ {
+ grn_obj constant;
+ GRN_BOOL_INIT(&constant, 0);
+ GRN_BOOL_SET(ctx, &constant, GRN_TRUE);
+ grn_expr_append_const(ctx, expr, &constant, op, n_args);
+ GRN_OBJ_FIN(ctx, &constant);
+ }
+ break;
+ case MRB_TT_FIXNUM :
+ grn_expr_append_const_int(ctx, expr, mrb_fixnum(mrb_constant), op, n_args);
+ break;
+ case MRB_TT_SYMBOL :
+ {
+ const char *value;
+ mrb_int value_length;
+
+ value = mrb_sym2name_len(mrb, mrb_symbol(mrb_constant), &value_length);
+ grn_expr_append_const_str(ctx, expr, value, value_length, op, n_args);
+ }
+ break;
+ case MRB_TT_FLOAT :
+ {
+ grn_obj constant;
+ GRN_FLOAT_INIT(&constant, 0);
+ GRN_FLOAT_SET(ctx, &constant, mrb_float(mrb_constant));
+ grn_expr_append_const(ctx, expr, &constant, op, n_args);
+ GRN_OBJ_FIN(ctx, &constant);
+ }
+ break;
+ case MRB_TT_STRING :
+ grn_expr_append_const_str(ctx, expr,
+ RSTRING_PTR(mrb_constant),
+ RSTRING_LEN(mrb_constant),
+ op, n_args);
+ break;
+ default :
+ {
+ struct RClass *klass;
+
+ klass = mrb_class(mrb, mrb_constant);
+ if (klass == ctx->impl->mrb.builtin.time_class) {
+ grn_obj constant;
+ mrb_value mrb_sec;
+ mrb_value mrb_usec;
+
+ mrb_sec = mrb_funcall(mrb, mrb_constant, "to_i", 0);
+ mrb_usec = mrb_funcall(mrb, mrb_constant, "usec", 0);
+ GRN_TIME_INIT(&constant, 0);
+ GRN_TIME_SET(ctx, &constant,
+ GRN_TIME_PACK(mrb_fixnum(mrb_sec), mrb_fixnum(mrb_usec)));
+ grn_expr_append_const(ctx, expr, &constant, op, n_args);
+ GRN_OBJ_FIN(ctx, &constant);
+ } else {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR,
+ "unsupported constant to append to expression: %S",
+ mrb_constant);
+ }
+ }
+ break;
+ }
+
+ grn_mrb_ctx_check(mrb);
+
+ return mrb_nil_value();
+}
+
+static mrb_value
+mrb_grn_expression_append_operator(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ grn_obj *expr;
+ grn_operator op;
+ int n_args;
+
+ expr = DATA_PTR(self);
+ mrb_get_args(mrb, "ii", &op, &n_args);
+
+ grn_expr_append_op(ctx, expr, op, n_args);
+ grn_mrb_ctx_check(mrb);
+
+ return mrb_nil_value();
+}
+
void
grn_mrb_expr_init(grn_ctx *ctx)
{
@@ -447,6 +674,10 @@ grn_mrb_expr_init(grn_ctx *ctx)
mrb_grn_scan_info_get_similarity_threshold, MRB_ARGS_NONE());
mrb_define_method(mrb, klass, "similarity_threshold=",
mrb_grn_scan_info_set_similarity_threshold, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, klass, "scorer",
+ mrb_grn_scan_info_get_scorer, MRB_ARGS_NONE());
+ mrb_define_method(mrb, klass, "scorer=",
+ mrb_grn_scan_info_set_scorer, MRB_ARGS_REQ(1));
mrb_define_method(mrb, klass, "get_arg",
mrb_grn_scan_info_get_arg, MRB_ARGS_REQ(1));
mrb_define_method(mrb, klass, "push_arg",
@@ -468,6 +699,11 @@ grn_mrb_expr_init(grn_ctx *ctx)
klass = mrb_define_class_under(mrb, module, "Expression", object_class);
MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA);
+
+ mrb_define_singleton_method(mrb, (struct RObject *)klass, "create",
+ mrb_grn_expression_singleton_create,
+ MRB_ARGS_REQ(1));
+
mrb_define_method(mrb, klass, "initialize",
mrb_grn_expression_initialize, MRB_ARGS_REQ(1));
mrb_define_method(mrb, klass, "codes",
@@ -479,6 +715,16 @@ grn_mrb_expr_init(grn_ctx *ctx)
mrb_define_method(mrb, klass, "allocate_constant",
mrb_grn_expression_allocate_constant, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, klass, "parse",
+ mrb_grn_expression_parse, MRB_ARGS_ARG(1, 1));
+
+ mrb_define_method(mrb, klass, "append_object",
+ mrb_grn_expression_append_object, MRB_ARGS_REQ(2));
+ mrb_define_method(mrb, klass, "append_constant",
+ mrb_grn_expression_append_constant, MRB_ARGS_REQ(3));
+ mrb_define_method(mrb, klass, "append_operator",
+ mrb_grn_expression_append_operator, MRB_ARGS_REQ(2));
+
grn_mrb_load(ctx, "expression.rb");
grn_mrb_load(ctx, "scan_info.rb");
grn_mrb_load(ctx, "scan_info_data.rb");
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.h
index 7fd5c66e9c5..687565dd6d9 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.h
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.h
@@ -19,8 +19,8 @@
#ifndef GRN_MRB_EXPR_H
#define GRN_MRB_EXPR_H
-#include "../ctx.h"
-#include "../expr.h"
+#include "../grn_ctx.h"
+#include "../grn_expr.h"
#ifdef __cplusplus
extern "C" {
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.c
index d8df913f77d..130225029a2 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.c
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.c
@@ -16,7 +16,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "../ctx_impl.h"
+#include "../grn_ctx_impl.h"
#ifdef GRN_WITH_MRUBY
#include <mruby.h>
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.h
index 938dcd76c7a..1037716c9f7 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.h
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.h
@@ -19,7 +19,7 @@
#ifndef GRN_MRB_FIXED_SIZE_COLUMN_H
#define GRN_MRB_FIXED_SIZE_COLUMN_H
-#include "../ctx.h"
+#include "../grn_ctx.h"
#ifdef __cplusplus
extern "C" {
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_hash_table.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_hash_table.c
new file mode 100644
index 00000000000..a5a4e797de2
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_hash_table.c
@@ -0,0 +1,60 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "../grn_ctx_impl.h"
+
+#ifdef GRN_WITH_MRUBY
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/data.h>
+
+#include "mrb_hash_table.h"
+
+static struct mrb_data_type mrb_grn_hash_table_type = {
+ "Groonga::HashTable",
+ NULL
+};
+
+static mrb_value
+mrb_grn_hash_table_initialize(mrb_state *mrb, mrb_value self)
+{
+ mrb_value mrb_hash_table_ptr;
+
+ mrb_get_args(mrb, "o", &mrb_hash_table_ptr);
+ DATA_TYPE(self) = &mrb_grn_hash_table_type;
+ DATA_PTR(self) = mrb_cptr(mrb_hash_table_ptr);
+ return self;
+}
+
+void
+grn_mrb_hash_table_init(grn_ctx *ctx)
+{
+ grn_mrb_data *data = &(ctx->impl->mrb);
+ mrb_state *mrb = data->state;
+ struct RClass *module = data->module;
+ struct RClass *table_class;
+ struct RClass *klass;
+
+ table_class = mrb_class_get_under(mrb, module, "Table");
+ klass = mrb_define_class_under(mrb, module, "HashTable", table_class);
+ MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA);
+
+ mrb_define_method(mrb, klass, "initialize",
+ mrb_grn_hash_table_initialize, MRB_ARGS_REQ(1));
+}
+#endif
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_hash_table.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_hash_table.h
new file mode 100644
index 00000000000..223267b47d9
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_hash_table.h
@@ -0,0 +1,34 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef GRN_MRB_HASH_TABLE_H
+#define GRN_MRB_HASH_TABLE_H
+
+#include "../grn_ctx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void grn_mrb_hash_table_init(grn_ctx *ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRN_MRB_HASH_TABLE_H */
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_id.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_id.c
index aa907b84a43..f55960716e9 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_id.c
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_id.c
@@ -16,7 +16,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "../ctx_impl.h"
+#include "../grn_ctx_impl.h"
#ifdef GRN_WITH_MRUBY
#include <mruby.h>
@@ -32,6 +32,11 @@ grn_mrb_id_init(grn_ctx *ctx)
id_module = mrb_define_module_under(mrb, module, "ID");
+ mrb_define_const(mrb, id_module, "NIL",
+ mrb_fixnum_value(GRN_ID_NIL));
+ mrb_define_const(mrb, id_module, "MAX",
+ mrb_fixnum_value(GRN_ID_MAX));
+
mrb_define_const(mrb, id_module, "VOID",
mrb_fixnum_value(GRN_DB_VOID));
mrb_define_const(mrb, id_module, "DB",
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_id.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_id.h
index f5b44358143..fcfd80384b5 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_id.h
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_id.h
@@ -19,7 +19,7 @@
#ifndef GRN_MRB_ID_H
#define GRN_MRB_ID_H
-#include "../ctx.h"
+#include "../grn_ctx.h"
#ifdef __cplusplus
extern "C" {
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.c
index 7bdf7528fc7..d91aa576e8e 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.c
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.c
@@ -16,7 +16,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "../ctx_impl.h"
+#include "../grn_ctx_impl.h"
#ifdef GRN_WITH_MRUBY
#include <mruby.h>
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.h
index 10e0589bf93..307448fd4c3 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.h
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.h
@@ -19,7 +19,7 @@
#ifndef GRN_MRB_INDEX_COLUMN_H
#define GRN_MRB_INDEX_COLUMN_H
-#include "../ctx.h"
+#include "../grn_ctx.h"
#ifdef __cplusplus
extern "C" {
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_cursor.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_cursor.c
new file mode 100644
index 00000000000..f57d59d727c
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_cursor.c
@@ -0,0 +1,128 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2015 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "../grn_ctx_impl.h"
+
+#ifdef GRN_WITH_MRUBY
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/data.h>
+#include <mruby/string.h>
+#include <mruby/hash.h>
+
+#include "mrb_ctx.h"
+#include "mrb_index_cursor.h"
+
+static struct mrb_data_type mrb_grn_index_cursor_type = {
+ "Groonga::IndexCursor",
+ NULL
+};
+
+static mrb_value
+mrb_grn_index_cursor_singleton_open_raw(mrb_state *mrb, mrb_value klass)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ mrb_value mrb_table_cursor;
+ mrb_value mrb_index;
+ mrb_value mrb_options = mrb_nil_value();
+ grn_obj *index_cursor;
+ grn_table_cursor *table_cursor;
+ grn_obj *index;
+ grn_id rid_min = GRN_ID_NIL;
+ grn_id rid_max = GRN_ID_MAX;
+ int flags = 0;
+
+ mrb_get_args(mrb, "oo|H", &mrb_table_cursor, &mrb_index, &mrb_options);
+
+ table_cursor = DATA_PTR(mrb_table_cursor);
+ index = DATA_PTR(mrb_index);
+ if (!mrb_nil_p(mrb_options)) {
+ /* TODO */
+ }
+ index_cursor = grn_index_cursor_open(ctx, table_cursor, index,
+ rid_min, rid_max, flags);
+ grn_mrb_ctx_check(mrb);
+
+ return mrb_funcall(mrb, klass, "new", 1, mrb_cptr_value(mrb, index_cursor));
+}
+
+static mrb_value
+mrb_grn_index_cursor_initialize(mrb_state *mrb, mrb_value self)
+{
+ mrb_value mrb_index_cursor_ptr;
+
+ mrb_get_args(mrb, "o", &mrb_index_cursor_ptr);
+ DATA_TYPE(self) = &mrb_grn_index_cursor_type;
+ DATA_PTR(self) = mrb_cptr(mrb_index_cursor_ptr);
+
+ return self;
+}
+
+static mrb_value
+mrb_grn_index_cursor_close(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ grn_obj *index_cursor;
+
+ index_cursor = DATA_PTR(self);
+ if (index_cursor) {
+ DATA_PTR(self) = NULL;
+ grn_obj_close(ctx, index_cursor);
+ grn_mrb_ctx_check(mrb);
+ }
+
+ return mrb_nil_value();
+}
+
+static mrb_value
+mrb_grn_index_cursor_count(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ grn_id term_id;
+ int n_records = 0;
+
+ while (grn_index_cursor_next(ctx, DATA_PTR(self), &term_id)) {
+ n_records++;
+ }
+
+ return mrb_fixnum_value(n_records);
+}
+
+void
+grn_mrb_index_cursor_init(grn_ctx *ctx)
+{
+ grn_mrb_data *data = &(ctx->impl->mrb);
+ mrb_state *mrb = data->state;
+ struct RClass *module = data->module;
+ struct RClass *klass;
+
+ klass = mrb_define_class_under(mrb, module, "IndexCursor", mrb->object_class);
+ MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA);
+
+ mrb_define_singleton_method(mrb, (struct RObject *)klass, "open_raw",
+ mrb_grn_index_cursor_singleton_open_raw,
+ MRB_ARGS_ARG(2, 1));
+
+ mrb_define_method(mrb, klass, "initialize",
+ mrb_grn_index_cursor_initialize, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, klass, "close",
+ mrb_grn_index_cursor_close, MRB_ARGS_NONE());
+ mrb_define_method(mrb, klass, "count",
+ mrb_grn_index_cursor_count, MRB_ARGS_NONE());
+}
+#endif
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_cursor.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_cursor.h
new file mode 100644
index 00000000000..afbad53db9f
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_cursor.h
@@ -0,0 +1,34 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2015 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef GRN_MRB_INDEX_CURSOR_H
+#define GRN_MRB_INDEX_CURSOR_H
+
+#include "../grn_ctx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void grn_mrb_index_cursor_init(grn_ctx *ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRN_MRB_INDEX_CURSOR_H */
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.c
index 4917694fa8a..884ca761e83 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.c
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.c
@@ -16,7 +16,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "../ctx_impl.h"
+#include "../grn_ctx_impl.h"
#ifdef GRN_WITH_MRUBY
#include <mruby.h>
@@ -25,7 +25,7 @@
#include <mruby/variable.h>
#include <mruby/string.h>
-#include "../mrb.h"
+#include "../grn_mrb.h"
#include "mrb_logger.h"
static mrb_value
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.h
index 5bfb62e98a2..358313b7ff9 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.h
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.h
@@ -19,7 +19,7 @@
#ifndef GRN_MRB_LOGGER_H
#define GRN_MRB_LOGGER_H
-#include "../ctx.h"
+#include "../grn_ctx.h"
#ifdef __cplusplus
extern "C" {
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_obj.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_object.c
index 142a242b980..60398b91829 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_obj.c
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_object.c
@@ -16,8 +16,8 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "../ctx_impl.h"
-#include "../util.h"
+#include "../grn_ctx_impl.h"
+#include "../grn_util.h"
#ifdef GRN_WITH_MRUBY
#include <mruby.h>
@@ -25,11 +25,22 @@
#include <mruby/class.h>
#include <mruby/data.h>
-#include "../mrb.h"
-#include "mrb_obj.h"
+#include "../grn_mrb.h"
+#include "mrb_object.h"
#include "mrb_converter.h"
static mrb_value
+object_get_id(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ grn_id id;
+
+ id = grn_obj_id(ctx, DATA_PTR(self));
+
+ return mrb_fixnum_value(id);
+}
+
+static mrb_value
object_get_name(mrb_state *mrb, mrb_value self)
{
grn_ctx *ctx = (grn_ctx *)mrb->ud;
@@ -111,8 +122,47 @@ object_equal(mrb_state *mrb, mrb_value self)
}
}
+static mrb_value
+object_close(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ grn_obj *object;
+
+ object = DATA_PTR(self);
+ if (!object) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "already closed object");
+ }
+
+ grn_obj_close(ctx, object);
+ DATA_PTR(self) = NULL;
+
+ return mrb_nil_value();
+}
+
+static mrb_value
+object_is_temporary(mrb_state *mrb, mrb_value self)
+{
+ grn_obj *object;
+ grn_obj_flags flags;
+
+ object = DATA_PTR(self);
+ flags = object->header.flags;
+ return mrb_bool_value((flags & GRN_OBJ_PERSISTENT) != GRN_OBJ_PERSISTENT);
+}
+
+static mrb_value
+object_is_persistent(mrb_state *mrb, mrb_value self)
+{
+ grn_obj *object;
+ grn_obj_flags flags;
+
+ object = DATA_PTR(self);
+ flags = object->header.flags;
+ return mrb_bool_value((flags & GRN_OBJ_PERSISTENT) == GRN_OBJ_PERSISTENT);
+}
+
void
-grn_mrb_obj_init(grn_ctx *ctx)
+grn_mrb_object_init(grn_ctx *ctx)
{
grn_mrb_data *data = &(ctx->impl->mrb);
mrb_state *mrb = data->state;
@@ -123,12 +173,19 @@ grn_mrb_obj_init(grn_ctx *ctx)
MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA);
data->object_class = klass;
+ mrb_define_method(mrb, klass, "id", object_get_id, MRB_ARGS_NONE());
mrb_define_method(mrb, klass, "name", object_get_name, MRB_ARGS_NONE());
mrb_define_method(mrb, klass, "find_index",
object_find_index, MRB_ARGS_REQ(1));
mrb_define_method(mrb, klass, "grn_inspect",
object_grn_inspect, MRB_ARGS_NONE());
mrb_define_method(mrb, klass, "==", object_equal, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, klass, "close", object_close, MRB_ARGS_NONE());
+
+ mrb_define_method(mrb, klass, "temporary?", object_is_temporary,
+ MRB_ARGS_NONE());
+ mrb_define_method(mrb, klass, "persistent?", object_is_persistent,
+ MRB_ARGS_NONE());
grn_mrb_load(ctx, "index_info.rb");
}
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_object.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_object.h
new file mode 100644
index 00000000000..97a586c0f11
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_object.h
@@ -0,0 +1,34 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2013-2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef GRN_MRB_OBJECT_H
+#define GRN_MRB_OBJECT_H
+
+#include "../grn_ctx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void grn_mrb_object_init(grn_ctx *ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRN_MRB_OBJECT_H */
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.c
index 5a18d2e7023..ca2fc74a38a 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.c
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.c
@@ -16,7 +16,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "../ctx_impl.h"
+#include "../grn_ctx_impl.h"
#ifdef GRN_WITH_MRUBY
#include <mruby.h>
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.h
index 2650cc9421d..683b9dacbd9 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.h
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.h
@@ -19,7 +19,7 @@
#ifndef GRN_MRB_OPERATOR_H
#define GRN_MRB_OPERATOR_H
-#include "../ctx.h"
+#include "../grn_ctx.h"
#ifdef __cplusplus
extern "C" {
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_patricia_trie.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_patricia_trie.c
new file mode 100644
index 00000000000..d2486f21c37
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_patricia_trie.c
@@ -0,0 +1,59 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "../grn_ctx_impl.h"
+
+#ifdef GRN_WITH_MRUBY
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/data.h>
+
+#include "mrb_patricia_trie.h"
+
+static struct mrb_data_type mrb_grn_patricia_trie_type = {
+ "Groonga::PatriciaTrie",
+ NULL
+};
+
+static mrb_value
+mrb_grn_patricia_trie_initialize(mrb_state *mrb, mrb_value self)
+{
+ mrb_value mrb_patricia_trie_ptr;
+
+ mrb_get_args(mrb, "o", &mrb_patricia_trie_ptr);
+ DATA_TYPE(self) = &mrb_grn_patricia_trie_type;
+ DATA_PTR(self) = mrb_cptr(mrb_patricia_trie_ptr);
+ return self;
+}
+
+void
+grn_mrb_patricia_trie_init(grn_ctx *ctx)
+{
+ grn_mrb_data *data = &(ctx->impl->mrb);
+ mrb_state *mrb = data->state;
+ struct RClass *module = data->module;
+ struct RClass *table_class;
+ struct RClass *klass;
+
+ table_class = mrb_class_get_under(mrb, module, "Table");
+ klass = mrb_define_class_under(mrb, module, "PatriciaTrie", table_class);
+ MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA);
+ mrb_define_method(mrb, klass, "initialize",
+ mrb_grn_patricia_trie_initialize, MRB_ARGS_REQ(1));
+}
+#endif
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_patricia_trie.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_patricia_trie.h
new file mode 100644
index 00000000000..f281b25969b
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_patricia_trie.h
@@ -0,0 +1,34 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef GRN_MRB_PATRICIA_TRIE_H
+#define GRN_MRB_PATRICIA_TRIE_H
+
+#include "../grn_ctx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void grn_mrb_patricia_trie_init(grn_ctx *ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRN_MRB_PATRICIA_TRIE_H */
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.c
index fa9c677f2e6..3dfe78488df 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.c
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.c
@@ -16,7 +16,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "../ctx_impl.h"
+#include "../grn_ctx_impl.h"
#ifdef GRN_WITH_MRUBY
#include <mruby.h>
@@ -41,6 +41,15 @@ mrb_grn_procedure_initialize(mrb_state *mrb, mrb_value self)
return self;
}
+static mrb_value
+mrb_grn_procedure_scorer_p(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ grn_obj *proc = DATA_PTR(self);
+
+ return mrb_bool_value(grn_obj_is_scorer_proc(ctx, proc));
+}
+
void
grn_mrb_procedure_init(grn_ctx *ctx)
{
@@ -54,5 +63,8 @@ grn_mrb_procedure_init(grn_ctx *ctx)
MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA);
mrb_define_method(mrb, klass, "initialize",
mrb_grn_procedure_initialize, MRB_ARGS_REQ(1));
+
+ mrb_define_method(mrb, klass, "scorer?",
+ mrb_grn_procedure_scorer_p, MRB_ARGS_NONE());
}
#endif
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.h
index 16a4b32895c..36bd10fdab9 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.h
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.h
@@ -19,7 +19,7 @@
#ifndef GRN_MRB_PROCEDURE_H
#define GRN_MRB_PROCEDURE_H
-#include "../ctx.h"
+#include "../grn_ctx.h"
#ifdef __cplusplus
extern "C" {
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table.c
new file mode 100644
index 00000000000..2b86fdb482b
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table.c
@@ -0,0 +1,226 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2014-2015 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "../grn_ctx_impl.h"
+
+#ifdef GRN_WITH_MRUBY
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/data.h>
+#include <mruby/hash.h>
+#include <mruby/array.h>
+#include <mruby/string.h>
+
+#include "mrb_ctx.h"
+#include "mrb_table.h"
+#include "mrb_converter.h"
+
+static mrb_value
+mrb_grn_table_is_locked(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ unsigned int is_locked;
+
+ is_locked = grn_obj_is_locked(ctx, DATA_PTR(self));
+ grn_mrb_ctx_check(mrb);
+
+ return mrb_bool_value(is_locked != 0);
+}
+
+static mrb_value
+mrb_grn_table_get_size(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ unsigned int size;
+
+ size = grn_table_size(ctx, DATA_PTR(self));
+ grn_mrb_ctx_check(mrb);
+
+ return mrb_fixnum_value(size);
+}
+
+static mrb_value
+mrb_grn_table_is_empty(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ unsigned int size;
+
+ size = grn_table_size(ctx, DATA_PTR(self));
+ grn_mrb_ctx_check(mrb);
+
+ return mrb_bool_value(size == 0);
+}
+
+static mrb_value
+mrb_grn_table_select(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ grn_obj *table;
+ grn_obj *expr;
+ grn_obj *result = NULL;
+ grn_operator operator = GRN_OP_OR;
+ mrb_value mrb_expr;
+ mrb_value mrb_options = mrb_nil_value();
+
+ table = DATA_PTR(self);
+ mrb_get_args(mrb, "o|H", &mrb_expr, &mrb_options);
+
+ expr = DATA_PTR(mrb_expr);
+
+ if (!mrb_nil_p(mrb_options)) {
+ mrb_value mrb_result;
+ mrb_value mrb_operator;
+
+ mrb_result = mrb_hash_get(mrb, mrb_options,
+ mrb_symbol_value(mrb_intern_lit(mrb, "result")));
+ if (!mrb_nil_p(mrb_result)) {
+ result = DATA_PTR(mrb_result);
+ }
+
+ mrb_operator = mrb_hash_get(mrb, mrb_options,
+ mrb_symbol_value(mrb_intern_lit(mrb, "operator")));
+ if (!mrb_nil_p(mrb_operator)) {
+ operator = mrb_fixnum(mrb_operator);
+ }
+ }
+
+ result = grn_table_select(ctx, table, expr, result, operator);
+ grn_mrb_ctx_check(mrb);
+
+ return grn_mrb_value_from_grn_obj(mrb, result);
+}
+
+/* TODO: Fix memory leak on error */
+static mrb_value
+mrb_grn_table_sort(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ grn_obj *table;
+ grn_obj *result = NULL;
+ grn_table_sort_key *keys;
+ int i, n_keys;
+ int offset = 0;
+ int limit = -1;
+ mrb_value mrb_keys;
+ mrb_value mrb_options = mrb_nil_value();
+
+ table = DATA_PTR(self);
+ mrb_get_args(mrb, "o|H", &mrb_keys, &mrb_options);
+
+ mrb_keys = mrb_convert_type(mrb, mrb_keys,
+ MRB_TT_ARRAY, "Array", "to_ary");
+
+ n_keys = RARRAY_LEN(mrb_keys);
+ keys = GRN_MALLOCN(grn_table_sort_key, n_keys);
+ for (i = 0; i < n_keys; i++) {
+ mrb_value mrb_sort_options;
+ mrb_value mrb_sort_key;
+ mrb_value mrb_sort_order;
+
+ mrb_sort_options = RARRAY_PTR(mrb_keys)[i];
+ mrb_sort_key = mrb_hash_get(mrb, mrb_sort_options,
+ mrb_symbol_value(mrb_intern_lit(mrb, "key")));
+ switch (mrb_type(mrb_sort_key)) {
+ case MRB_TT_STRING :
+ keys[i].key = grn_obj_column(ctx, table,
+ RSTRING_PTR(mrb_sort_key),
+ RSTRING_LEN(mrb_sort_key));
+ break;
+ case MRB_TT_SYMBOL :
+ {
+ const char *name;
+ mrb_int name_length;
+ name = mrb_sym2name_len(mrb, mrb_symbol(mrb_sort_key), &name_length);
+ keys[i].key = grn_obj_column(ctx, table, name, name_length);
+ }
+ break;
+ default :
+ /* TODO: free */
+ mrb_raisef(mrb, E_ARGUMENT_ERROR,
+ "sort key must be string or symbol: %S",
+ mrb_sort_key);
+ break;
+ }
+
+ keys[i].flags = 0;
+ mrb_sort_order =
+ mrb_hash_get(mrb, mrb_sort_options,
+ mrb_symbol_value(mrb_intern_lit(mrb, "order")));
+ if (mrb_nil_p(mrb_sort_order) ||
+ (mrb_symbol(mrb_sort_order) == mrb_intern_lit(mrb, "ascending"))) {
+ keys[i].flags |= GRN_TABLE_SORT_ASC;
+ } else {
+ keys[i].flags |= GRN_TABLE_SORT_DESC;
+ }
+ }
+
+ if (!mrb_nil_p(mrb_options)) {
+ mrb_value mrb_offset;
+ mrb_value mrb_limit;
+
+ mrb_offset = mrb_hash_get(mrb, mrb_options,
+ mrb_symbol_value(mrb_intern_lit(mrb, "offset")));
+ if (!mrb_nil_p(mrb_offset)) {
+ offset = mrb_fixnum(mrb_offset);
+ }
+
+ mrb_limit = mrb_hash_get(mrb, mrb_options,
+ mrb_symbol_value(mrb_intern_lit(mrb, "limit")));
+ if (!mrb_nil_p(mrb_limit)) {
+ limit = mrb_fixnum(mrb_limit);
+ }
+ }
+
+ result = grn_table_create(ctx, NULL, 0, NULL, GRN_TABLE_NO_KEY,
+ NULL, table);
+ grn_table_sort(ctx, table, offset, limit, result, keys, n_keys);
+ for (i = 0; i < n_keys; i++) {
+ grn_obj_unlink(ctx, keys[i].key);
+ }
+ GRN_FREE(keys);
+ grn_mrb_ctx_check(mrb);
+
+ return grn_mrb_value_from_grn_obj(mrb, result);
+}
+
+void
+grn_mrb_table_init(grn_ctx *ctx)
+{
+ grn_mrb_data *data = &(ctx->impl->mrb);
+ mrb_state *mrb = data->state;
+ struct RClass *module = data->module;
+ struct RClass *object_class = data->object_class;
+ struct RClass *klass;
+
+ klass = mrb_define_class_under(mrb, module, "Table", object_class);
+ MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA);
+
+ mrb_define_method(mrb, klass, "locked?",
+ mrb_grn_table_is_locked, MRB_ARGS_NONE());
+
+ mrb_define_method(mrb, klass, "size",
+ mrb_grn_table_get_size, MRB_ARGS_NONE());
+ mrb_define_method(mrb, klass, "empty?",
+ mrb_grn_table_is_empty, MRB_ARGS_NONE());
+
+ mrb_define_method(mrb, klass, "select",
+ mrb_grn_table_select, MRB_ARGS_ARG(1, 1));
+ mrb_define_method(mrb, klass, "sort",
+ mrb_grn_table_sort, MRB_ARGS_ARG(1, 1));
+}
+#endif
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table.h
new file mode 100644
index 00000000000..000088fcf40
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table.h
@@ -0,0 +1,34 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef GRN_MRB_TABLE_H
+#define GRN_MRB_TABLE_H
+
+#include "../grn_ctx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void grn_mrb_table_init(grn_ctx *ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRN_MRB_TABLE_H */
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor.c
new file mode 100644
index 00000000000..660596070d3
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor.c
@@ -0,0 +1,211 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2014-2015 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "../grn_ctx_impl.h"
+
+#ifdef GRN_WITH_MRUBY
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/data.h>
+#include <mruby/string.h>
+#include <mruby/hash.h>
+
+#include "mrb_ctx.h"
+#include "mrb_table_cursor.h"
+
+static struct mrb_data_type mrb_grn_table_cursor_type = {
+ "Groonga::TableCursor",
+ NULL
+};
+
+typedef union {
+ int64_t time_value;
+} border_value_buffer;
+
+static void
+mrb_value_to_border_value(mrb_state *mrb,
+ const char *type,
+ mrb_value mrb_border_value,
+ border_value_buffer *buffer,
+ void **border_value,
+ unsigned int *border_value_size)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+
+ if (mrb_nil_p(mrb_border_value)) {
+ return;
+ }
+
+ switch (mrb_type(mrb_border_value)) {
+ case MRB_TT_STRING :
+ *border_value = RSTRING_PTR(mrb_border_value);
+ *border_value_size = RSTRING_LEN(mrb_border_value);
+ break;
+ default :
+ {
+ struct RClass *klass;
+
+ klass = mrb_class(mrb, mrb_border_value);
+ if (klass == ctx->impl->mrb.builtin.time_class) {
+ mrb_value mrb_sec;
+ mrb_value mrb_usec;
+
+ mrb_sec = mrb_funcall(mrb, mrb_border_value, "to_i", 0);
+ mrb_usec = mrb_funcall(mrb, mrb_border_value, "usec", 0);
+ buffer->time_value = GRN_TIME_PACK(mrb_fixnum(mrb_sec),
+ mrb_fixnum(mrb_usec));
+ *border_value = &(buffer->time_value);
+ *border_value_size = sizeof(buffer->time_value);
+ } else {
+ mrb_raisef(mrb, E_NOTIMP_ERROR,
+ "%s: only String and Time is supported for now: %S",
+ type,
+ mrb_border_value);
+ }
+ }
+ break;
+ }
+}
+
+static mrb_value
+mrb_grn_table_cursor_singleton_open_raw(mrb_state *mrb, mrb_value klass)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ mrb_value mrb_table;
+ mrb_value mrb_options = mrb_nil_value();
+ grn_table_cursor *table_cursor;
+ grn_obj *table;
+ void *min = NULL;
+ unsigned int min_size = 0;
+ border_value_buffer min_buffer;
+ void *max = NULL;
+ unsigned int max_size = 0;
+ border_value_buffer max_buffer;
+ int offset = 0;
+ int limit = -1;
+ int flags = 0;
+
+ mrb_get_args(mrb, "o|H", &mrb_table, &mrb_options);
+
+ table = DATA_PTR(mrb_table);
+ if (!mrb_nil_p(mrb_options)) {
+ mrb_value mrb_min;
+ mrb_value mrb_max;
+ mrb_value mrb_flags;
+
+ mrb_min = mrb_hash_get(mrb, mrb_options,
+ mrb_symbol_value(mrb_intern_lit(mrb, "min")));
+ mrb_value_to_border_value(mrb, "min", mrb_min, &min_buffer, &min, &min_size);
+
+ mrb_max = mrb_hash_get(mrb, mrb_options,
+ mrb_symbol_value(mrb_intern_lit(mrb, "max")));
+ mrb_value_to_border_value(mrb, "max", mrb_max, &max_buffer, &max, &max_size);
+
+ mrb_flags = mrb_hash_get(mrb, mrb_options,
+ mrb_symbol_value(mrb_intern_lit(mrb, "flags")));
+ if (!mrb_nil_p(mrb_flags)) {
+ flags = mrb_fixnum(mrb_flags);
+ }
+ }
+ table_cursor = grn_table_cursor_open(ctx, table,
+ min, min_size,
+ max, max_size,
+ offset, limit, flags);
+ grn_mrb_ctx_check(mrb);
+
+ return mrb_funcall(mrb, klass, "new", 1, mrb_cptr_value(mrb, table_cursor));
+}
+
+static mrb_value
+mrb_grn_table_cursor_initialize(mrb_state *mrb, mrb_value self)
+{
+ mrb_value mrb_table_cursor_ptr;
+
+ mrb_get_args(mrb, "o", &mrb_table_cursor_ptr);
+ DATA_TYPE(self) = &mrb_grn_table_cursor_type;
+ DATA_PTR(self) = mrb_cptr(mrb_table_cursor_ptr);
+
+ return self;
+}
+
+static mrb_value
+mrb_grn_table_cursor_close(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ grn_table_cursor *table_cursor;
+
+ table_cursor = DATA_PTR(self);
+ if (table_cursor) {
+ DATA_PTR(self) = NULL;
+ grn_table_cursor_close(ctx, table_cursor);
+ grn_mrb_ctx_check(mrb);
+ }
+
+ return mrb_nil_value();
+}
+
+static mrb_value
+mrb_grn_table_cursor_next(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ grn_id id;
+
+ id = grn_table_cursor_next(ctx, DATA_PTR(self));
+ grn_mrb_ctx_check(mrb);
+
+ return mrb_fixnum_value(id);
+}
+
+static mrb_value
+mrb_grn_table_cursor_count(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ int n_records = 0;
+
+ while (grn_table_cursor_next(ctx, DATA_PTR(self)) != GRN_ID_NIL) {
+ n_records++;
+ }
+
+ return mrb_fixnum_value(n_records);
+}
+
+void
+grn_mrb_table_cursor_init(grn_ctx *ctx)
+{
+ grn_mrb_data *data = &(ctx->impl->mrb);
+ mrb_state *mrb = data->state;
+ struct RClass *module = data->module;
+ struct RClass *klass;
+
+ klass = mrb_define_class_under(mrb, module, "TableCursor", mrb->object_class);
+ MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA);
+
+ mrb_define_singleton_method(mrb, (struct RObject *)klass, "open_raw",
+ mrb_grn_table_cursor_singleton_open_raw,
+ MRB_ARGS_ARG(1, 1));
+
+ mrb_define_method(mrb, klass, "initialize",
+ mrb_grn_table_cursor_initialize, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, klass, "close",
+ mrb_grn_table_cursor_close, MRB_ARGS_NONE());
+ mrb_define_method(mrb, klass, "next",
+ mrb_grn_table_cursor_next, MRB_ARGS_NONE());
+ mrb_define_method(mrb, klass, "count",
+ mrb_grn_table_cursor_count, MRB_ARGS_NONE());
+}
+#endif
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor.h
new file mode 100644
index 00000000000..f05ab0977a1
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor.h
@@ -0,0 +1,34 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef GRN_MRB_TABLE_CURSOR_H
+#define GRN_MRB_TABLE_CURSOR_H
+
+#include "../grn_ctx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void grn_mrb_table_cursor_init(grn_ctx *ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRN_MRB_TABLE_CURSOR_H */
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor_flags.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor_flags.c
new file mode 100644
index 00000000000..8b889fc5b47
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor_flags.c
@@ -0,0 +1,60 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "../grn_ctx_impl.h"
+
+#ifdef GRN_WITH_MRUBY
+#include <mruby.h>
+#include <mruby/class.h>
+
+#include "mrb_table_cursor_flags.h"
+
+void
+grn_mrb_table_cursor_flags_init(grn_ctx *ctx)
+{
+ grn_mrb_data *data = &(ctx->impl->mrb);
+ mrb_state *mrb = data->state;
+ struct RClass *module = data->module;
+ struct RClass *flags_module;
+
+ flags_module = mrb_define_module_under(mrb, module, "TableCursorFlags");
+
+ mrb_define_const(mrb, flags_module, "ASCENDING",
+ mrb_fixnum_value(GRN_CURSOR_ASCENDING));
+ mrb_define_const(mrb, flags_module, "DESCENDING",
+ mrb_fixnum_value(GRN_CURSOR_DESCENDING));
+ mrb_define_const(mrb, flags_module, "GE",
+ mrb_fixnum_value(GRN_CURSOR_GE));
+ mrb_define_const(mrb, flags_module, "GT",
+ mrb_fixnum_value(GRN_CURSOR_GT));
+ mrb_define_const(mrb, flags_module, "LE",
+ mrb_fixnum_value(GRN_CURSOR_LE));
+ mrb_define_const(mrb, flags_module, "LT",
+ mrb_fixnum_value(GRN_CURSOR_LT));
+ mrb_define_const(mrb, flags_module, "BY_KEY",
+ mrb_fixnum_value(GRN_CURSOR_BY_KEY));
+ mrb_define_const(mrb, flags_module, "BY_ID",
+ mrb_fixnum_value(GRN_CURSOR_BY_ID));
+ mrb_define_const(mrb, flags_module, "PREFIX",
+ mrb_fixnum_value(GRN_CURSOR_PREFIX));
+ mrb_define_const(mrb, flags_module, "SIZE_BY_BIT",
+ mrb_fixnum_value(GRN_CURSOR_SIZE_BY_BIT));
+ mrb_define_const(mrb, flags_module, "RK",
+ mrb_fixnum_value(GRN_CURSOR_RK));
+}
+#endif
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor_flags.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor_flags.h
new file mode 100644
index 00000000000..f336cde9325
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor_flags.h
@@ -0,0 +1,34 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef GRN_MRB_TABLE_CURSOR_FLAGS_H
+#define GRN_MRB_TABLE_CURSOR_FLAGS_H
+
+#include "../grn_ctx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void grn_mrb_table_cursor_flags_init(grn_ctx *ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRN_MRB_TABLE_CURSOR_FLAGS_H */
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_type.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_type.c
new file mode 100644
index 00000000000..9fe602e6c40
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_type.c
@@ -0,0 +1,60 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "../grn_ctx_impl.h"
+
+#ifdef GRN_WITH_MRUBY
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/data.h>
+
+#include "mrb_ctx.h"
+#include "mrb_type.h"
+
+static struct mrb_data_type mrb_grn_type_type = {
+ "Groonga::Type",
+ NULL
+};
+
+static mrb_value
+mrb_grn_type_initialize(mrb_state *mrb, mrb_value self)
+{
+ mrb_value mrb_type_ptr;
+
+ mrb_get_args(mrb, "o", &mrb_type_ptr);
+ DATA_TYPE(self) = &mrb_grn_type_type;
+ DATA_PTR(self) = mrb_cptr(mrb_type_ptr);
+ return self;
+}
+
+void
+grn_mrb_type_init(grn_ctx *ctx)
+{
+ grn_mrb_data *data = &(ctx->impl->mrb);
+ mrb_state *mrb = data->state;
+ struct RClass *module = data->module;
+ struct RClass *object_class = data->object_class;
+ struct RClass *klass;
+
+ klass = mrb_define_class_under(mrb, module, "Type", object_class);
+ MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA);
+
+ mrb_define_method(mrb, klass, "initialize",
+ mrb_grn_type_initialize, MRB_ARGS_REQ(1));
+}
+#endif
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_obj.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_type.h
index 31d53240f9e..f86167443a6 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_obj.h
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_type.h
@@ -1,6 +1,6 @@
/* -*- c-basic-offset: 2 -*- */
/*
- Copyright(C) 2013 Brazil
+ Copyright(C) 2014 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -16,19 +16,19 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef GRN_MRB_OBJ_H
-#define GRN_MRB_OBJ_H
+#ifndef GRN_MRB_TYPE_H
+#define GRN_MRB_TYPE_H
-#include "../ctx.h"
+#include "../grn_ctx.h"
#ifdef __cplusplus
extern "C" {
#endif
-void grn_mrb_obj_init(grn_ctx *ctx);
+void grn_mrb_type_init(grn_ctx *ctx);
#ifdef __cplusplus
}
#endif
-#endif /* GRN_MRB_OBJ_H */
+#endif /* GRN_MRB_TYPE_H */
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.c
index 9073b326f85..153b28066d8 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.c
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.c
@@ -16,7 +16,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "../ctx_impl.h"
+#include "../grn_ctx_impl.h"
#ifdef GRN_WITH_MRUBY
#include <mruby.h>
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.h
index d120f737671..c904e7023b1 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.h
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.h
@@ -19,7 +19,7 @@
#ifndef GRN_MRB_VARIABLE_SIZE_COLUMN_H
#define GRN_MRB_VARIABLE_SIZE_COLUMN_H
-#include "../ctx.h"
+#include "../grn_ctx.h"
#ifdef __cplusplus
extern "C" {
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_void.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_void.c
index 976c472be92..bdc451930f6 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_void.c
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_void.c
@@ -16,7 +16,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "../ctx_impl.h"
+#include "../grn_ctx_impl.h"
#ifdef GRN_WITH_MRUBY
#include <mruby.h>
@@ -24,7 +24,7 @@
#include <mruby/variable.h>
#include <mruby/data.h>
-#include "../db.h"
+#include "../grn_db.h"
#include "mrb_void.h"
static struct mrb_data_type mrb_grn_void_type = {
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_void.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_void.h
index a766cecb0b7..474d7804c73 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_void.h
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_void.h
@@ -19,7 +19,7 @@
#ifndef GRN_MRB_VOID_H
#define GRN_MRB_VOID_H
-#include "../ctx.h"
+#include "../grn_ctx.h"
#ifdef __cplusplus
extern "C" {
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_writer.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_writer.c
new file mode 100644
index 00000000000..e14073e5fe2
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_writer.c
@@ -0,0 +1,223 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2015 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "../grn_ctx_impl.h"
+
+#ifdef GRN_WITH_MRUBY
+#include <mruby.h>
+#include <mruby/data.h>
+#include <mruby/hash.h>
+#include <mruby/string.h>
+
+#include "../grn_mrb.h"
+#include "../grn_output.h"
+#include "mrb_ctx.h"
+#include "mrb_writer.h"
+
+static mrb_value
+writer_write(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ mrb_value target;
+
+ mrb_get_args(mrb, "o", &target);
+
+ switch (mrb_type(target)) {
+ case MRB_TT_FALSE :
+ GRN_OUTPUT_BOOL(GRN_FALSE);
+ break;
+ case MRB_TT_TRUE :
+ GRN_OUTPUT_BOOL(GRN_TRUE);
+ break;
+ case MRB_TT_FIXNUM :
+ GRN_OUTPUT_INT32(mrb_fixnum(target));
+ break;
+ case MRB_TT_FLOAT :
+ GRN_OUTPUT_FLOAT(mrb_float(target));
+ break;
+ case MRB_TT_STRING :
+ GRN_OUTPUT_STR(RSTRING_PTR(target), RSTRING_LEN(target));
+ break;
+ default :
+ mrb_raisef(mrb, E_ARGUMENT_ERROR,
+ "must be true, false, number, float or string: %S", target);
+ break;
+ }
+
+ return mrb_nil_value();
+}
+
+static mrb_value
+writer_open_array(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ char *name;
+ mrb_int n_elements;
+
+ mrb_get_args(mrb, "zi", &name, &n_elements);
+ GRN_OUTPUT_ARRAY_OPEN(name, n_elements);
+
+ return mrb_nil_value();
+}
+
+static mrb_value
+writer_close_array(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+
+ GRN_OUTPUT_ARRAY_CLOSE();
+
+ return mrb_nil_value();
+}
+
+static mrb_value
+writer_open_map(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ char *name;
+ mrb_int n_elements;
+
+ mrb_get_args(mrb, "zi", &name, &n_elements);
+ GRN_OUTPUT_MAP_OPEN(name, n_elements);
+
+ return mrb_nil_value();
+}
+
+static mrb_value
+writer_close_map(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+
+ GRN_OUTPUT_MAP_CLOSE();
+
+ return mrb_nil_value();
+}
+
+static mrb_value
+writer_write_table_columns(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ mrb_value mrb_table;
+ char *columns;
+ mrb_int columns_size;
+ grn_obj *table;
+ grn_obj_format format;
+ int n_hits = 0;
+ int offset = 0;
+ int limit = 0;
+ int hits_offset = 0;
+
+ mrb_get_args(mrb, "os", &mrb_table, &columns, &columns_size);
+
+ table = DATA_PTR(mrb_table);
+ GRN_OBJ_FORMAT_INIT(&format, n_hits, offset, limit, hits_offset);
+ format.flags |= GRN_OBJ_FORMAT_WITH_COLUMN_NAMES;
+ {
+ grn_rc rc;
+ rc = grn_output_format_set_columns(ctx, &format,
+ table, columns, columns_size);
+ if (rc != GRN_SUCCESS) {
+ GRN_OBJ_FORMAT_FIN(ctx, &format);
+ grn_mrb_ctx_check(mrb);
+ }
+ }
+ GRN_OUTPUT_TABLE_COLUMNS(table, &format);
+ GRN_OBJ_FORMAT_FIN(ctx, &format);
+
+ return mrb_nil_value();
+}
+
+static mrb_value
+writer_write_table_records(mrb_state *mrb, mrb_value self)
+{
+ grn_ctx *ctx = (grn_ctx *)mrb->ud;
+ mrb_value mrb_table;
+ mrb_value mrb_options = mrb_nil_value();
+ char *columns;
+ mrb_int columns_size;
+ grn_obj *table;
+ grn_obj_format format;
+ int n_hits = 0;
+ int offset = 0;
+ int limit = -1;
+ int hits_offset = 0;
+
+ mrb_get_args(mrb, "os|H", &mrb_table, &columns, &columns_size, &mrb_options);
+
+ table = DATA_PTR(mrb_table);
+ if (!mrb_nil_p(mrb_options)) {
+ mrb_value mrb_offset;
+ mrb_value mrb_limit;
+
+ mrb_offset = mrb_hash_get(mrb, mrb_options,
+ mrb_symbol_value(mrb_intern_lit(mrb, "offset")));
+ if (!mrb_nil_p(mrb_offset)) {
+ offset = mrb_fixnum(mrb_offset);
+ }
+
+ mrb_limit = mrb_hash_get(mrb, mrb_options,
+ mrb_symbol_value(mrb_intern_lit(mrb, "limit")));
+ if (!mrb_nil_p(mrb_limit)) {
+ limit = mrb_fixnum(mrb_limit);
+ }
+ }
+ if (limit < 0) {
+ limit = grn_table_size(ctx, table) + limit + 1;
+ }
+ GRN_OBJ_FORMAT_INIT(&format, n_hits, offset, limit, hits_offset);
+ {
+ grn_rc rc;
+ rc = grn_output_format_set_columns(ctx, &format,
+ table, columns, columns_size);
+ if (rc != GRN_SUCCESS) {
+ GRN_OBJ_FORMAT_FIN(ctx, &format);
+ grn_mrb_ctx_check(mrb);
+ }
+ }
+ GRN_OUTPUT_TABLE_RECORDS(table, &format);
+ GRN_OBJ_FORMAT_FIN(ctx, &format);
+
+ return mrb_nil_value();
+}
+
+void
+grn_mrb_writer_init(grn_ctx *ctx)
+{
+ grn_mrb_data *data = &(ctx->impl->mrb);
+ mrb_state *mrb = data->state;
+ struct RClass *module = data->module;
+ struct RClass *klass;
+
+ klass = mrb_define_class_under(mrb, module, "Writer", mrb->object_class);
+
+ mrb_define_method(mrb, klass, "write", writer_write, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, klass, "open_array",
+ writer_open_array, MRB_ARGS_REQ(2));
+ mrb_define_method(mrb, klass, "close_array",
+ writer_close_array, MRB_ARGS_NONE());
+ mrb_define_method(mrb, klass, "open_map",
+ writer_open_map, MRB_ARGS_REQ(2));
+ mrb_define_method(mrb, klass, "close_map",
+ writer_close_map, MRB_ARGS_NONE());
+
+ mrb_define_method(mrb, klass, "write_table_columns",
+ writer_write_table_columns, MRB_ARGS_REQ(2));
+ mrb_define_method(mrb, klass, "write_table_records",
+ writer_write_table_records, MRB_ARGS_ARG(2, 1));
+}
+#endif
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_writer.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_writer.h
new file mode 100644
index 00000000000..a6b4a6b3a75
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_writer.h
@@ -0,0 +1,34 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2015 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef GRN_MRB_WRITER_H
+#define GRN_MRB_WRITER_H
+
+#include "../grn_ctx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void grn_mrb_writer_init(grn_ctx *ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRN_MRB_WRITER_H */
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/command.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command.rb
new file mode 100644
index 00000000000..c4e3e94bc4e
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command.rb
@@ -0,0 +1,35 @@
+module Groonga
+ class Command
+ @@classes = {}
+ class << self
+ def register_class(name, klass)
+ @@classes[name] = klass
+ end
+
+ def find_class(name)
+ @@classes[name]
+ end
+ end
+
+ private
+ def context
+ @context ||= Context.instance
+ end
+
+ def writer
+ @writer ||= context.writer
+ end
+
+ def run_internal(input)
+ begin
+ run_body(input)
+ rescue GroongaError => groonga_error
+ context.set_groonga_error(groonga_error)
+ nil
+ rescue => error
+ context.record_error(:command_error, error)
+ nil
+ end
+ end
+ end
+end
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/grndb.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/grndb.rb
new file mode 100644
index 00000000000..96a99c80223
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/grndb.rb
@@ -0,0 +1,169 @@
+module Groonga
+ module CommandLine
+ class Grndb
+ def initialize(argv)
+ @command, *@arguments = argv
+ @succeeded = true
+ @executed = false
+ @database_path = nil
+ end
+
+ def run
+ slop = create_slop
+ rest = nil
+ begin
+ rest = slop.parse(@arguments)
+ rescue Slop::Error
+ $stderr.puts($!.message)
+ return false
+ end
+
+ if slop.help?
+ $stdout.puts(slop.help)
+ return true
+ end
+
+ unless @executed
+ if rest.empty?
+ $stderr.puts("No command is specified.")
+ else
+ $stderr.puts("Unknown command: <#{rest.first}>")
+ end
+ return false
+ end
+
+ @succeeded
+ end
+
+ private
+ def create_slop
+ slop = Slop.new
+ command_name = File.basename(@command)
+ slop.banner = "Usage: #{command_name} COMMAND [OPTIONS] DB_PATH"
+ slop_enable_help(slop)
+
+ slop.command "check" do |command|
+ command.description "Check database"
+ slop_enable_help(command)
+
+ command.run do |options, arguments|
+ run_command(options, arguments) do |database, new_arguments|
+ check(database, options, new_arguments)
+ end
+ end
+ end
+
+ slop.command "recover" do |command|
+ command.description "Recover database"
+ slop_enable_help(command)
+
+ command.run do |options, arguments|
+ run_command(options, arguments) do |database, new_arguments|
+ recover(database, options, new_arguments)
+ end
+ end
+ end
+
+ slop
+ end
+
+ def slop_enable_help(slop)
+ slop.on("-h", "--help", "Display this help message.", :tail => true)
+ end
+
+ def open_database(arguments)
+ if arguments.empty?
+ $stderr.puts("Database path is missing")
+ @succeesed = false
+ return
+ end
+
+ database = nil
+ @database_path, *rest_arguments = arguments
+ begin
+ database = Database.open(@database_path)
+ rescue Error => error
+ $stderr.puts("Failed to open database: <#{@database_path}>")
+ $stderr.puts(error.message)
+ @succeeded = false
+ return
+ end
+
+ begin
+ yield(database, rest_arguments)
+ ensure
+ database.close
+ end
+ end
+
+ def run_command(options, arguments)
+ @executed = true
+
+ if options.help?
+ $stdout.puts(options.help)
+ return
+ end
+
+ open_database(arguments) do |database|
+ yield(database)
+ end
+ end
+
+ def recover(database, options, arguments)
+ begin
+ database.recover
+ rescue Error => error
+ $stderr.puts("Failed to recover database: <#{@database_path}>")
+ $stderr.puts(error.message)
+ @succeeded = false
+ end
+ end
+
+ def check(database, options, arguments)
+ if database.locked?
+ message =
+ "Database is locked. " +
+ "It may be broken. " +
+ "Re-create the database."
+ $stdout.puts(message)
+ @succeeded = false
+ end
+
+ database.each do |object|
+ case object
+ when IndexColumn
+ next unless object.locked?
+ message =
+ "[#{object.name}] Index column is locked. " +
+ "It may be broken. " +
+ "Re-create index by '#{@command} recover #{@database_path}'."
+ $stdout.puts(message)
+ @succeeded = false
+ when Column
+ next unless object.locked?
+ name = object.name
+ message =
+ "[#{name}] Data column is locked. " +
+ "It may be broken. " +
+ "(1) Truncate the column (truncate #{name}) or " +
+ "clear lock of the column (lock_clear #{name}) " +
+ "and (2) load data again."
+ $stdout.puts(message)
+ @succeeded = false
+ when Table
+ next unless object.locked?
+ name = object.name
+ message =
+ "[#{name}] Table is locked. " +
+ "It may be broken. " +
+ "(1) Truncate the table (truncate #{name}) or " +
+ "clear lock of the table (lock_clear #{name}) " +
+ "and (2) load data again."
+ $stdout.puts(message)
+ @succeeded = false
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/context.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context.rb
index 8ebe2c913b4..e65d6653110 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/context.rb
+++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context.rb
@@ -1,3 +1,6 @@
+require "context/error_level"
+require "context/rc"
+
module Groonga
class Context
def guard(fallback=nil)
@@ -13,19 +16,37 @@ module Groonga
@logger ||= Logger.new
end
+ def writer
+ @writer ||= Writer.new
+ end
+
+ def set_groonga_error(groonga_error)
+ set_error_raw(groonga_error.class.rc,
+ ErrorLevel::ERROR,
+ groonga_error.message,
+ groonga_error.backtrace)
+ end
+
def record_error(rc, error)
rc = RC.find(rc) if rc.is_a?(Symbol)
+ set_error_raw(rc, ErrorLevel::ERROR, error.message, error.backtrace)
+
+ logger.log_error(error)
+ end
+
+ private
+ def set_error_raw(rc, error_level, message, backtrace)
self.rc = rc.to_i
- self.error_level = ErrorLevel.find(:error).to_i
+ self.error_level = error_level.to_i
- backtrace = error.backtrace
- entry = BacktraceEntry.parse(backtrace.first)
- self.error_file = entry.file
- self.error_line = entry.line
- self.error_method = entry.method
- self.error_message = error.message
+ self.error_message = message
- logger.log_error(error)
+ if backtrace
+ entry = BacktraceEntry.parse(backtrace.first)
+ self.error_file = entry.file
+ self.error_line = entry.line
+ self.error_method = entry.method
+ end
end
end
end
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/rc.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/rc.rb
index 2863c7f6195..f06b32d78b6 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/rc.rb
+++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/rc.rb
@@ -5,13 +5,19 @@ module Groonga
class << self
def find(name)
- @@names[name]
+ @@names[name] || UNKNOWN_ERROR
+ end
+
+ def register(name, code, error_class)
+ rc = new(name, code)
+ @@names[name] = rc
+ error_class.rc = rc if error_class
+ rc
end
end
attr_reader :name
def initialize(name, code)
- @@names[name] = self
@name = name
@code = code
end
@@ -20,80 +26,164 @@ module Groonga
@code
end
- SUCCESS = new(:success, 0)
- END_OF_DATA = new(:end_of_data, 1)
- UNKNOWN_ERROR = new(:unknown_error, -1)
- OPERATION_NOT_PERMITTED = new(:operation_not_permitted, -2)
- NO_SUCH_FILE_OR_DIRECTORY = new(:no_such_file_or_directory, -3)
- NO_SUCH_PROCESS = new(:no_such_process, -4)
- INTERRUPTED_FUNCTION_CALL = new(:interrupted_function_call, -5)
- INPUT_OUTPUT_ERROR = new(:input_output_error, -6)
- NO_SUCH_DEVICE_OR_ADDRESS = new(:no_such_device_or_address, -7)
- ARG_LIST_TOO_LONG = new(:arg_list_too_long, -8)
- EXEC_FORMAT_ERROR = new(:exec_format_error, -9)
- BAD_FILE_DESCRIPTOR = new(:bad_file_descriptor, -10)
- NO_CHILD_PROCESSES = new(:no_child_processes, -11)
- RESOURCE_TEMPORARILY_UNAVAILABLE = new(:resource_temporarily_unavailable, -12)
- NOT_ENOUGH_SPACE = new(:not_enough_space, -13)
- PERMISSION_DENIED = new(:permission_denied, -14)
- BAD_ADDRESS = new(:bad_address, -15)
- RESOURCE_BUSY = new(:resource_busy, -16)
- FILE_EXISTS = new(:file_exists, -17)
- IMPROPER_LINK = new(:improper_link, -18)
- NO_SUCH_DEVICE = new(:no_such_device, -19)
- NOT_A_DIRECTORY = new(:not_a_directory, -20)
- IS_A_DIRECTORY = new(:is_a_directory, -21)
- INVALID_ARGUMENT = new(:invalid_argument, -22)
- TOO_MANY_OPEN_FILES_IN_SYSTEM = new(:too_many_open_files_in_system, -23)
- TOO_MANY_OPEN_FILES = new(:too_many_open_files, -24)
- INAPPROPRIATE_IO_CONTROL_OPERATION = new(:inappropriate_io_control_operation, -25)
- FILE_TOO_LARGE = new(:file_too_large, -26)
- NO_SPACE_LEFT_ON_DEVICE = new(:no_space_left_on_device, -27)
- INVALID_SEEK = new(:invalid_seek, -28)
- READ_ONLY_FILE_SYSTEM = new(:read_only_file_system, -29)
- TOO_MANY_LINKS = new(:too_many_links, -30)
- BROKEN_PIPE = new(:broken_pipe, -31)
- DOMAIN_ERROR = new(:domain_error, -32)
- RESULT_TOO_LARGE = new(:result_too_large, -33)
- RESOURCE_DEADLOCK_AVOIDED = new(:resource_deadlock_avoided, -34)
- NO_MEMORY_AVAILABLE = new(:no_memory_available, -35)
- FILENAME_TOO_LONG = new(:filename_too_long, -36)
- NO_LOCKS_AVAILABLE = new(:no_locks_available, -37)
- FUNCTION_NOT_IMPLEMENTED = new(:function_not_implemented, -38)
- DIRECTORY_NOT_EMPTY = new(:directory_not_empty, -39)
- ILLEGAL_BYTE_SEQUENCE = new(:illegal_byte_sequence, -40)
- SOCKET_NOT_INITIALIZED = new(:socket_not_initialized, -41)
- OPERATION_WOULD_BLOCK = new(:operation_would_block, -42)
- ADDRESS_IS_NOT_AVAILABLE = new(:address_is_not_available, -43)
- NETWORK_IS_DOWN = new(:network_is_down, -44)
- NO_BUFFER = new(:no_buffer, -45)
- SOCKET_IS_ALREADY_CONNECTED = new(:socket_is_already_connected, -46)
- SOCKET_IS_NOT_CONNECTED = new(:socket_is_not_connected, -47)
- SOCKET_IS_ALREADY_SHUTDOWNED = new(:socket_is_already_shutdowned, -48)
- OPERATION_TIMEOUT = new(:operation_timeout, -49)
- CONNECTION_REFUSED = new(:connection_refused, -50)
- RANGE_ERROR = new(:range_error, -51)
- TOKENIZER_ERROR = new(:tokenizer_error, -52)
- FILE_CORRUPT = new(:file_corrupt, -53)
- INVALID_FORMAT = new(:invalid_format, -54)
- OBJECT_CORRUPT = new(:object_corrupt, -55)
- TOO_MANY_SYMBOLIC_LINKS = new(:too_many_symbolic_links, -56)
- NOT_SOCKET = new(:not_socket, -57)
- OPERATION_NOT_SUPPORTED = new(:operation_not_supported, -58)
- ADDRESS_IS_IN_USE = new(:address_is_in_use, -59)
- ZLIB_ERROR = new(:zlib_error, -60)
- LZO_ERROR = new(:lzo_error, -61)
- STACK_OVER_FLOW = new(:stack_over_flow, -62)
- SYNTAX_ERROR = new(:syntax_error, -63)
- RETRY_MAX = new(:retry_max, -64)
- INCOMPATIBLE_FILE_FORMAT = new(:incompatible_file_format, -65)
- UPDATE_NOT_ALLOWED = new(:update_not_allowed, -66)
- TOO_SMALL_OFFSET = new(:too_small_offset, -67)
- TOO_LARGE_OFFSET = new(:too_large_offset, -68)
- TOO_SMALL_LIMIT = new(:too_small_limit, -69)
- CAS_ERROR = new(:cas_error, -70)
- UNSUPPORTED_COMMAND_VERSION = new(:unsupported_command_version, -71)
- NORMALIZER_ERROR = new(:normalizer_error, -72)
+ SUCCESS =
+ register(:success, 0, nil)
+ END_OF_DATA =
+ register(:end_of_data, 1, EndOfData)
+ UNKNOWN_ERROR =
+ register(:unknown_error, -1, UnknownError)
+ OPERATION_NOT_PERMITTED =
+ register(:operation_not_permitted, -2, OperationNotPermitted)
+ NO_SUCH_FILE_OR_DIRECTORY =
+ register(:no_such_file_or_directory, -3, NoSuchFileOrDirectory)
+ NO_SUCH_PROCESS =
+ register(:no_such_process, -4, NoSuchProcess)
+ INTERRUPTED_FUNCTION_CALL =
+ register(:interrupted_function_call, -5, InterruptedFunctionCall)
+ INPUT_OUTPUT_ERROR =
+ register(:input_output_error, -6, InputOutputError)
+ NO_SUCH_DEVICE_OR_ADDRESS =
+ register(:no_such_device_or_address, -7, NoSuchDeviceOrAddress)
+ ARG_LIST_TOO_LONG =
+ register(:arg_list_too_long, -8, ArgListTooLong)
+ EXEC_FORMAT_ERROR =
+ register(:exec_format_error, -9, ExecFormatError)
+ BAD_FILE_DESCRIPTOR =
+ register(:bad_file_descriptor, -10, BadFileDescriptor)
+ NO_CHILD_PROCESSES =
+ register(:no_child_processes, -11, NoChildProcesses)
+ RESOURCE_TEMPORARILY_UNAVAILABLE =
+ register(:resource_temporarily_unavailable, -12,
+ ResourceTemporarilyUnavailable)
+ NOT_ENOUGH_SPACE =
+ register(:not_enough_space, -13, NotEnoughSpace)
+ PERMISSION_DENIED =
+ register(:permission_denied, -14, PermissionDenied)
+ BAD_ADDRESS =
+ register(:bad_address, -15, BadAddress)
+ RESOURCE_BUSY =
+ register(:resource_busy, -16, ResourceBusy)
+ FILE_EXISTS =
+ register(:file_exists, -17, FileExists)
+ IMPROPER_LINK =
+ register(:improper_link, -18, ImproperLink)
+ NO_SUCH_DEVICE =
+ register(:no_such_device, -19, NoSuchDevice)
+ NOT_DIRECTORY =
+ register(:not_directory, -20, NotDirectory)
+ IS_DIRECTORY =
+ register(:is_directory, -21, IsDirectory)
+ INVALID_ARGUMENT =
+ register(:invalid_argument, -22, InvalidArgument)
+ TOO_MANY_OPEN_FILES_IN_SYSTEM =
+ register(:too_many_open_files_in_system, -23, TooManyOpenFilesInSystem)
+ TOO_MANY_OPEN_FILES =
+ register(:too_many_open_files, -24, TooManyOpenFiles)
+ INAPPROPRIATE_IO_CONTROL_OPERATION =
+ register(:inappropriate_io_control_operation, -25,
+ InappropriateIOControlOperation)
+ FILE_TOO_LARGE =
+ register(:file_too_large, -26, FileTooLarge)
+ NO_SPACE_LEFT_ON_DEVICE =
+ register(:no_space_left_on_device, -27, NoSpaceLeftOnDevice)
+ INVALID_SEEK =
+ register(:invalid_seek, -28, InvalidSeek)
+ READ_ONLY_FILE_SYSTEM =
+ register(:read_only_file_system, -29, ReadOnlyFileSystem)
+ TOO_MANY_LINKS =
+ register(:too_many_links, -30, TooManyLinks)
+ BROKEN_PIPE =
+ register(:broken_pipe, -31, BrokenPipe)
+ DOMAIN_ERROR =
+ register(:domain_error, -32, DomainError)
+ RESULT_TOO_LARGE =
+ register(:result_too_large, -33, ResultTooLarge)
+ RESOURCE_DEADLOCK_AVOIDED =
+ register(:resource_deadlock_avoided, -34, ResourceDeadlockAvoided)
+ NO_MEMORY_AVAILABLE =
+ register(:no_memory_available, -35, NoMemoryAvailable)
+ FILENAME_TOO_LONG =
+ register(:filename_too_long, -36, FilenameTooLong)
+ NO_LOCKS_AVAILABLE =
+ register(:no_locks_available, -37, NoLocksAvailable)
+ FUNCTION_NOT_IMPLEMENTED =
+ register(:function_not_implemented, -38, FunctionNotImplemented)
+ DIRECTORY_NOT_EMPTY =
+ register(:directory_not_empty, -39, DirectoryNotEmpty)
+ ILLEGAL_BYTE_SEQUENCE =
+ register(:illegal_byte_sequence, -40, IllegalByteSequence)
+ SOCKET_NOT_INITIALIZED =
+ register(:socket_not_initialized, -41, SocketNotInitialized)
+ OPERATION_WOULD_BLOCK =
+ register(:operation_would_block, -42, OperationWouldBlock)
+ ADDRESS_IS_NOT_AVAILABLE =
+ register(:address_is_not_available, -43, AddressIsNotAvailable)
+ NETWORK_IS_DOWN =
+ register(:network_is_down, -44, NetworkIsDown)
+ NO_BUFFER =
+ register(:no_buffer, -45, NoBuffer)
+ SOCKET_IS_ALREADY_CONNECTED =
+ register(:socket_is_already_connected, -46, SocketIsAlreadyConnected)
+ SOCKET_IS_NOT_CONNECTED =
+ register(:socket_is_not_connected, -47, SocketIsNotConnected)
+ SOCKET_IS_ALREADY_SHUTDOWNED =
+ register(:socket_is_already_shutdowned, -48, SocketIsAlreadyShutdowned)
+ OPERATION_TIMEOUT =
+ register(:operation_timeout, -49, OperationTimeout)
+ CONNECTION_REFUSED =
+ register(:connection_refused, -50, ConnectionRefused)
+ RANGE_ERROR =
+ register(:range_error, -51, RangeError)
+ TOKENIZER_ERROR =
+ register(:tokenizer_error, -52, TokenizerError)
+ FILE_CORRUPT =
+ register(:file_corrupt, -53, FileCorrupt)
+ INVALID_FORMAT =
+ register(:invalid_format, -54, InvalidFormat)
+ OBJECT_CORRUPT =
+ register(:object_corrupt, -55, ObjectCorrupt)
+ TOO_MANY_SYMBOLIC_LINKS =
+ register(:too_many_symbolic_links, -56, TooManySymbolicLinks)
+ NOT_SOCKET =
+ register(:not_socket, -57, NotSocket)
+ OPERATION_NOT_SUPPORTED =
+ register(:operation_not_supported, -58, OperationNotSupported)
+ ADDRESS_IS_IN_USE =
+ register(:address_is_in_use, -59, AddressIsInUse)
+ ZLIB_ERROR =
+ register(:zlib_error, -60, ZlibError)
+ LZ4_ERROR =
+ register(:lz4_error, -61, LZ4Error)
+ STACK_OVER_FLOW =
+ register(:stack_over_flow, -62, StackOverFlow)
+ SYNTAX_ERROR =
+ register(:syntax_error, -63, SyntaxError)
+ RETRY_MAX =
+ register(:retry_max, -64, RetryMax)
+ INCOMPATIBLE_FILE_FORMAT =
+ register(:incompatible_file_format, -65, IncompatibleFileFormat)
+ UPDATE_NOT_ALLOWED =
+ register(:update_not_allowed, -66, UpdateNotAllowed)
+ TOO_SMALL_OFFSET =
+ register(:too_small_offset, -67, TooSmallOffset)
+ TOO_LARGE_OFFSET =
+ register(:too_large_offset, -68, TooLargeOffset)
+ TOO_SMALL_LIMIT =
+ register(:too_small_limit, -69, TooSmallLimit)
+ CAS_ERROR =
+ register(:cas_error, -70, CASError)
+ UNSUPPORTED_COMMAND_VERSION =
+ register(:unsupported_command_version, -71, UnsupportedCommandVersion)
+ NORMALIZER_ERROR =
+ register(:normalizer_error, -72, NormalizerError)
+ TOKEN_FILTER_ERROR =
+ register(:token_filter_error, -73, TokenFilterError)
+ COMMAND_ERROR =
+ register(:command_error, -74, CommandError)
+ PLUGIN_ERROR =
+ register(:plugin_error, -75, PluginError)
+
+ GroongaError.rc = UNKNOWN_ERROR
end
end
end
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/database.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/database.rb
new file mode 100644
index 00000000000..54d9dc1a631
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/database.rb
@@ -0,0 +1,39 @@
+module Groonga
+ class Database
+ def each
+ context = Context.instance
+ flags =
+ TableCursorFlags::ASCENDING |
+ TableCursorFlags::BY_ID
+ TableCursor.open(self, :flags => flags) do |cursor|
+ cursor.each do |id|
+ object = context[id]
+ yield(object) if object
+ end
+ end
+ end
+
+ def each_table(options={})
+ context = Context.instance
+ min = options[:prefix]
+ flags = 0
+ if options[:order] == :descending
+ flags |= TableCursorFlags::DESCENDING
+ else
+ flags |= TableCursorFlags::ASCENDING
+ end
+ if options[:order_by] == :id
+ flags |= TableCursorFlags::BY_ID
+ else
+ flags |= TableCursorFlags::BY_KEY
+ end
+ flags |= TableCursorFlags::PREFIX if min
+ TableCursor.open(self, :min => min, :flags => flags) do |cursor|
+ cursor.each do |id|
+ object = context[id]
+ yield(object) if object.is_a?(Table)
+ end
+ end
+ end
+ end
+end
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/error.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/error.rb
new file mode 100644
index 00000000000..e39c904534a
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/error.rb
@@ -0,0 +1,16 @@
+module Groonga
+ class GroongaError
+ class << self
+ def rc
+ @rc
+ end
+
+ def rc=(rc)
+ @rc = rc
+ end
+ end
+ end
+
+ class ErrorMessage < Error
+ end
+end
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/index_cursor.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/index_cursor.rb
new file mode 100644
index 00000000000..8044066930a
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/index_cursor.rb
@@ -0,0 +1,18 @@
+module Groonga
+ class IndexCursor
+ class << self
+ def open(*arguments)
+ cursor = open_raw(*arguments)
+ if block_given?
+ begin
+ yield(cursor)
+ ensure
+ cursor.close
+ end
+ else
+ cursor
+ end
+ end
+ end
+ end
+end
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/post.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/post.rb
new file mode 100644
index 00000000000..7110437c200
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/post.rb
@@ -0,0 +1,14 @@
+require "error"
+
+require "context"
+
+require "writer"
+
+require "database"
+require "command"
+require "table_cursor"
+require "index_cursor"
+
+require "plugin_loader"
+
+require "eval_context"
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/pre.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/pre.rb
new file mode 100644
index 00000000000..c9a74a80dd9
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/pre.rb
@@ -0,0 +1 @@
+require "backtrace_entry"
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger.rb
index 06f99c14fc3..33021355824 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger.rb
+++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger.rb
@@ -3,7 +3,11 @@ module Groonga
def log_error(error)
log_level = Level::ERROR.to_i
- message = "#{error.class}: #{error.message}"
+ if error.is_a?(Error)
+ message = error.message
+ else
+ message = "#{error.class}: #{error.message}"
+ end
backtrace = error.backtrace
first_raw_entry = backtrace.first
if first_raw_entry
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/plugin_loader.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/plugin_loader.rb
new file mode 100644
index 00000000000..09b972f120d
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/plugin_loader.rb
@@ -0,0 +1,14 @@
+module Groonga
+ class PluginLoader
+ class << self
+ def load_file(path)
+ begin
+ load(path)
+ rescue => error
+ Context.instance.record_error(:plugin_error, error)
+ nil
+ end
+ end
+ end
+ end
+end
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/require.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/require.rb
new file mode 100644
index 00000000000..a824e92fa51
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/require.rb
@@ -0,0 +1,68 @@
+$" = [__FILE__]
+
+class ScriptLoader
+ @@loading_paths = {}
+
+ def initialize(path)
+ @base_path = path
+ end
+
+ def load_once
+ if absolete_path?(@base_path)
+ loaded = load_once_path(@base_path)
+ if loaded.nil?
+ raise LoadError, error_message
+ else
+ loaded
+ end
+ else
+ $LOAD_PATH.each do |load_path|
+ unless absolete_path?(load_path)
+ load_path = File.expand_path(load_path)
+ end
+ loaded = load_once_path(File.join(load_path, @base_path))
+ return loaded unless loaded.nil?
+ end
+ raise LoadError, error_message
+ end
+ end
+
+ private
+ def error_message
+ "cannot load such file -- #{@base_path}"
+ end
+
+ def absolete_path?(path)
+ path.start_with?("/")
+ end
+
+ def load_once_path(path)
+ loaded = load_once_absolete_path(path)
+ return loaded unless loaded.nil?
+
+ return nil unless File.extname(path).empty?
+
+ load_once_absolete_path("#{path}.rb")
+ end
+
+ def load_once_absolete_path(path)
+ return false if $".include?(path)
+ return false if @@loading_paths.key?(path)
+
+ return nil unless File.file?(path)
+
+ @@loading_paths[path] = true
+ load(path)
+ $" << path
+ @@loading_paths.delete(path)
+
+ true
+ end
+end
+
+module Kernel
+ def require(path)
+ loader = ScriptLoader.new(path)
+ loader.load_once
+ end
+end
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info.rb
index cf0056d7fd3..64262f8f975 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info.rb
+++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info.rb
@@ -19,6 +19,9 @@ module Groonga
if data.similarity_threshold
self.similarity_threshold = data.similarity_threshold
end
+ if data.scorer
+ self.scorer = data.scorer
+ end
data.args.each do |arg|
push_arg(arg)
end
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_builder.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_builder.rb
index 5e258e90e5a..b002eaa14c0 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_builder.rb
+++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_builder.rb
@@ -41,6 +41,20 @@ module Groonga
Operator::TERM_EXTRACT,
]
+ ARITHMETIC_OPERATORS = [
+ Operator::BITWISE_OR,
+ Operator::BITWISE_XOR,
+ Operator::BITWISE_AND,
+ Operator::BITWISE_NOT,
+ Operator::SHIFTL,
+ Operator::SHIFTR,
+ Operator::SHIFTRR,
+ Operator::PLUS,
+ Operator::MINUS,
+ Operator::STAR,
+ Operator::MOD,
+ ]
+
LOGICAL_OPERATORS = [
Operator::AND,
Operator::OR,
@@ -89,7 +103,7 @@ module Groonga
status = Status::COL1
data.args << code.value
when Status::COL1
- raise "invalid expression: can't use column as a value: <#{code.value.name}>: <#{@expression.grn_inspect}>"
+ raise ErrorMessage, "invalid expression: can't use column as a value: <#{code.value.name}>: <#{@expression.grn_inspect}>"
status = Status::COL2
when Status::COL2
# Do nothing
@@ -114,7 +128,7 @@ module Groonga
first_data = @data_list.first
if (first_data.flags & ScanInfo::Flags::PUSH) == 0 or
first_data.logical_op != @operator
- raise "invalid expr"
+ raise ErrorMessage, "invalid expr"
else
first_data.flags &= ~ScanInfo::Flags::PUSH
first_data.logical_op = @operator
@@ -140,6 +154,11 @@ module Groonga
return false if status > Status::CONST
status = Status::START
n_relation_expressions += 1
+ when *ARITHMETIC_OPERATORS
+ return false if status < Status::COL1
+ return false if status > Status::CONST
+ status = Status::START
+ return false if n_relation_expressions != (n_logical_expressions + 1)
when *LOGICAL_OPERATORS
return false if status != Status::START
n_logical_expressions += 1
@@ -206,10 +225,12 @@ module Groonga
new_data.flags = ScanInfo::Flags::POP
new_data.logical_op = operator
@data_list << new_data
+ break
end
else
data.flags &= ~ScanInfo::Flags::PUSH
data.logical_op = operator
+ break
end
else
if n_dif_ops > 0
@@ -225,6 +246,7 @@ module Groonga
@data_list[r..-1] +
@data_list[j...r]
end
+ break
end
end
else
@@ -235,7 +257,7 @@ module Groonga
end
if j < 0
- raise GRN_INVALID_ARGUMENT.new("unmatched nesting level")
+ raise ErrorMessage, "unmatched nesting level"
end
end
end
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data.rb
index 67d0bc3aef7..b0ebfea3cee 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data.rb
+++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data.rb
@@ -10,6 +10,7 @@ module Groonga
attr_accessor :flags
attr_accessor :max_interval
attr_accessor :similarity_threshold
+ attr_accessor :scorer
def initialize(start)
@start = start
@end = 0
@@ -21,6 +22,7 @@ module Groonga
@flags = ScanInfo::Flags::PUSH
@max_interval = nil
@similarity_threshold = nil
+ @scorer = nil
end
def match_resolve_index
@@ -57,7 +59,7 @@ module Groonga
else
message =
"The first argument of NEAR/NEAR2 must be Expression, Accessor or Object: #{arg.class}"
- raise message
+ raise ErrorMessage, message
end
self.query = @args[1]
@@ -80,7 +82,7 @@ module Groonga
else
message =
"The first argument of SIMILAR must be Expression, Accessor or Object: #{arg.class}"
- raise message
+ raise ErrorMesesage, message
end
self.query = @args[1]
@@ -107,28 +109,47 @@ module Groonga
n_codes = codes.size
i = 0
while i < n_codes
- code = codes[i]
- value = code.value
- case value
- when Accessor
- match_resolve_index_expression_accessor(code)
- when FixedSizeColumn, VariableSizeColumn
- match_resolve_index_expression_data_column(code)
- when IndexColumn
- section_id = 0
- rest_n_codes = n_codes - i
- if rest_n_codes >= 2 and
- codes[i + 1].value.is_a?(Bulk) and
- codes[i + 1].value.domain == ID::UINT32 and
- codes[i + 2].op == Operator::GET_MEMBER
- section_id = codes[i + 1].value.value + 1
- code = codes[i + 2]
- i += 2
- end
- put_index(value, section_id, code.weight)
+ i = match_resolve_index_expression_codes(codes, i, n_codes)
+ end
+ end
+
+ def match_resolve_index_expression_codes(codes, i, n_codes)
+ code = codes[i]
+ value = code.value
+ case value
+ when Accessor
+ match_resolve_index_expression_accessor(code)
+ when FixedSizeColumn, VariableSizeColumn
+ match_resolve_index_expression_data_column(code)
+ when IndexColumn
+ section_id = 0
+ rest_n_codes = n_codes - i
+ if rest_n_codes >= 2 and
+ codes[i + 1].value.is_a?(Bulk) and
+ (codes[i + 1].value.domain == ID::UINT32 or
+ codes[i + 1].value.domain == ID::INT32) and
+ codes[i + 2].op == Operator::GET_MEMBER
+ section_id = codes[i + 1].value.value + 1
+ code = codes[i + 2]
+ i += 2
+ end
+ put_index(value, section_id, code.weight)
+ when Procedure
+ unless value.scorer?
+ message = "procedure must be scorer: #{scorer.name}>"
+ raise ErrorMessage, message
+ end
+ @scorer = value
+ rest_n_codes = n_codes - i
+ if rest_n_codes == 0
+ message = "match target is required as an argument: <#{scorer.name}>"
+ raise ErrorMessage, message
end
- i += 1
+ i = match_resolve_index_expression_codes(codes, i + 1, n_codes)
+ when Table
+ raise ErrorMessage, "invalid match target: <#{value.name}>"
end
+ i + 1
end
def match_resolve_index_expression_accessor(expr_code)
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/sources.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/sources.am
index 93ade1627e6..fa90c59ce23 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/sources.am
+++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/sources.am
@@ -1,13 +1,24 @@
RUBY_SCRIPT_FILES = \
backtrace_entry.rb \
+ command.rb \
+ command_line/grndb.rb \
context.rb \
context/error_level.rb \
context/rc.rb \
+ database.rb \
+ error.rb \
eval_context.rb \
expression.rb \
+ index_cursor.rb \
index_info.rb \
+ initialize/pre.rb \
+ initialize/post.rb \
logger.rb \
logger/level.rb \
+ plugin_loader.rb \
+ require.rb \
scan_info.rb \
scan_info_builder.rb \
- scan_info_data.rb
+ scan_info_data.rb \
+ table_cursor.rb \
+ writer.rb
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/table_cursor.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/table_cursor.rb
new file mode 100644
index 00000000000..a36d88d556d
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/table_cursor.rb
@@ -0,0 +1,26 @@
+module Groonga
+ class TableCursor
+ class << self
+ def open(*arguments)
+ cursor = open_raw(*arguments)
+ if block_given?
+ begin
+ yield(cursor)
+ ensure
+ cursor.close
+ end
+ else
+ cursor
+ end
+ end
+ end
+
+ def each
+ loop do
+ id = self.next
+ return if id == Groonga::ID::NIL
+ yield(id)
+ end
+ end
+ end
+end
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/writer.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/writer.rb
new file mode 100644
index 00000000000..de2bc2611e9
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/writer.rb
@@ -0,0 +1,21 @@
+module Groonga
+ class Writer
+ def array(name, n_elements)
+ open_array(name, n_elements)
+ begin
+ yield
+ ensure
+ close_array
+ end
+ end
+
+ def map(name, n_elements)
+ open_map(name, n_elements)
+ begin
+ yield
+ ensure
+ close_map
+ end
+ end
+ end
+end
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/sources.am b/storage/mroonga/vendor/groonga/lib/mrb/sources.am
index 947607c7ecd..c4f02fca639 100644
--- a/storage/mroonga/vendor/groonga/lib/mrb/sources.am
+++ b/storage/mroonga/vendor/groonga/lib/mrb/sources.am
@@ -1,33 +1,59 @@
libgrnmrb_la_SOURCES = \
mrb_accessor.c \
mrb_accessor.h \
+ mrb_array.c \
+ mrb_array.h \
mrb_bulk.c \
mrb_bulk.h \
mrb_column.c \
mrb_column.h \
+ mrb_command.c \
+ mrb_command.h \
+ mrb_command_input.c \
+ mrb_command_input.h \
mrb_converter.c \
mrb_converter.h \
mrb_ctx.c \
mrb_ctx.h \
+ mrb_database.c \
+ mrb_database.h \
+ mrb_double_array_trie.c \
+ mrb_double_array_trie.h \
mrb_error.c \
mrb_error.h \
mrb_expr.c \
mrb_expr.h \
mrb_fixed_size_column.c \
mrb_fixed_size_column.h \
+ mrb_hash_table.c \
+ mrb_hash_table.h \
mrb_id.c \
mrb_id.h \
mrb_index_column.c \
mrb_index_column.h \
+ mrb_index_cursor.c \
+ mrb_index_cursor.h \
mrb_logger.c \
mrb_logger.h \
- mrb_obj.c \
- mrb_obj.h \
+ mrb_object.c \
+ mrb_object.h \
mrb_operator.c \
mrb_operator.h \
+ mrb_patricia_trie.c \
+ mrb_patricia_trie.h \
mrb_procedure.c \
mrb_procedure.h \
+ mrb_table.c \
+ mrb_table.h \
+ mrb_table_cursor.c \
+ mrb_table_cursor.h \
+ mrb_table_cursor_flags.c \
+ mrb_table_cursor_flags.h \
+ mrb_type.c \
+ mrb_type.h \
mrb_variable_size_column.c \
mrb_variable_size_column.h \
mrb_void.c \
- mrb_void.h
+ mrb_void.h \
+ mrb_writer.c \
+ mrb_writer.h
diff --git a/storage/mroonga/vendor/groonga/lib/nfkc.c b/storage/mroonga/vendor/groonga/lib/nfkc.c
index 252fb210e6e..30e06f94a34 100644
--- a/storage/mroonga/vendor/groonga/lib/nfkc.c
+++ b/storage/mroonga/vendor/groonga/lib/nfkc.c
@@ -17,10 +17,7 @@
don't edit this file by hand. it generated automatically by nfkc.rb
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif /* HAVE_CONFIG_H */
-
+#include "grn.h"
#include <groonga/nfkc.h>
#ifdef GRN_WITH_NFKC
diff --git a/storage/mroonga/vendor/groonga/lib/normalizer.c b/storage/mroonga/vendor/groonga/lib/normalizer.c
index 04719bdd463..27d34a4850b 100644
--- a/storage/mroonga/vendor/groonga/lib/normalizer.c
+++ b/storage/mroonga/vendor/groonga/lib/normalizer.c
@@ -18,8 +18,8 @@
#include <string.h>
-#include "normalizer_in.h"
-#include "string_in.h"
+#include "grn_normalizer.h"
+#include "grn_string.h"
#include <groonga/normalizer.h>
#include <groonga/tokenizer.h>
diff --git a/storage/mroonga/vendor/groonga/lib/obj.c b/storage/mroonga/vendor/groonga/lib/obj.c
new file mode 100644
index 00000000000..87850b6357b
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/obj.c
@@ -0,0 +1,106 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2015 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#include "grn.h"
+#include "grn_db.h"
+#include <groonga/obj.h>
+
+grn_bool
+grn_obj_is_builtin(grn_ctx *ctx, grn_obj *obj)
+{
+ grn_id id;
+
+ if (!obj) { return GRN_FALSE; }
+
+ id = grn_obj_id(ctx, obj);
+ if (id == GRN_ID_NIL) {
+ return GRN_FALSE;
+ } else {
+ return id < GRN_N_RESERVED_TYPES;
+ }
+}
+
+grn_bool
+grn_obj_is_table(grn_ctx *ctx, grn_obj *obj)
+{
+ grn_bool is_table = GRN_FALSE;
+
+ if (!obj) {
+ return GRN_FALSE;
+ }
+
+ switch (obj->header.type) {
+ case GRN_TABLE_NO_KEY :
+ case GRN_TABLE_HASH_KEY :
+ case GRN_TABLE_PAT_KEY :
+ case GRN_TABLE_DAT_KEY :
+ is_table = GRN_TRUE;
+ default :
+ break;
+ }
+
+ return is_table;
+}
+
+grn_bool
+grn_obj_is_proc(grn_ctx *ctx, grn_obj *obj)
+{
+ if (!obj) {
+ return GRN_FALSE;
+ }
+
+ return obj->header.type == GRN_PROC;
+}
+
+grn_bool
+grn_obj_is_function_proc(grn_ctx *ctx, grn_obj *obj)
+{
+ grn_proc *proc;
+
+ if (!grn_obj_is_proc(ctx, obj)) {
+ return GRN_FALSE;
+ }
+
+ proc = (grn_proc *)obj;
+ return proc->type == GRN_PROC_FUNCTION;
+}
+
+grn_bool
+grn_obj_is_selector_proc(grn_ctx *ctx, grn_obj *obj)
+{
+ grn_proc *proc;
+
+ if (!grn_obj_is_function_proc(ctx, obj)) {
+ return GRN_FALSE;
+ }
+
+ proc = (grn_proc *)obj;
+ return proc->selector != NULL;
+}
+
+grn_bool
+grn_obj_is_scorer_proc(grn_ctx *ctx, grn_obj *obj)
+{
+ grn_proc *proc;
+
+ if (!grn_obj_is_proc(ctx, obj)) {
+ return GRN_FALSE;
+ }
+
+ proc = (grn_proc *)obj;
+ return proc->type == GRN_PROC_SCORER;
+}
diff --git a/storage/mroonga/vendor/groonga/lib/operator.c b/storage/mroonga/vendor/groonga/lib/operator.c
new file mode 100644
index 00000000000..27aa5df5819
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/operator.c
@@ -0,0 +1,596 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2014-2015 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "grn.h"
+#include "grn_db.h"
+#include "grn_str.h"
+
+#include <string.h>
+
+static const char *operator_names[] = {
+ "push",
+ "pop",
+ "nop",
+ "call",
+ "intern",
+ "get_ref",
+ "get_value",
+ "and",
+ "and_not",
+ "or",
+ "assign",
+ "star_assign",
+ "slash_assign",
+ "mod_assign",
+ "plus_assign",
+ "minus_assign",
+ "shiftl_assign",
+ "shiftr_assign",
+ "shiftrr_assign",
+ "and_assign",
+ "xor_assign",
+ "or_assign",
+ "jump",
+ "cjump",
+ "comma",
+ "bitwise_or",
+ "bitwise_xor",
+ "bitwise_and",
+ "bitwise_not",
+ "equal",
+ "not_equal",
+ "less",
+ "greater",
+ "less_equal",
+ "greater_equal",
+ "in",
+ "match",
+ "near",
+ "near2",
+ "similar",
+ "term_extract",
+ "shiftl",
+ "shiftr",
+ "shiftrr",
+ "plus",
+ "minus",
+ "star",
+ "slash",
+ "mod",
+ "delete",
+ "incr",
+ "decr",
+ "incr_post",
+ "decr_post",
+ "not",
+ "adjust",
+ "exact",
+ "lcp",
+ "partial",
+ "unsplit",
+ "prefix",
+ "suffix",
+ "geo_distance1",
+ "geo_distance2",
+ "geo_distance3",
+ "geo_distance4",
+ "geo_withinp5",
+ "geo_withinp6",
+ "geo_withinp8",
+ "obj_search",
+ "expr_get_var",
+ "table_create",
+ "table_select",
+ "table_sort",
+ "table_group",
+ "json_put",
+ "get_member"
+};
+
+const char *
+grn_operator_to_string(grn_operator op)
+{
+ if (GRN_OP_PUSH <= op && op <= GRN_OP_GET_MEMBER) {
+ return operator_names[op];
+ } else {
+ return "unknown";
+ }
+}
+
+#define DO_EQ_SUB do {\
+ switch (y->header.domain) {\
+ case GRN_DB_INT8 :\
+ r = (x_ == GRN_INT8_VALUE(y));\
+ break;\
+ case GRN_DB_UINT8 :\
+ r = (x_ == GRN_UINT8_VALUE(y));\
+ break;\
+ case GRN_DB_INT16 :\
+ r = (x_ == GRN_INT16_VALUE(y));\
+ break;\
+ case GRN_DB_UINT16 :\
+ r = (x_ == GRN_UINT16_VALUE(y));\
+ break;\
+ case GRN_DB_INT32 :\
+ r = (x_ == GRN_INT32_VALUE(y));\
+ break;\
+ case GRN_DB_UINT32 :\
+ r = (x_ == GRN_UINT32_VALUE(y));\
+ break;\
+ case GRN_DB_INT64 :\
+ r = (x_ == GRN_INT64_VALUE(y));\
+ break;\
+ case GRN_DB_TIME :\
+ r = (GRN_TIME_PACK(x_,0) == GRN_INT64_VALUE(y));\
+ break;\
+ case GRN_DB_UINT64 :\
+ r = (x_ == GRN_UINT64_VALUE(y));\
+ break;\
+ case GRN_DB_FLOAT :\
+ r = ((x_ <= GRN_FLOAT_VALUE(y)) && (x_ >= GRN_FLOAT_VALUE(y)));\
+ break;\
+ case GRN_DB_SHORT_TEXT :\
+ case GRN_DB_TEXT :\
+ case GRN_DB_LONG_TEXT :\
+ {\
+ const char *p_ = GRN_TEXT_VALUE(y);\
+ int i_ = grn_atoi(p_, p_ + GRN_TEXT_LEN(y), NULL);\
+ r = (x_ == i_);\
+ }\
+ break;\
+ default :\
+ r = GRN_FALSE;\
+ break;\
+ }\
+} while (0)
+
+#define DO_EQ(x,y,r) do {\
+ switch (x->header.domain) {\
+ case GRN_DB_VOID :\
+ r = GRN_FALSE;\
+ break;\
+ case GRN_DB_INT8 :\
+ {\
+ int8_t x_ = GRN_INT8_VALUE(x);\
+ DO_EQ_SUB;\
+ }\
+ break;\
+ case GRN_DB_UINT8 :\
+ {\
+ uint8_t x_ = GRN_UINT8_VALUE(x);\
+ DO_EQ_SUB;\
+ }\
+ break;\
+ case GRN_DB_INT16 :\
+ {\
+ int16_t x_ = GRN_INT16_VALUE(x);\
+ DO_EQ_SUB;\
+ }\
+ break;\
+ case GRN_DB_UINT16 :\
+ {\
+ uint16_t x_ = GRN_UINT16_VALUE(x);\
+ DO_EQ_SUB;\
+ }\
+ break;\
+ case GRN_DB_INT32 :\
+ {\
+ int32_t x_ = GRN_INT32_VALUE(x);\
+ DO_EQ_SUB;\
+ }\
+ break;\
+ case GRN_DB_UINT32 :\
+ {\
+ uint32_t x_ = GRN_UINT32_VALUE(x);\
+ DO_EQ_SUB;\
+ }\
+ break;\
+ case GRN_DB_INT64 :\
+ {\
+ int64_t x_ = GRN_INT64_VALUE(x);\
+ DO_EQ_SUB;\
+ }\
+ break;\
+ case GRN_DB_TIME :\
+ {\
+ int64_t x_ = GRN_INT64_VALUE(x);\
+ switch (y->header.domain) {\
+ case GRN_DB_INT32 :\
+ r = (x_ == GRN_TIME_PACK(GRN_INT32_VALUE(y), 0));\
+ break;\
+ case GRN_DB_UINT32 :\
+ r = (x_ == GRN_TIME_PACK(GRN_UINT32_VALUE(y), 0));\
+ break;\
+ case GRN_DB_INT64 :\
+ case GRN_DB_TIME :\
+ r = (x_ == GRN_INT64_VALUE(y));\
+ break;\
+ case GRN_DB_UINT64 :\
+ r = (x_ == GRN_UINT64_VALUE(y));\
+ break;\
+ case GRN_DB_FLOAT :\
+ r = (x_ == GRN_TIME_PACK(GRN_FLOAT_VALUE(y), 0));\
+ break;\
+ case GRN_DB_SHORT_TEXT :\
+ case GRN_DB_TEXT :\
+ case GRN_DB_LONG_TEXT :\
+ {\
+ grn_obj time_value_;\
+ GRN_TIME_INIT(&time_value_, 0);\
+ if (grn_obj_cast(ctx, y, &time_value_, GRN_FALSE) == GRN_SUCCESS) {\
+ r = (x_ == GRN_TIME_VALUE(&time_value_));\
+ } else {\
+ r = GRN_FALSE;\
+ }\
+ GRN_OBJ_FIN(ctx, &time_value_);\
+ }\
+ break;\
+ default :\
+ r = GRN_FALSE;\
+ break;\
+ }\
+ }\
+ break;\
+ case GRN_DB_UINT64 :\
+ {\
+ uint64_t x_ = GRN_UINT64_VALUE(x);\
+ DO_EQ_SUB;\
+ }\
+ break;\
+ case GRN_DB_FLOAT :\
+ {\
+ double x_ = GRN_FLOAT_VALUE(x);\
+ switch (y->header.domain) {\
+ case GRN_DB_INT32 :\
+ r = ((x_ <= GRN_INT32_VALUE(y)) && (x_ >= GRN_INT32_VALUE(y)));\
+ break;\
+ case GRN_DB_UINT32 :\
+ r = ((x_ <= GRN_UINT32_VALUE(y)) && (x_ >= GRN_UINT32_VALUE(y)));\
+ break;\
+ case GRN_DB_INT64 :\
+ case GRN_DB_TIME :\
+ r = ((x_ <= GRN_INT64_VALUE(y)) && (x_ >= GRN_INT64_VALUE(y)));\
+ break;\
+ case GRN_DB_UINT64 :\
+ r = ((x_ <= GRN_UINT64_VALUE(y)) && (x_ >= GRN_UINT64_VALUE(y)));\
+ break;\
+ case GRN_DB_FLOAT :\
+ r = ((x_ <= GRN_FLOAT_VALUE(y)) && (x_ >= GRN_FLOAT_VALUE(y)));\
+ break;\
+ case GRN_DB_SHORT_TEXT :\
+ case GRN_DB_TEXT :\
+ case GRN_DB_LONG_TEXT :\
+ {\
+ const char *p_ = GRN_TEXT_VALUE(y);\
+ int i_ = grn_atoi(p_, p_ + GRN_TEXT_LEN(y), NULL);\
+ r = (x_ <= i_ && x_ >= i_);\
+ }\
+ break;\
+ default :\
+ r = GRN_FALSE;\
+ break;\
+ }\
+ }\
+ break;\
+ case GRN_DB_SHORT_TEXT :\
+ case GRN_DB_TEXT :\
+ case GRN_DB_LONG_TEXT :\
+ if (GRN_DB_SHORT_TEXT <= y->header.domain && y->header.domain <= GRN_DB_LONG_TEXT) {\
+ uint32_t la = GRN_TEXT_LEN(x), lb = GRN_TEXT_LEN(y);\
+ r = (la == lb && !memcmp(GRN_TEXT_VALUE(x), GRN_TEXT_VALUE(y), lb));\
+ } else {\
+ const char *q_ = GRN_TEXT_VALUE(x);\
+ int x_ = grn_atoi(q_, q_ + GRN_TEXT_LEN(x), NULL);\
+ DO_EQ_SUB;\
+ }\
+ break;\
+ default :\
+ if ((x->header.domain == y->header.domain)) {\
+ r = (GRN_BULK_VSIZE(x) == GRN_BULK_VSIZE(y) &&\
+ !(memcmp(GRN_BULK_HEAD(x), GRN_BULK_HEAD(y), GRN_BULK_VSIZE(x))));\
+ } else {\
+ grn_obj dest;\
+ if (x->header.domain < y->header.domain) {\
+ GRN_OBJ_INIT(&dest, GRN_BULK, 0, y->header.domain);\
+ if (!grn_obj_cast(ctx, x, &dest, GRN_FALSE)) {\
+ r = (GRN_BULK_VSIZE(&dest) == GRN_BULK_VSIZE(y) &&\
+ !memcmp(GRN_BULK_HEAD(&dest), GRN_BULK_HEAD(y), GRN_BULK_VSIZE(y))); \
+ }\
+ } else {\
+ GRN_OBJ_INIT(&dest, GRN_BULK, 0, x->header.domain);\
+ if (!grn_obj_cast(ctx, y, &dest, GRN_FALSE)) {\
+ r = (GRN_BULK_VSIZE(&dest) == GRN_BULK_VSIZE(x) &&\
+ !memcmp(GRN_BULK_HEAD(&dest), GRN_BULK_HEAD(x), GRN_BULK_VSIZE(x))); \
+ }\
+ }\
+ GRN_OBJ_FIN(ctx, &dest);\
+ }\
+ break;\
+ }\
+} while (0)
+
+grn_bool
+grn_operator_exec_equal(grn_ctx *ctx, grn_obj *x, grn_obj *y)
+{
+ grn_bool r;
+ GRN_API_ENTER;
+ DO_EQ(x, y, r);
+ GRN_API_RETURN(r);
+}
+
+grn_bool
+grn_operator_exec_not_equal(grn_ctx *ctx, grn_obj *x, grn_obj *y)
+{
+ grn_bool r;
+ GRN_API_ENTER;
+ DO_EQ(x, y, r);
+ GRN_API_RETURN(!r);
+}
+
+#define DO_COMPARE_SUB_NUMERIC(y,op) do {\
+ switch ((y)->header.domain) {\
+ case GRN_DB_INT8 :\
+ r = (x_ op GRN_INT8_VALUE(y));\
+ break;\
+ case GRN_DB_UINT8 :\
+ r = (x_ op GRN_UINT8_VALUE(y));\
+ break;\
+ case GRN_DB_INT16 :\
+ r = (x_ op GRN_INT16_VALUE(y));\
+ break;\
+ case GRN_DB_UINT16 :\
+ r = (x_ op GRN_UINT16_VALUE(y));\
+ break;\
+ case GRN_DB_INT32 :\
+ r = (x_ op GRN_INT32_VALUE(y));\
+ break;\
+ case GRN_DB_UINT32 :\
+ r = (x_ op GRN_UINT32_VALUE(y));\
+ break;\
+ case GRN_DB_INT64 :\
+ r = (x_ op GRN_INT64_VALUE(y));\
+ break;\
+ case GRN_DB_TIME :\
+ r = (GRN_TIME_PACK(x_,0) op GRN_INT64_VALUE(y));\
+ break;\
+ case GRN_DB_UINT64 :\
+ r = (x_ op GRN_UINT64_VALUE(y));\
+ break;\
+ case GRN_DB_FLOAT :\
+ r = (x_ op GRN_FLOAT_VALUE(y));\
+ break;\
+ default :\
+ r = GRN_FALSE;\
+ break;\
+ }\
+} while (0)
+
+#define DO_COMPARE_SUB(op) do {\
+ switch (y->header.domain) {\
+ case GRN_DB_SHORT_TEXT :\
+ case GRN_DB_TEXT :\
+ case GRN_DB_LONG_TEXT :\
+ {\
+ grn_obj y_;\
+ GRN_OBJ_INIT(&y_, GRN_BULK, 0, x->header.domain);\
+ if (grn_obj_cast(ctx, y, &y_, GRN_FALSE)) {\
+ r = GRN_FALSE;\
+ } else {\
+ DO_COMPARE_SUB_NUMERIC(&y_, op);\
+ }\
+ GRN_OBJ_FIN(ctx, &y_);\
+ }\
+ break;\
+ default :\
+ DO_COMPARE_SUB_NUMERIC(y,op);\
+ break;\
+ }\
+} while (0)
+
+#define DO_COMPARE_BUILTIN(x,y,r,op) do {\
+ switch (x->header.domain) {\
+ case GRN_DB_INT8 :\
+ {\
+ int8_t x_ = GRN_INT8_VALUE(x);\
+ DO_COMPARE_SUB(op);\
+ }\
+ break;\
+ case GRN_DB_UINT8 :\
+ {\
+ uint8_t x_ = GRN_UINT8_VALUE(x);\
+ DO_COMPARE_SUB(op);\
+ }\
+ break;\
+ case GRN_DB_INT16 :\
+ {\
+ int16_t x_ = GRN_INT16_VALUE(x);\
+ DO_COMPARE_SUB(op);\
+ }\
+ break;\
+ case GRN_DB_UINT16 :\
+ {\
+ uint16_t x_ = GRN_UINT16_VALUE(x);\
+ DO_COMPARE_SUB(op);\
+ }\
+ break;\
+ case GRN_DB_INT32 :\
+ {\
+ int32_t x_ = GRN_INT32_VALUE(x);\
+ DO_COMPARE_SUB(op);\
+ }\
+ break;\
+ case GRN_DB_UINT32 :\
+ {\
+ uint32_t x_ = GRN_UINT32_VALUE(x);\
+ DO_COMPARE_SUB(op);\
+ }\
+ break;\
+ case GRN_DB_TIME :\
+ {\
+ int64_t x_ = GRN_INT64_VALUE(x);\
+ switch (y->header.domain) {\
+ case GRN_DB_INT32 :\
+ r = (x_ op GRN_TIME_PACK(GRN_INT32_VALUE(y), 0));\
+ break;\
+ case GRN_DB_UINT32 :\
+ r = (x_ op GRN_TIME_PACK(GRN_UINT32_VALUE(y), 0));\
+ break;\
+ case GRN_DB_INT64 :\
+ case GRN_DB_TIME :\
+ r = (x_ op GRN_INT64_VALUE(y));\
+ break;\
+ case GRN_DB_UINT64 :\
+ r = (x_ op GRN_UINT64_VALUE(y));\
+ break;\
+ case GRN_DB_FLOAT :\
+ r = (x_ op GRN_TIME_PACK(GRN_FLOAT_VALUE(y), 0));\
+ break;\
+ case GRN_DB_SHORT_TEXT :\
+ case GRN_DB_TEXT :\
+ case GRN_DB_LONG_TEXT :\
+ {\
+ grn_obj time_value_;\
+ GRN_TIME_INIT(&time_value_, 0);\
+ if (grn_obj_cast(ctx, y, &time_value_, GRN_FALSE) == GRN_SUCCESS) {\
+ r = (x_ op GRN_TIME_VALUE(&time_value_));\
+ } else {\
+ r = GRN_FALSE;\
+ }\
+ GRN_OBJ_FIN(ctx, &time_value_);\
+ }\
+ break;\
+ default :\
+ r = GRN_FALSE;\
+ break;\
+ }\
+ }\
+ break;\
+ case GRN_DB_INT64 :\
+ {\
+ int64_t x_ = GRN_INT64_VALUE(x);\
+ DO_COMPARE_SUB(op);\
+ }\
+ break;\
+ case GRN_DB_UINT64 :\
+ {\
+ uint64_t x_ = GRN_UINT64_VALUE(x);\
+ DO_COMPARE_SUB(op);\
+ }\
+ break;\
+ case GRN_DB_FLOAT :\
+ {\
+ double x_ = GRN_FLOAT_VALUE(x);\
+ DO_COMPARE_SUB(op);\
+ }\
+ break;\
+ case GRN_DB_SHORT_TEXT :\
+ case GRN_DB_TEXT :\
+ case GRN_DB_LONG_TEXT :\
+ if (GRN_DB_SHORT_TEXT <= y->header.domain && y->header.domain <= GRN_DB_LONG_TEXT) {\
+ int r_;\
+ uint32_t la = GRN_TEXT_LEN(x), lb = GRN_TEXT_LEN(y);\
+ if (la > lb) {\
+ if (!(r_ = memcmp(GRN_TEXT_VALUE(x), GRN_TEXT_VALUE(y), lb))) {\
+ r_ = 1;\
+ }\
+ } else {\
+ if (!(r_ = memcmp(GRN_TEXT_VALUE(x), GRN_TEXT_VALUE(y), la))) {\
+ r_ = la == lb ? 0 : -1;\
+ }\
+ }\
+ r = (r_ op 0);\
+ } else {\
+ const char *q_ = GRN_TEXT_VALUE(x);\
+ int x_ = grn_atoi(q_, q_ + GRN_TEXT_LEN(x), NULL);\
+ DO_COMPARE_SUB(op);\
+ }\
+ break;\
+ default :\
+ r = GRN_FALSE;\
+ break;\
+ }\
+} while (0)
+
+#define DO_COMPARE(x, y, r, op) do {\
+ if (x->header.domain >= GRN_N_RESERVED_TYPES) {\
+ grn_obj *table;\
+ table = grn_ctx_at(ctx, x->header.domain);\
+ switch (table->header.type) {\
+ case GRN_TABLE_HASH_KEY :\
+ case GRN_TABLE_PAT_KEY :\
+ {\
+ grn_obj key;\
+ int length;\
+ GRN_OBJ_INIT(&key, GRN_BULK, 0, table->header.domain);\
+ length = grn_table_get_key2(ctx, table, GRN_RECORD_VALUE(x), &key);\
+ if (length > 0) {\
+ grn_obj *x_original = x;\
+ x = &key;\
+ DO_COMPARE_BUILTIN((&key), y, r, op);\
+ x = x_original;\
+ } else {\
+ r = GRN_FALSE;\
+ }\
+ GRN_OBJ_FIN(ctx, &key);\
+ }\
+ break;\
+ default :\
+ r = GRN_FALSE;\
+ break;\
+ }\
+ grn_obj_unlink(ctx, table);\
+ } else {\
+ DO_COMPARE_BUILTIN(x, y, r, op);\
+ }\
+} while (0)
+
+grn_bool
+grn_operator_exec_less(grn_ctx *ctx, grn_obj *x, grn_obj *y)
+{
+ grn_bool r;
+ GRN_API_ENTER;
+ DO_COMPARE(x, y, r, <);
+ GRN_API_RETURN(r);
+}
+
+grn_bool
+grn_operator_exec_greater(grn_ctx *ctx, grn_obj *x, grn_obj *y)
+{
+ grn_bool r;
+ GRN_API_ENTER;
+ DO_COMPARE(x, y, r, >);
+ GRN_API_RETURN(r);
+}
+
+grn_bool
+grn_operator_exec_less_equal(grn_ctx *ctx, grn_obj *x, grn_obj *y)
+{
+ grn_bool r;
+ GRN_API_ENTER;
+ DO_COMPARE(x, y, r, <=);
+ GRN_API_RETURN(r);
+}
+
+grn_bool
+grn_operator_exec_greater_equal(grn_ctx *ctx, grn_obj *x, grn_obj *y)
+{
+ grn_bool r;
+ GRN_API_ENTER;
+ DO_COMPARE(x, y, r, >=);
+ GRN_API_RETURN(r);
+}
diff --git a/storage/mroonga/vendor/groonga/lib/output.c b/storage/mroonga/vendor/groonga/lib/output.c
index 9b745c89a01..20bd2a8694a 100644
--- a/storage/mroonga/vendor/groonga/lib/output.c
+++ b/storage/mroonga/vendor/groonga/lib/output.c
@@ -15,15 +15,13 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef GROONGA_IN_H
-#include "groonga_in.h"
-#endif /* GROONGA_IN_H */
+#include "grn.h"
#include <string.h>
-#include "str.h"
-#include "db.h"
-#include "util.h"
-#include "output.h"
+#include "grn_str.h"
+#include "grn_db.h"
+#include "grn_util.h"
+#include "grn_output.h"
#define LEVELS (&ctx->impl->levels)
#define DEPTH (GRN_BULK_VSIZE(LEVELS)>>2)
@@ -521,10 +519,10 @@ grn_text_atoj(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type,
buf.header.domain = DB_OBJ(a->obj)->range;
break;
case GRN_ACCESSOR_GET_SCORE :
- grn_obj_get_value(ctx, a->obj, id, &buf);
{
grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs);
- GRN_INT32_PUT(ctx, &buf, ri->score);
+ int32_t int32_score = ri->score;
+ GRN_INT32_PUT(ctx, &buf, int32_score);
}
buf.header.domain = GRN_DB_INT32;
break;
@@ -535,6 +533,42 @@ grn_text_atoj(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type,
}
buf.header.domain = GRN_DB_INT32;
break;
+ case GRN_ACCESSOR_GET_MAX :
+ {
+ grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs);
+ int64_t max;
+ max = grn_rset_recinfo_get_max(ctx, ri, a->obj);
+ GRN_INT64_PUT(ctx, &buf, max);
+ }
+ buf.header.domain = GRN_DB_INT64;
+ break;
+ case GRN_ACCESSOR_GET_MIN :
+ {
+ grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs);
+ int64_t min;
+ min = grn_rset_recinfo_get_min(ctx, ri, a->obj);
+ GRN_INT64_PUT(ctx, &buf, min);
+ }
+ buf.header.domain = GRN_DB_INT64;
+ break;
+ case GRN_ACCESSOR_GET_SUM :
+ {
+ grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs);
+ int64_t sum;
+ sum = grn_rset_recinfo_get_sum(ctx, ri, a->obj);
+ GRN_INT64_PUT(ctx, &buf, sum);
+ }
+ buf.header.domain = GRN_DB_INT64;
+ break;
+ case GRN_ACCESSOR_GET_AVG :
+ {
+ grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs);
+ double avg;
+ avg = grn_rset_recinfo_get_avg(ctx, ri, a->obj);
+ GRN_FLOAT_PUT(ctx, &buf, avg);
+ }
+ buf.header.domain = GRN_DB_FLOAT;
+ break;
case GRN_ACCESSOR_GET_COLUMN_VALUE :
if ((a->obj->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) == GRN_OBJ_COLUMN_VECTOR) {
if (a->next) {
@@ -1023,6 +1057,7 @@ grn_output_table_header(grn_ctx *ctx, grn_obj *outbuf,
grn_content_type output_type,
grn_obj *table, grn_obj_format *format)
{
+ if (format->nhits != -1) {
grn_output_array_open(ctx, outbuf, output_type, "NHITS", 1);
if (output_type == GRN_CONTENT_XML) {
grn_text_itoa(ctx, outbuf, format->nhits);
@@ -1030,6 +1065,7 @@ grn_output_table_header(grn_ctx *ctx, grn_obj *outbuf,
grn_output_int32(ctx, outbuf, output_type, format->nhits);
}
grn_output_array_close(ctx, outbuf, output_type);
+ }
}
static inline int
@@ -1105,6 +1141,20 @@ count_used_n_codes(grn_ctx *ctx, grn_expr_code *start, grn_expr_code *target)
return n_codes;
}
+static grn_bool
+is_score_accessor(grn_ctx *ctx, grn_obj *obj)
+{
+ grn_accessor *a;
+
+ if (obj->header.type != GRN_ACCESSOR) {
+ return GRN_FALSE;
+ }
+
+ for (a = (grn_accessor *)obj; a->next; a = a->next) {
+ }
+ return a->action == GRN_ACCESSOR_GET_SCORE;
+}
+
static inline void
grn_output_table_column(grn_ctx *ctx, grn_obj *outbuf,
grn_content_type output_type,
@@ -1112,11 +1162,18 @@ grn_output_table_column(grn_ctx *ctx, grn_obj *outbuf,
{
grn_output_array_open(ctx, outbuf, output_type, "COLUMN", 2);
if (column) {
- grn_id range_id;
+ grn_id range_id = GRN_ID_NIL;
GRN_BULK_REWIND(buf);
grn_column_name_(ctx, column, buf);
grn_output_obj(ctx, outbuf, output_type, buf, NULL);
- range_id = grn_obj_get_range(ctx, column);
+ if (column->header.type == GRN_COLUMN_INDEX) {
+ range_id = GRN_DB_UINT32;
+ } else if (is_score_accessor(ctx, column)) {
+ range_id = GRN_DB_INT32;
+ }
+ if (range_id == GRN_ID_NIL) {
+ range_id = grn_obj_get_range(ctx, column);
+ }
if (range_id == GRN_ID_NIL) {
grn_output_cstr(ctx, outbuf, output_type, "null");
} else {
@@ -1139,6 +1196,46 @@ grn_output_table_column(grn_ctx *ctx, grn_obj *outbuf,
}
static inline void
+grn_output_table_column_by_expression(grn_ctx *ctx, grn_obj *outbuf,
+ grn_content_type output_type,
+ grn_expr_code *code,
+ grn_expr_code *code_end,
+ grn_obj *buf)
+{
+ if (code_end <= code) {
+ grn_output_array_open(ctx, outbuf, output_type, "COLUMN", 2);
+ grn_output_null(ctx, outbuf, output_type);
+ grn_output_null(ctx, outbuf, output_type);
+ grn_output_array_close(ctx, outbuf, output_type);
+ return;
+ }
+
+ switch (code_end[-1].op) {
+ case GRN_OP_GET_MEMBER :
+ if ((code_end - code) == 3) {
+ grn_output_array_open(ctx, outbuf, output_type, "COLUMN", 2);
+
+ GRN_BULK_REWIND(buf);
+ grn_column_name_(ctx, code[0].value, buf);
+ GRN_TEXT_PUTC(ctx, buf, '[');
+ grn_inspect(ctx, buf, code[1].value);
+ GRN_TEXT_PUTC(ctx, buf, ']');
+
+ grn_output_obj(ctx, outbuf, output_type, buf, NULL);
+ grn_output_null(ctx, outbuf, output_type);
+
+ grn_output_array_close(ctx, outbuf, output_type);
+ } else {
+ grn_output_table_column(ctx, outbuf, output_type, code->value, buf);
+ }
+ break;
+ default :
+ grn_output_table_column(ctx, outbuf, output_type, code->value, buf);
+ break;
+ }
+}
+
+static inline void
grn_output_table_columns_by_expression(grn_ctx *ctx, grn_obj *outbuf,
grn_content_type output_type,
grn_obj *table, grn_obj_format *format,
@@ -1163,30 +1260,35 @@ grn_output_table_columns_by_expression(grn_ctx *ctx, grn_obj *outbuf,
}
have_comma = GRN_TRUE;
- code_start_offset = previous_comma_offset + 1;
if (is_first_comma) {
+ int n_used_codes;
int code_end_offset;
- int n_used_code;
- grn_output_table_column(ctx, outbuf, output_type,
- expr->codes[0].value, buf);
+ n_used_codes = count_used_n_codes(ctx, expr->codes, code - 1);
+ code_end_offset = code - expr->codes - n_used_codes;
- code_end_offset = code - expr->codes - code_start_offset - 1;
- n_used_code = count_used_n_codes(ctx,
- expr->codes,
- expr->codes + code_end_offset);
- code_start_offset = code_end_offset - n_used_code + 1;
+ grn_output_table_column_by_expression(ctx, outbuf, output_type,
+ expr->codes,
+ expr->codes + code_end_offset,
+ buf);
+ code_start_offset = code_end_offset;
is_first_comma = GRN_FALSE;
+ } else {
+ code_start_offset = previous_comma_offset + 1;
}
- grn_output_table_column(ctx, outbuf, output_type,
- expr->codes[code_start_offset].value, buf);
+ grn_output_table_column_by_expression(ctx, outbuf, output_type,
+ expr->codes + code_start_offset,
+ code,
+ buf);
previous_comma_offset = code - expr->codes;
}
if (!have_comma && expr->codes_curr > 0) {
- grn_output_table_column(ctx, outbuf, output_type,
- expr->codes[0].value, buf);
+ grn_output_table_column_by_expression(ctx, outbuf, output_type,
+ expr->codes,
+ code_end,
+ buf);
}
grn_output_array_close(ctx, outbuf, output_type);
@@ -1209,7 +1311,7 @@ grn_output_table_columns_by_columns(grn_ctx *ctx, grn_obj *outbuf,
grn_output_array_close(ctx, outbuf, output_type);
}
-static inline void
+void
grn_output_table_columns(grn_ctx *ctx, grn_obj *outbuf,
grn_content_type output_type,
grn_obj *table, grn_obj_format *format)
@@ -1322,7 +1424,7 @@ grn_output_table_records_by_columns(grn_ctx *ctx, grn_obj *outbuf,
}
}
-static inline void
+void
grn_output_table_records(grn_ctx *ctx, grn_obj *outbuf,
grn_content_type output_type,
grn_obj *table, grn_obj_format *format)
@@ -1925,3 +2027,51 @@ grn_output_envelope(grn_ctx *ctx,
break;
}
}
+
+static inline grn_bool
+is_output_columns_format_v1(grn_ctx *ctx,
+ const char *output_columns,
+ unsigned int output_columns_len)
+{
+ unsigned int i;
+
+ /* TODO: REMOVE ME. If new output_columns handler is marked as stable,
+ this check is removed. We need more error checks. */
+ if (grn_ctx_get_command_version(ctx) == GRN_COMMAND_VERSION_1) {
+ return GRN_TRUE;
+ }
+
+ for (i = 0; i < output_columns_len; i++) {
+ switch (output_columns[i]) {
+ case ',' :
+ case '(' :
+ case '[' :
+ return GRN_FALSE;
+ default :
+ break;
+ }
+ }
+
+ return GRN_TRUE;
+}
+
+grn_rc
+grn_output_format_set_columns(grn_ctx *ctx, grn_obj_format *format,
+ grn_obj *table,
+ const char *columns, int columns_len)
+{
+ grn_rc rc;
+
+ if (is_output_columns_format_v1(ctx, columns, columns_len)) {
+ rc = grn_obj_columns(ctx, table, columns, columns_len, &(format->columns));
+ } else {
+ grn_obj *variable;
+ GRN_EXPR_CREATE_FOR_QUERY(ctx, table, format->expression, variable);
+ rc = grn_expr_parse(ctx, format->expression,
+ columns, columns_len, NULL,
+ GRN_OP_MATCH, GRN_OP_AND,
+ GRN_EXPR_SYNTAX_OUTPUT_COLUMNS);
+ }
+
+ return rc;
+}
diff --git a/storage/mroonga/vendor/groonga/lib/pat.c b/storage/mroonga/vendor/groonga/lib/pat.c
index 5b03e6132e9..add8469a009 100644
--- a/storage/mroonga/vendor/groonga/lib/pat.c
+++ b/storage/mroonga/vendor/groonga/lib/pat.c
@@ -14,13 +14,13 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "groonga_in.h"
+#include "grn.h"
#include <string.h>
#include <limits.h>
-#include "pat.h"
-#include "output.h"
-#include "util.h"
-#include "normalizer_in.h"
+#include "grn_pat.h"
+#include "grn_output.h"
+#include "grn_util.h"
+#include "grn_normalizer.h"
#define GRN_PAT_DELETED (GRN_ID_MAX + 1)
@@ -749,16 +749,16 @@ _grn_pat_add(grn_ctx *ctx, grn_pat *pat, const uint8_t *key, uint32_t size, uint
return r;
}
-inline static int
+inline static grn_bool
chop(grn_ctx *ctx, grn_pat *pat, const char **key, const char *end, uint32_t *lkey)
{
size_t len = grn_charlen(ctx, *key, end);
if (len) {
*lkey += len;
*key += len;
- return **key;
+ return (end - *key) > 0;
} else {
- return 0;
+ return GRN_FALSE;
}
}
diff --git a/storage/mroonga/vendor/groonga/lib/plugin.c b/storage/mroonga/vendor/groonga/lib/plugin.c
index 3483cc9a5b0..7fd0fbd1971 100644
--- a/storage/mroonga/vendor/groonga/lib/plugin.c
+++ b/storage/mroonga/vendor/groonga/lib/plugin.c
@@ -1,6 +1,6 @@
/* -*- c-basic-offset: 2 -*- */
/*
- Copyright(C) 2012-2013 Brazil
+ Copyright(C) 2012-2015 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -15,22 +15,39 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "groonga_in.h"
-#include "groonga/plugin.h"
+#include "grn.h"
+#include <groonga/plugin.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
-#include "db.h"
-#include "plugin_in.h"
-#include "ctx_impl.h"
-#include "util.h"
+#include <sys/stat.h>
+#ifdef HAVE_DIRENT_H
+# include <dirent.h>
+#endif /* HAVE_DIRENT_H */
+
+#ifndef S_ISREG
+# ifdef _S_IFREG
+# define S_ISREG(mode) (mode & _S_IFREG)
+# endif /* _S_IFREG */
+#endif /* !S_ISREG */
+
+#include "grn_db.h"
+#include "grn_plugin.h"
+#include "grn_ctx_impl.h"
+#include "grn_util.h"
+
+#ifdef GRN_WITH_MRUBY
+# include <mruby.h>
+#endif /* GRN_WITH_MRUBY */
static grn_hash *grn_plugins = NULL;
static grn_critical_section grn_plugins_lock;
-#define PATHLEN(filename) (strlen(filename) + 1)
+#ifdef GRN_WITH_MRUBY
+static const char *grn_plugin_mrb_suffix = ".rb";
+#endif /* GRN_WITH_MRUBY */
#ifdef HAVE_DLFCN_H
# include <dlfcn.h>
@@ -71,7 +88,7 @@ grn_plugin_reference(grn_ctx *ctx, const char *filename)
grn_plugin **plugin = NULL;
CRITICAL_SECTION_ENTER(grn_plugins_lock);
- id = grn_hash_get(&grn_gctx, grn_plugins, filename, PATHLEN(filename),
+ id = grn_hash_get(&grn_gctx, grn_plugins, filename, strlen(filename),
(void **)&plugin);
if (plugin) {
(*plugin)->refcount++;
@@ -89,6 +106,10 @@ grn_plugin_path(grn_ctx *ctx, grn_id id)
const char *system_plugins_dir;
size_t system_plugins_dir_size;
+ if (id == GRN_ID_NIL) {
+ return NULL;
+ }
+
CRITICAL_SECTION_ENTER(grn_plugins_lock);
path = _grn_hash_key(&grn_gctx, grn_plugins, id, &key_size);
CRITICAL_SECTION_LEAVE(grn_plugins_lock);
@@ -114,7 +135,7 @@ grn_plugin_path(grn_ctx *ctx, grn_id id)
#define GRN_PLUGIN_FUNC_PREFIX "grn_plugin_impl_"
static grn_rc
-grn_plugin_call_init (grn_ctx *ctx, grn_id id)
+grn_plugin_call_init(grn_ctx *ctx, grn_id id)
{
grn_plugin *plugin;
if (!grn_hash_get_value(&grn_gctx, grn_plugins, id, &plugin)) {
@@ -126,6 +147,34 @@ grn_plugin_call_init (grn_ctx *ctx, grn_id id)
return GRN_SUCCESS;
}
+#ifdef GRN_WITH_MRUBY
+static grn_rc
+grn_plugin_call_register_mrb(grn_ctx *ctx, grn_id id, grn_plugin *plugin)
+{
+ grn_mrb_data *data = &(ctx->impl->mrb);
+ mrb_state *mrb = data->state;
+ struct RClass *module = data->module;
+ struct RClass *plugin_loader_class;
+ int arena_index;
+
+ {
+ int added;
+ grn_hash_add(ctx, ctx->impl->mrb.registered_plugins,
+ &id, sizeof(grn_id), NULL, &added);
+ if (!added) {
+ return ctx->rc;
+ }
+ }
+
+ arena_index = mrb_gc_arena_save(mrb);
+ plugin_loader_class = mrb_class_get_under(mrb, module, "PluginLoader");
+ mrb_funcall(mrb, mrb_obj_value(plugin_loader_class),
+ "load_file", 1, mrb_str_new_cstr(mrb, ctx->impl->plugin_path));
+ mrb_gc_arena_restore(mrb, arena_index);
+ return ctx->rc;
+}
+#endif /*GRN_WITH_MRUBY */
+
static grn_rc
grn_plugin_call_register(grn_ctx *ctx, grn_id id)
{
@@ -133,6 +182,11 @@ grn_plugin_call_register(grn_ctx *ctx, grn_id id)
if (!grn_hash_get_value(&grn_gctx, grn_plugins, id, &plugin)) {
return GRN_INVALID_ARGUMENT;
}
+#ifdef GRN_WITH_MRUBY
+ if (!plugin->dl) {
+ return grn_plugin_call_register_mrb(ctx, id, plugin);
+ }
+#endif /* GRN_WITH_MRUBY */
if (plugin->register_func) {
return plugin->register_func(ctx);
}
@@ -193,22 +247,63 @@ grn_plugin_initialize(grn_ctx *ctx, grn_plugin *plugin,
return ctx->rc;
}
+#ifdef GRN_WITH_MRUBY
+static grn_id
+grn_plugin_open_mrb(grn_ctx *ctx, const char *filename, size_t filename_size)
+{
+ grn_id id = GRN_ID_NIL;
+ grn_plugin **plugin = NULL;
+
+ id = grn_hash_add(&grn_gctx, grn_plugins, filename, filename_size,
+ (void **)&plugin, NULL);
+ if (!id) {
+ return id;
+ }
+
+ *plugin = GRN_GMALLOCN(grn_plugin, 1);
+ if (!*plugin) {
+ grn_hash_delete_by_id(&grn_gctx, grn_plugins, id, NULL);
+ return GRN_ID_NIL;
+ }
+
+ (*plugin)->dl = NULL;
+ (*plugin)->init_func = NULL;
+ (*plugin)->register_func = NULL;
+ (*plugin)->fin_func = NULL;
+ (*plugin)->refcount = 1;
+
+ return id;
+}
+#endif /* GRN_WITH_MRUBY */
+
grn_id
grn_plugin_open(grn_ctx *ctx, const char *filename)
{
- grn_id id;
+ grn_id id = GRN_ID_NIL;
grn_dl dl;
grn_plugin **plugin = NULL;
+ size_t filename_size;
+
+ filename_size = strlen(filename);
CRITICAL_SECTION_ENTER(grn_plugins_lock);
- if ((id = grn_hash_get(&grn_gctx, grn_plugins, filename, PATHLEN(filename),
+ if ((id = grn_hash_get(&grn_gctx, grn_plugins, filename, filename_size,
(void **)&plugin))) {
(*plugin)->refcount++;
goto exit;
}
+#ifdef GRN_WITH_MRUBY
+ if (filename_size > strlen(grn_plugin_mrb_suffix) &&
+ strcmp(filename + (filename_size - strlen(grn_plugin_mrb_suffix)),
+ grn_plugin_mrb_suffix) == 0) {
+ id = grn_plugin_open_mrb(ctx, filename, filename_size);
+ goto exit;
+ }
+#endif /* GRN_WITH_MRUBY */
+
if ((dl = grn_dl_open(filename))) {
- if ((id = grn_hash_add(&grn_gctx, grn_plugins, filename, PATHLEN(filename),
+ if ((id = grn_hash_add(&grn_gctx, grn_plugins, filename, filename_size,
(void **)&plugin, NULL))) {
*plugin = GRN_GMALLOCN(grn_plugin, 1);
if (*plugin) {
@@ -270,11 +365,13 @@ grn_plugin_close(grn_ctx *ctx, grn_id id)
rc = GRN_SUCCESS;
goto exit;
}
- grn_plugin_call_fin(ctx, id);
- if (!grn_dl_close(plugin->dl)) {
- const char *label;
- label = grn_dl_close_error_label();
- SERR(label);
+ if (plugin->dl) {
+ grn_plugin_call_fin(ctx, id);
+ if (!grn_dl_close(plugin->dl)) {
+ const char *label;
+ label = grn_dl_close_error_label();
+ SERR(label);
+ }
}
GRN_GFREE(plugin);
rc = grn_hash_delete_by_id(&grn_gctx, grn_plugins, id, NULL);
@@ -369,8 +466,8 @@ grn_plugin_register_by_path(grn_ctx *ctx, const char *path)
#ifdef WIN32
static char *win32_plugins_dir = NULL;
static char win32_plugins_dir_buffer[PATH_MAX];
-const char *
-grn_plugin_get_system_plugins_dir(void)
+static const char *
+grn_plugin_get_default_system_plugins_dir(void)
{
if (!win32_plugins_dir) {
const char *base_dir;
@@ -388,13 +485,126 @@ grn_plugin_get_system_plugins_dir(void)
}
#else /* WIN32 */
-const char *
-grn_plugin_get_system_plugins_dir(void)
+static const char *
+grn_plugin_get_default_system_plugins_dir(void)
{
return GRN_PLUGINS_DIR;
}
#endif /* WIN32 */
+const char *
+grn_plugin_get_system_plugins_dir(void)
+{
+ const char *plugins_dir;
+
+ plugins_dir = getenv("GRN_PLUGINS_DIR");
+ if (!plugins_dir) {
+ plugins_dir = grn_plugin_get_default_system_plugins_dir();
+ }
+
+ return plugins_dir;
+}
+
+static char *
+grn_plugin_find_path_raw(grn_ctx *ctx, const char *path)
+{
+ struct stat path_stat;
+
+ if (stat(path, &path_stat) != 0) {
+ return NULL;
+ }
+
+ if (!S_ISREG(path_stat.st_mode)) {
+ return NULL;
+ }
+
+ return GRN_STRDUP(path);
+}
+
+#if GRN_WITH_MRUBY
+static char *
+grn_plugin_find_path_mrb(grn_ctx *ctx, const char *path, size_t path_len)
+{
+ char mrb_path[PATH_MAX];
+ const char *mrb_suffix = grn_plugin_mrb_suffix;
+ size_t mrb_path_len;
+
+ mrb_path_len = path_len + strlen(mrb_suffix);
+ if (mrb_path_len >= PATH_MAX) {
+ ERR(GRN_FILENAME_TOO_LONG,
+ "too long plugin path: <%s%s>",
+ path, mrb_suffix);
+ return NULL;
+ }
+
+ strcpy(mrb_path, path);
+ strcat(mrb_path, mrb_suffix);
+ return grn_plugin_find_path_raw(ctx, mrb_path);
+}
+#else /* GRN_WITH_MRUBY */
+static char *
+grn_plugin_find_path_mrb(grn_ctx *ctx, const char *path, size_t path_len)
+{
+ return NULL;
+}
+#endif /* GRN_WITH_MRUBY */
+
+static char *
+grn_plugin_find_path_so(grn_ctx *ctx, const char *path, size_t path_len)
+{
+ char so_path[PATH_MAX];
+ const char *so_suffix;
+ size_t so_path_len;
+
+ so_suffix = grn_plugin_get_suffix();
+ so_path_len = path_len + strlen(so_suffix);
+ if (so_path_len >= PATH_MAX) {
+ ERR(GRN_FILENAME_TOO_LONG,
+ "too long plugin path: <%s%s>",
+ path, so_suffix);
+ return NULL;
+ }
+
+ strcpy(so_path, path);
+ strcat(so_path, so_suffix);
+ return grn_plugin_find_path_raw(ctx, so_path);
+}
+
+static char *
+grn_plugin_find_path_libs_so(grn_ctx *ctx, const char *path, size_t path_len)
+{
+ char libs_so_path[PATH_MAX];
+ const char *base_name;
+ const char *so_suffix;
+ const char *libs_path = "/.libs";
+ size_t libs_so_path_len;
+
+ base_name = strrchr(path, '/');
+ if (!base_name) {
+ return NULL;
+ }
+
+ so_suffix = grn_plugin_get_suffix();
+ libs_so_path_len =
+ base_name - path +
+ strlen(libs_path) +
+ strlen(base_name) +
+ strlen(so_suffix);
+ if (libs_so_path_len >= PATH_MAX) {
+ ERR(GRN_FILENAME_TOO_LONG,
+ "too long plugin path: <%.*s/.libs%s%s>",
+ (int)(base_name - path), path, base_name, so_suffix);
+ return NULL;
+ }
+
+ libs_so_path[0] = '\0';
+ strncat(libs_so_path, path, base_name - path);
+ strcat(libs_so_path, libs_path);
+ strcat(libs_so_path, base_name);
+ strcat(libs_so_path, so_suffix);
+ return grn_plugin_find_path_raw(ctx, libs_so_path);
+}
+
char *
grn_plugin_find_path(grn_ctx *ctx, const char *name)
{
@@ -402,8 +612,6 @@ grn_plugin_find_path(grn_ctx *ctx, const char *name)
char dir_last_char;
char path[PATH_MAX];
int name_length, max_name_length;
- FILE *plugin_file;
- char complemented_path[PATH_MAX], complemented_libs_path[PATH_MAX];
char *found_path = NULL;
size_t path_len;
@@ -411,10 +619,7 @@ grn_plugin_find_path(grn_ctx *ctx, const char *name)
if (name[0] == '/') {
path[0] = '\0';
} else {
- plugins_dir = getenv("GRN_PLUGINS_DIR");
- if (!plugins_dir) {
- plugins_dir = grn_plugin_get_system_plugins_dir();
- }
+ plugins_dir = grn_plugin_get_system_plugins_dir();
strcpy(path, plugins_dir);
dir_last_char = plugins_dir[strlen(path) - 1];
@@ -434,50 +639,34 @@ grn_plugin_find_path(grn_ctx *ctx, const char *name)
}
strcat(path, name);
- plugin_file = fopen(path, "r");
- if (plugin_file) {
- fclose(plugin_file);
- found_path = GRN_STRDUP(path);
- } else {
- path_len = strlen(path);
- path_len += strlen(grn_plugin_get_suffix());
- if (path_len >= PATH_MAX) {
- ERR(GRN_FILENAME_TOO_LONG,
- "too long plugin path: <%s%s>",
- path, grn_plugin_get_suffix());
- goto exit;
- }
- strcpy(complemented_path, path);
- strcat(complemented_path, grn_plugin_get_suffix());
- plugin_file = fopen(complemented_path, "r");
- if (plugin_file) {
- fclose(plugin_file);
- found_path = GRN_STRDUP(complemented_path);
- } else {
- const char *base_name;
-
- base_name = strrchr(path, '/');
- if (base_name) {
- path_len = base_name - path + strlen("/.libs") + strlen(base_name);
- path_len += strlen(grn_plugin_get_suffix());
- if (path_len >= PATH_MAX) {
- ERR(GRN_FILENAME_TOO_LONG,
- "too long plugin path: <%.*s/.libs%s%s>",
- (int)(base_name - path), path, base_name, grn_plugin_get_suffix());
- goto exit;
- }
- complemented_libs_path[0] = '\0';
- strncat(complemented_libs_path, path, base_name - path);
- strcat(complemented_libs_path, "/.libs");
- strcat(complemented_libs_path, base_name);
- strcat(complemented_libs_path, grn_plugin_get_suffix());
- plugin_file = fopen(complemented_libs_path, "r");
- if (plugin_file) {
- fclose(plugin_file);
- found_path = GRN_STRDUP(complemented_libs_path);
- }
- }
- }
+ found_path = grn_plugin_find_path_raw(ctx, path);
+ if (found_path) {
+ goto exit;
+ }
+
+ path_len = strlen(path);
+ found_path = grn_plugin_find_path_mrb(ctx, path, path_len);
+ if (found_path) {
+ goto exit;
+ }
+ if (ctx->rc) {
+ goto exit;
+ }
+
+ found_path = grn_plugin_find_path_so(ctx, path, path_len);
+ if (found_path) {
+ goto exit;
+ }
+ if (ctx->rc) {
+ goto exit;
+ }
+
+ found_path = grn_plugin_find_path_libs_so(ctx, path, path_len);
+ if (found_path) {
+ goto exit;
+ }
+ if (ctx->rc) {
+ goto exit;
}
exit :
@@ -503,10 +692,7 @@ grn_plugin_register(grn_ctx *ctx, const char *name)
prefix_separator = "";
suffix = "";
} else {
- prefix = getenv("GRN_PLUGINS_DIR");
- if (!prefix) {
- prefix = grn_plugin_get_system_plugins_dir();
- }
+ prefix = grn_plugin_get_system_plugins_dir();
if (prefix[strlen(prefix) - 1] != '/') {
prefix_separator = "/";
} else {
@@ -523,6 +709,57 @@ grn_plugin_register(grn_ctx *ctx, const char *name)
GRN_API_RETURN(rc);
}
+void
+grn_plugin_ensure_registered(grn_ctx *ctx, grn_obj *proc)
+{
+#ifdef GRN_WITH_MRUBY
+ grn_id plugin_id;
+ const char *plugin_path;
+ uint32_t key_size;
+ grn_plugin *plugin;
+ int value_size;
+
+ if (!ctx->impl->mrb.state) {
+ return;
+ }
+
+ if (!(proc->header.flags & GRN_OBJ_CUSTOM_NAME)) {
+ return;
+ }
+
+ {
+ grn_id id;
+ int added;
+ id = DB_OBJ(proc)->id;
+ grn_hash_add(ctx, ctx->impl->mrb.checked_procs,
+ &id, sizeof(grn_id), NULL, &added);
+ if (!added) {
+ return;
+ }
+ }
+
+ plugin_id = DB_OBJ(proc)->range;
+ CRITICAL_SECTION_ENTER(grn_plugins_lock);
+ plugin_path = _grn_hash_key(&grn_gctx, grn_plugins, plugin_id, &key_size);
+ if (plugin_path) {
+ value_size = grn_hash_get_value(&grn_gctx, grn_plugins, plugin_id, &plugin);
+ }
+ CRITICAL_SECTION_LEAVE(grn_plugins_lock);
+
+ if (!plugin_path) {
+ return;
+ }
+
+ if (plugin->dl) {
+ return;
+ }
+
+ ctx->impl->plugin_path = plugin_path;
+ grn_plugin_call_register_mrb(ctx, plugin_id, plugin);
+ ctx->impl->plugin_path = NULL;
+#endif /* GRN_WITH_MRUBY */
+}
+
void *
grn_plugin_malloc(grn_ctx *ctx, size_t size, const char *file, int line,
const char *func)
@@ -647,6 +884,12 @@ grn_plugin_proc_alloc(grn_ctx *ctx, grn_user_data *user_data,
}
grn_obj *
+grn_plugin_proc_get_vars(grn_ctx *ctx, grn_user_data *user_data)
+{
+ return grn_proc_get_vars(ctx, user_data);
+}
+
+grn_obj *
grn_plugin_proc_get_var(grn_ctx *ctx, grn_user_data *user_data,
const char *name, int name_size)
{
diff --git a/storage/mroonga/vendor/groonga/lib/proc.c b/storage/mroonga/vendor/groonga/lib/proc.c
index 37b7ae67d35..03deb0c4b70 100644
--- a/storage/mroonga/vendor/groonga/lib/proc.c
+++ b/storage/mroonga/vendor/groonga/lib/proc.c
@@ -1,6 +1,6 @@
/* -*- c-basic-offset: 2 -*- */
/*
- Copyright(C) 2009-2014 Brazil
+ Copyright(C) 2009-2015 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -16,17 +16,18 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "proc.h"
-#include "ii.h"
-#include "db.h"
-#include "util.h"
-#include "output.h"
-#include "pat.h"
-#include "geo.h"
-#include "token.h"
-#include "expr.h"
+#include "grn_proc.h"
+#include "grn_ii.h"
+#include "grn_db.h"
+#include "grn_util.h"
+#include "grn_output.h"
+#include "grn_pat.h"
+#include "grn_geo.h"
+#include "grn_token_cursor.h"
+#include "grn_expr.h"
#include <string.h>
+#include <float.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
@@ -395,7 +396,7 @@ grn_parse_query_flags(grn_ctx *ctx, const char *query_flags,
if (((query_flags_end - query_flags) >= (sizeof(#name) - 1)) &&\
(!memcmp(query_flags, #name, sizeof(#name) - 1))) {\
flags |= GRN_EXPR_ ## name;\
- query_flags += sizeof(#name);\
+ query_flags += sizeof(#name) - 1;\
continue;\
}
@@ -417,32 +418,6 @@ grn_parse_query_flags(grn_ctx *ctx, const char *query_flags,
return flags;
}
-static inline grn_bool
-is_output_columns_format_v1(grn_ctx *ctx,
- const char *output_columns,
- unsigned int output_columns_len)
-{
- unsigned int i;
-
- /* TODO: REMOVE ME. If new output_columns handler is marked as stable,
- this check is removed. We need more error checks. */
- if (grn_ctx_get_command_version(ctx) == GRN_COMMAND_VERSION_1) {
- return GRN_TRUE;
- }
-
- for (i = 0; i < output_columns_len; i++) {
- switch (output_columns[i]) {
- case ',' :
- case '(' :
- return GRN_FALSE;
- default :
- break;
- }
- }
-
- return GRN_TRUE;
-}
-
static int
grn_select_apply_adjuster_ensure_factor(grn_ctx *ctx, grn_obj *factor_object)
{
@@ -492,6 +467,7 @@ grn_select_apply_adjuster_adjust(grn_ctx *ctx, grn_obj *table, grn_obj *res,
{
grn_search_optarg options;
+ memset(&options, 0, sizeof(grn_search_optarg));
options.mode = GRN_OP_EXACT;
options.similarity_threshold = 0;
@@ -500,6 +476,7 @@ grn_select_apply_adjuster_adjust(grn_ctx *ctx, grn_obj *table, grn_obj *res,
options.vector_size = factor_value;
options.proc = NULL;
options.max_size = 0;
+ options.scorer = NULL;
grn_obj_search(ctx, index, value, res, GRN_OP_ADJUST, &options);
}
@@ -538,7 +515,335 @@ grn_select_apply_adjuster(grn_ctx *ctx, grn_obj *table, grn_obj *res,
}
}
-grn_rc
+static void
+grn_select_output_columns(grn_ctx *ctx, grn_obj *res,
+ int n_hits, int offset, int limit,
+ const char *columns, int columns_len,
+ grn_obj *condition)
+{
+ grn_rc rc;
+ grn_obj_format format;
+
+ GRN_OBJ_FORMAT_INIT(&format, n_hits, offset, limit, offset);
+ format.flags =
+ GRN_OBJ_FORMAT_WITH_COLUMN_NAMES|
+ GRN_OBJ_FORMAT_XML_ELEMENT_RESULTSET;
+ rc = grn_output_format_set_columns(ctx, &format, res, columns, columns_len);
+ /* TODO: check rc */
+ if (format.expression) {
+ grn_obj *condition_ptr;
+ condition_ptr =
+ grn_expr_get_or_add_var(ctx, format.expression,
+ GRN_SELECT_INTERNAL_VAR_CONDITION,
+ strlen(GRN_SELECT_INTERNAL_VAR_CONDITION));
+ GRN_PTR_INIT(condition_ptr, 0, GRN_DB_OBJECT);
+ GRN_PTR_SET(ctx, condition_ptr, condition);
+ }
+ GRN_OUTPUT_OBJ(res, &format);
+ GRN_OBJ_FORMAT_FIN(ctx, &format);
+}
+
+typedef struct {
+ const char *label;
+ unsigned int label_len;
+ const char *keys;
+ unsigned int keys_len;
+ const char *sortby;
+ unsigned int sortby_len;
+ const char *output_columns;
+ unsigned int output_columns_len;
+ int offset;
+ int limit;
+ grn_table_group_flags calc_types;
+ const char *calc_target_name;
+ unsigned int calc_target_name_len;
+} drilldown_info;
+
+static grn_table_group_flags
+grn_parse_table_group_calc_types(grn_ctx *ctx,
+ const char *calc_types,
+ unsigned int calc_types_len)
+{
+ grn_table_group_flags flags = 0;
+ const char *calc_types_end = calc_types + calc_types_len;
+
+ while (calc_types < calc_types_end) {
+ if (*calc_types == ',' || *calc_types == ' ') {
+ calc_types += 1;
+ continue;
+ }
+
+#define CHECK_TABLE_GROUP_CALC_TYPE(name)\
+ if (((calc_types_end - calc_types) >= (sizeof(#name) - 1)) &&\
+ (!memcmp(calc_types, #name, sizeof(#name) - 1))) {\
+ flags |= GRN_TABLE_GROUP_CALC_ ## name;\
+ calc_types += sizeof(#name) - 1;\
+ continue;\
+ }
+
+ CHECK_TABLE_GROUP_CALC_TYPE(COUNT);
+ CHECK_TABLE_GROUP_CALC_TYPE(MAX);
+ CHECK_TABLE_GROUP_CALC_TYPE(MIN);
+ CHECK_TABLE_GROUP_CALC_TYPE(SUM);
+ CHECK_TABLE_GROUP_CALC_TYPE(AVG);
+
+#define GRN_TABLE_GROUP_CALC_NONE 0
+ CHECK_TABLE_GROUP_CALC_TYPE(NONE);
+#undef GRN_TABLE_GROUP_CALC_NONE
+
+ ERR(GRN_INVALID_ARGUMENT, "invalid table group calc type: <%.*s>",
+ (int)(calc_types_end - calc_types), calc_types);
+ return 0;
+#undef CHECK_TABLE_GROUP_CALC_TYPE
+ }
+
+ return flags;
+}
+
+static void
+drilldown_info_fill(grn_ctx *ctx,
+ drilldown_info *drilldown,
+ grn_obj *keys,
+ grn_obj *sortby,
+ grn_obj *output_columns,
+ grn_obj *offset,
+ grn_obj *limit,
+ grn_obj *calc_types,
+ grn_obj *calc_target)
+{
+ if (keys) {
+ drilldown->keys = GRN_TEXT_VALUE(keys);
+ drilldown->keys_len = GRN_TEXT_LEN(keys);
+ } else {
+ drilldown->keys = NULL;
+ drilldown->keys_len = 0;
+ }
+
+ if (sortby) {
+ drilldown->sortby = GRN_TEXT_VALUE(sortby);
+ drilldown->sortby_len = GRN_TEXT_LEN(sortby);
+ } else {
+ drilldown->sortby = NULL;
+ drilldown->sortby_len = 0;
+ }
+
+ if (output_columns) {
+ drilldown->output_columns = GRN_TEXT_VALUE(output_columns);
+ drilldown->output_columns_len = GRN_TEXT_LEN(output_columns);
+ } else {
+ drilldown->output_columns = NULL;
+ drilldown->output_columns_len = 0;
+ }
+ if (!drilldown->output_columns_len) {
+ drilldown->output_columns = DEFAULT_DRILLDOWN_OUTPUT_COLUMNS;
+ drilldown->output_columns_len = strlen(DEFAULT_DRILLDOWN_OUTPUT_COLUMNS);
+ }
+
+ if (offset && GRN_TEXT_LEN(offset)) {
+ drilldown->offset =
+ grn_atoi(GRN_TEXT_VALUE(offset), GRN_BULK_CURR(offset), NULL);
+ } else {
+ drilldown->offset = 0;
+ }
+
+ if (limit && GRN_TEXT_LEN(limit)) {
+ drilldown->limit =
+ grn_atoi(GRN_TEXT_VALUE(limit), GRN_BULK_CURR(limit), NULL);
+ } else {
+ drilldown->limit = DEFAULT_DRILLDOWN_LIMIT;
+ }
+
+ if (calc_types && GRN_TEXT_LEN(calc_types)) {
+ drilldown->calc_types =
+ grn_parse_table_group_calc_types(ctx,
+ GRN_TEXT_VALUE(calc_types),
+ GRN_TEXT_LEN(calc_types));
+ } else {
+ drilldown->calc_types = 0;
+ }
+
+ if (calc_target && GRN_TEXT_LEN(calc_target)) {
+ drilldown->calc_target_name = GRN_TEXT_VALUE(calc_target);
+ drilldown->calc_target_name_len = GRN_TEXT_LEN(calc_target);
+ } else {
+ drilldown->calc_target_name = NULL;
+ drilldown->calc_target_name_len = 0;
+ }
+}
+
+static void
+grn_select_drilldown(grn_ctx *ctx, grn_obj *table,
+ grn_table_sort_key *keys, uint32_t n_keys,
+ drilldown_info *drilldown)
+{
+ uint32_t i;
+ for (i = 0; i < n_keys; i++) {
+ grn_table_group_result g = {NULL, 0, 0, 1, GRN_TABLE_GROUP_CALC_COUNT, 0};
+ uint32_t n_hits;
+ int offset;
+ int limit;
+
+ if (drilldown->calc_target_name) {
+ g.calc_target = grn_obj_column(ctx, table,
+ drilldown->calc_target_name,
+ drilldown->calc_target_name_len);
+ }
+ if (g.calc_target) {
+ g.flags |= drilldown->calc_types;
+ }
+
+ grn_table_group(ctx, table, &keys[i], 1, &g, 1);
+ if (ctx->rc != GRN_SUCCESS) {
+ break;
+ }
+ n_hits = grn_table_size(ctx, g.table);
+
+ offset = drilldown->offset;
+ limit = drilldown->limit;
+ grn_normalize_offset_and_limit(ctx, n_hits, &offset, &limit);
+
+ if (drilldown->sortby_len) {
+ grn_table_sort_key *sort_keys;
+ uint32_t n_sort_keys;
+ sort_keys = grn_table_sort_key_from_str(ctx,
+ drilldown->sortby,
+ drilldown->sortby_len,
+ g.table, &n_sort_keys);
+ if (sort_keys) {
+ grn_obj *sorted;
+ sorted = grn_table_create(ctx, NULL, 0, NULL, GRN_OBJ_TABLE_NO_KEY,
+ NULL, g.table);
+ if (sorted) {
+ grn_obj_format format;
+ grn_table_sort(ctx, g.table, offset, limit,
+ sorted, sort_keys, n_sort_keys);
+ GRN_OBJ_FORMAT_INIT(&format, n_hits, 0, limit, offset);
+ format.flags =
+ GRN_OBJ_FORMAT_WITH_COLUMN_NAMES|
+ GRN_OBJ_FORMAT_XML_ELEMENT_NAVIGATIONENTRY;
+ grn_obj_columns(ctx, sorted,
+ drilldown->output_columns,
+ drilldown->output_columns_len,
+ &format.columns);
+ GRN_OUTPUT_OBJ(sorted, &format);
+ GRN_OBJ_FORMAT_FIN(ctx, &format);
+ grn_obj_unlink(ctx, sorted);
+ }
+ grn_table_sort_key_close(ctx, sort_keys, n_sort_keys);
+ }
+ } else {
+ grn_obj_format format;
+ GRN_OBJ_FORMAT_INIT(&format, n_hits, offset, limit, offset);
+ format.flags =
+ GRN_OBJ_FORMAT_WITH_COLUMN_NAMES|
+ GRN_OBJ_FORMAT_XML_ELEMENT_NAVIGATIONENTRY;
+ grn_obj_columns(ctx, g.table,
+ drilldown->output_columns,
+ drilldown->output_columns_len,
+ &format.columns);
+ GRN_OUTPUT_OBJ(g.table, &format);
+ GRN_OBJ_FORMAT_FIN(ctx, &format);
+ }
+ grn_obj_unlink(ctx, g.table);
+ GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE,
+ ":", "drilldown(%d)", n_hits);
+ }
+}
+
+static void
+grn_select_drilldowns(grn_ctx *ctx, grn_obj *table,
+ drilldown_info *drilldowns, unsigned int n_drilldowns,
+ grn_obj *condition)
+{
+ unsigned int i;
+
+ /* TODO: Remove invalid key drilldowns from the count. */
+ GRN_OUTPUT_MAP_OPEN("DRILLDOWNS", n_drilldowns);
+ for (i = 0; i < n_drilldowns; i++) {
+ drilldown_info *drilldown = &(drilldowns[i]);
+ grn_table_sort_key *keys = NULL;
+ unsigned int n_keys;
+ uint32_t n_hits;
+ int offset;
+ int limit;
+ grn_table_group_result result = {
+ NULL, 0, 0, 1, GRN_TABLE_GROUP_CALC_COUNT, 0, 0, NULL
+ };
+
+ keys = grn_table_sort_key_from_str(ctx,
+ drilldown->keys,
+ drilldown->keys_len,
+ table, &n_keys);
+ if (!keys) {
+ continue;
+ }
+
+ GRN_OUTPUT_STR(drilldown->label, drilldown->label_len);
+
+ result.key_begin = 0;
+ result.key_end = n_keys - 1;
+ if (n_keys > 1) {
+ result.max_n_subrecs = 1;
+ }
+ if (drilldown->calc_target_name) {
+ result.calc_target = grn_obj_column(ctx, table,
+ drilldown->calc_target_name,
+ drilldown->calc_target_name_len);
+ }
+ if (result.calc_target) {
+ result.flags |= drilldown->calc_types;
+ }
+
+ grn_table_group(ctx, table, keys, n_keys, &result, 1);
+ n_hits = grn_table_size(ctx, result.table);
+
+ offset = drilldown->offset;
+ limit = drilldown->limit;
+ grn_normalize_offset_and_limit(ctx, n_hits, &offset, &limit);
+
+ if (drilldown->sortby_len) {
+ grn_table_sort_key *sort_keys;
+ uint32_t n_sort_keys;
+ sort_keys = grn_table_sort_key_from_str(ctx,
+ drilldown->sortby,
+ drilldown->sortby_len,
+ result.table, &n_sort_keys);
+ if (sort_keys) {
+ grn_obj *sorted;
+ sorted = grn_table_create(ctx, NULL, 0, NULL, GRN_OBJ_TABLE_NO_KEY,
+ NULL, result.table);
+ if (sorted) {
+ grn_table_sort(ctx, result.table, offset, limit,
+ sorted, sort_keys, n_sort_keys);
+ grn_select_output_columns(ctx, sorted, n_hits, 0, limit,
+ drilldown->output_columns,
+ drilldown->output_columns_len,
+ condition);
+ grn_obj_unlink(ctx, sorted);
+ }
+ grn_table_sort_key_close(ctx, sort_keys, n_sort_keys);
+ }
+ } else {
+ grn_select_output_columns(ctx, result.table, n_hits, offset, limit,
+ drilldown->output_columns,
+ drilldown->output_columns_len,
+ condition);
+ }
+
+ grn_table_sort_key_close(ctx, keys, n_keys);
+ if (result.calc_target) {
+ grn_obj_unlink(ctx, result.calc_target);
+ }
+ grn_obj_unlink(ctx, result.table);
+
+ GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE,
+ ":", "drilldown(%d)[%.*s]", n_hits,
+ (int)(drilldown->label_len), drilldown->label);
+ }
+ GRN_OUTPUT_MAP_CLOSE();
+}
+
+static grn_rc
grn_select(grn_ctx *ctx, const char *table, unsigned int table_len,
const char *match_columns, unsigned int match_columns_len,
const char *query, unsigned int query_len,
@@ -547,10 +852,8 @@ grn_select(grn_ctx *ctx, const char *table, unsigned int table_len,
const char *sortby, unsigned int sortby_len,
const char *output_columns, unsigned int output_columns_len,
int offset, int limit,
- const char *drilldown, unsigned int drilldown_len,
- const char *drilldown_sortby, unsigned int drilldown_sortby_len,
- const char *drilldown_output_columns, unsigned int drilldown_output_columns_len,
- int drilldown_offset, int drilldown_limit,
+ drilldown_info *drilldowns,
+ unsigned int n_drilldowns,
const char *cache, unsigned int cache_len,
const char *match_escalation_threshold, unsigned int match_escalation_threshold_len,
const char *query_expander, unsigned int query_expander_len,
@@ -559,20 +862,31 @@ grn_select(grn_ctx *ctx, const char *table, unsigned int table_len,
{
uint32_t nkeys, nhits;
uint16_t cacheable = 1, taintable = 0;
- grn_obj_format format;
grn_table_sort_key *keys;
grn_obj *outbuf = ctx->impl->outbuf;
grn_content_type output_type = ctx->impl->output_type;
grn_obj *table_, *match_columns_ = NULL, *cond = NULL, *scorer_, *res = NULL, *sorted;
char cache_key[GRN_TABLE_MAX_KEY_SIZE];
- uint32_t cache_key_size = table_len + 1 + match_columns_len + 1 + query_len + 1 +
- filter_len + 1 + scorer_len + 1 + sortby_len + 1 + output_columns_len + 1 +
- drilldown_len + 1 + drilldown_sortby_len + 1 +
- drilldown_output_columns_len + 1 + match_escalation_threshold_len + 1 +
- query_expander_len + 1 + query_flags_len + 1 + adjuster_len + 1 +
- sizeof(grn_content_type) + sizeof(int) * 4;
+ uint32_t cache_key_size;
long long int threshold, original_threshold = 0;
grn_cache *cache_obj = grn_cache_current_get(ctx);
+
+ cache_key_size = table_len + 1 + match_columns_len + 1 + query_len + 1 +
+ filter_len + 1 + scorer_len + 1 + sortby_len + 1 + output_columns_len + 1 +
+ match_escalation_threshold_len + 1 +
+ query_expander_len + 1 + query_flags_len + 1 + adjuster_len + 1 +
+ sizeof(grn_content_type) + sizeof(int) * 2;
+ {
+ unsigned int i;
+ for (i = 0; i < n_drilldowns; i++) {
+ drilldown_info *drilldown = &(drilldowns[i]);
+ cache_key_size +=
+ drilldown->keys_len + 1 +
+ drilldown->sortby_len + 1 +
+ drilldown->output_columns_len + 1 +
+ sizeof(int) * 2;
+ }
+ }
if (cache_key_size <= GRN_TABLE_MAX_KEY_SIZE) {
grn_obj *cache_value;
char *cp = cache_key;
@@ -590,12 +904,18 @@ grn_select(grn_ctx *ctx, const char *table, unsigned int table_len,
cp += sortby_len; *cp++ = '\0';
memcpy(cp, output_columns, output_columns_len);
cp += output_columns_len; *cp++ = '\0';
- memcpy(cp, drilldown, drilldown_len);
- cp += drilldown_len; *cp++ = '\0';
- memcpy(cp, drilldown_sortby, drilldown_sortby_len);
- cp += drilldown_sortby_len; *cp++ = '\0';
- memcpy(cp, drilldown_output_columns, drilldown_output_columns_len);
- cp += drilldown_output_columns_len; *cp++ = '\0';
+ {
+ unsigned int i;
+ for (i = 0; i < n_drilldowns; i++) {
+ drilldown_info *drilldown = &(drilldowns[i]);
+ memcpy(cp, drilldown->keys, drilldown->keys_len);
+ cp += drilldown->keys_len; *cp++ = '\0';
+ memcpy(cp, drilldown->sortby, drilldown->sortby_len);
+ cp += drilldown->sortby_len; *cp++ = '\0';
+ memcpy(cp, drilldown->output_columns, drilldown->output_columns_len);
+ cp += drilldown->output_columns_len; *cp++ = '\0';
+ }
+ }
memcpy(cp, match_escalation_threshold, match_escalation_threshold_len);
cp += match_escalation_threshold_len; *cp++ = '\0';
memcpy(cp, query_expander, query_expander_len);
@@ -607,8 +927,14 @@ grn_select(grn_ctx *ctx, const char *table, unsigned int table_len,
memcpy(cp, &output_type, sizeof(grn_content_type)); cp += sizeof(grn_content_type);
memcpy(cp, &offset, sizeof(int)); cp += sizeof(int);
memcpy(cp, &limit, sizeof(int)); cp += sizeof(int);
- memcpy(cp, &drilldown_offset, sizeof(int)); cp += sizeof(int);
- memcpy(cp, &drilldown_limit, sizeof(int)); cp += sizeof(int);
+ {
+ unsigned int i;
+ for (i = 0; i < n_drilldowns; i++) {
+ drilldown_info *drilldown = &(drilldowns[i]);
+ memcpy(cp, &(drilldown->offset), sizeof(int)); cp += sizeof(int);
+ memcpy(cp, &(drilldown->limit), sizeof(int)); cp += sizeof(int);
+ }
+ }
cache_value = grn_cache_fetch(ctx, cache_obj, cache_key, cache_key_size);
if (cache_value) {
GRN_TEXT_PUT(ctx, outbuf,
@@ -710,12 +1036,17 @@ grn_select(grn_ctx *ctx, const char *table, unsigned int table_len,
uint32_t ngkeys;
grn_table_sort_key *gkeys = NULL;
int result_size = 1;
- if (!ctx->rc && drilldown_len) {
- gkeys = grn_table_sort_key_from_str(ctx,
- drilldown, drilldown_len,
- res, &ngkeys);
- if (gkeys) {
- result_size += ngkeys;
+ if (!ctx->rc && n_drilldowns > 0) {
+ if (n_drilldowns == 1 && !drilldowns[0].label) {
+ gkeys = grn_table_sort_key_from_str(ctx,
+ drilldowns[0].keys,
+ drilldowns[0].keys_len,
+ res, &ngkeys);
+ if (gkeys) {
+ result_size += ngkeys;
+ }
+ } else {
+ result_size += 1;
}
}
@@ -755,6 +1086,9 @@ grn_select(grn_ctx *ctx, const char *table, unsigned int table_len,
while ((id = grn_table_cursor_next(ctx, tc)) != GRN_ID_NIL) {
GRN_RECORD_SET(ctx, v, id);
grn_expr_exec(ctx, scorer_, 0);
+ if (ctx->rc) {
+ break;
+ }
}
grn_table_cursor_close(ctx, tc);
}
@@ -775,120 +1109,30 @@ grn_select(grn_ctx *ctx, const char *table, unsigned int table_len,
grn_table_sort(ctx, res, offset, limit, sorted, keys, nkeys);
GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE,
":", "sort(%d)", limit);
- GRN_OBJ_FORMAT_INIT(&format, nhits, 0, limit, offset);
- format.flags =
- GRN_OBJ_FORMAT_WITH_COLUMN_NAMES|
- GRN_OBJ_FORMAT_XML_ELEMENT_RESULTSET;
- if (is_output_columns_format_v1(ctx, output_columns, output_columns_len)) {
- grn_obj_columns(ctx, sorted, output_columns, output_columns_len,
- &format.columns);
- } else {
- grn_obj *v;
- grn_obj *condition_ptr;
- GRN_EXPR_CREATE_FOR_QUERY(ctx, sorted, format.expression, v);
- grn_expr_parse(ctx, format.expression,
- output_columns, output_columns_len, NULL,
- GRN_OP_MATCH, GRN_OP_AND,
- GRN_EXPR_SYNTAX_OUTPUT_COLUMNS);
- condition_ptr =
- grn_expr_get_or_add_var(ctx, format.expression,
- GRN_SELECT_INTERNAL_VAR_CONDITION,
- strlen(GRN_SELECT_INTERNAL_VAR_CONDITION));
- GRN_PTR_INIT(condition_ptr, 0, GRN_DB_OBJECT);
- GRN_PTR_SET(ctx, condition_ptr, cond);
- }
- GRN_OUTPUT_OBJ(sorted, &format);
- GRN_OBJ_FORMAT_FIN(ctx, &format);
+ grn_select_output_columns(ctx, sorted, nhits, 0, limit,
+ output_columns, output_columns_len, cond);
grn_obj_unlink(ctx, sorted);
}
grn_table_sort_key_close(ctx, keys, nkeys);
} else {
if (!ctx->rc) {
- GRN_OBJ_FORMAT_INIT(&format, nhits, offset, limit, offset);
- format.flags =
- GRN_OBJ_FORMAT_WITH_COLUMN_NAMES|
- GRN_OBJ_FORMAT_XML_ELEMENT_RESULTSET;
- if (is_output_columns_format_v1(ctx, output_columns, output_columns_len)) {
- grn_obj_columns(ctx, res, output_columns, output_columns_len,
- &format.columns);
- } else {
- grn_obj *v;
- grn_obj *condition_ptr;
- GRN_EXPR_CREATE_FOR_QUERY(ctx, res, format.expression, v);
- grn_expr_parse(ctx, format.expression,
- output_columns, output_columns_len, NULL,
- GRN_OP_MATCH, GRN_OP_AND,
- GRN_EXPR_SYNTAX_OUTPUT_COLUMNS);
- condition_ptr =
- grn_expr_get_or_add_var(ctx, format.expression,
- GRN_SELECT_INTERNAL_VAR_CONDITION,
- strlen(GRN_SELECT_INTERNAL_VAR_CONDITION));
- GRN_PTR_INIT(condition_ptr, 0, GRN_DB_OBJECT);
- GRN_PTR_SET(ctx, condition_ptr, cond);
- }
- GRN_OUTPUT_OBJ(res, &format);
- GRN_OBJ_FORMAT_FIN(ctx, &format);
+ grn_select_output_columns(ctx, res, nhits, offset, limit,
+ output_columns, output_columns_len, cond);
}
}
GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE,
":", "output(%d)", limit);
- if (!ctx->rc && drilldown_len) {
- uint32_t i;
- grn_table_group_result g = {NULL, 0, 0, 1, GRN_TABLE_GROUP_CALC_COUNT, 0};
+ if (!ctx->rc) {
if (gkeys) {
- for (i = 0; i < ngkeys; i++) {
- if ((g.table = grn_table_create_for_group(ctx, NULL, 0, NULL,
- gkeys[i].key, res, 0))) {
- int n_drilldown_offset = drilldown_offset,
- n_drilldown_limit = drilldown_limit;
-
- grn_table_group(ctx, res, &gkeys[i], 1, &g, 1);
- nhits = grn_table_size(ctx, g.table);
-
- grn_normalize_offset_and_limit(ctx, nhits,
- &n_drilldown_offset, &n_drilldown_limit);
-
- if (drilldown_sortby_len) {
- if ((keys = grn_table_sort_key_from_str(ctx,
- drilldown_sortby, drilldown_sortby_len,
- g.table, &nkeys))) {
- if ((sorted = grn_table_create(ctx, NULL, 0, NULL, GRN_OBJ_TABLE_NO_KEY,
- NULL, g.table))) {
- grn_table_sort(ctx, g.table, n_drilldown_offset, n_drilldown_limit,
- sorted, keys, nkeys);
- GRN_OBJ_FORMAT_INIT(&format, nhits, 0,
- n_drilldown_limit, n_drilldown_offset);
- format.flags =
- GRN_OBJ_FORMAT_WITH_COLUMN_NAMES|
- GRN_OBJ_FORMAT_XML_ELEMENT_NAVIGATIONENTRY;
- grn_obj_columns(ctx, sorted,
- drilldown_output_columns, drilldown_output_columns_len,
- &format.columns);
- GRN_OUTPUT_OBJ(sorted, &format);
- GRN_OBJ_FORMAT_FIN(ctx, &format);
- grn_obj_unlink(ctx, sorted);
- }
- grn_table_sort_key_close(ctx, keys, nkeys);
- }
- } else {
- GRN_OBJ_FORMAT_INIT(&format, nhits, n_drilldown_offset,
- n_drilldown_limit, n_drilldown_offset);
- format.flags =
- GRN_OBJ_FORMAT_WITH_COLUMN_NAMES|
- GRN_OBJ_FORMAT_XML_ELEMENT_NAVIGATIONENTRY;
- grn_obj_columns(ctx, g.table, drilldown_output_columns,
- drilldown_output_columns_len, &format.columns);
- GRN_OUTPUT_OBJ(g.table, &format);
- GRN_OBJ_FORMAT_FIN(ctx, &format);
- }
- grn_obj_unlink(ctx, g.table);
- }
- GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE,
- ":", "drilldown(%d)", nhits);
- }
- grn_table_sort_key_close(ctx, gkeys, ngkeys);
+ drilldown_info *drilldown = &(drilldowns[0]);
+ grn_select_drilldown(ctx, res, gkeys, ngkeys, drilldown);
+ } else if (n_drilldowns > 0) {
+ grn_select_drilldowns(ctx, res, drilldowns, n_drilldowns, cond);
}
}
+ if (gkeys) {
+ grn_table_sort_key_close(ctx, gkeys, ngkeys);
+ }
if (res != table_) { grn_obj_unlink(ctx, res); }
} else {
GRN_OUTPUT_ARRAY_OPEN("RESULT", 0);
@@ -903,7 +1147,7 @@ grn_select(grn_ctx *ctx, const char *table, unsigned int table_len,
} else {
ERR(GRN_INVALID_ARGUMENT, "invalid table name: <%.*s>", table_len, table);
}
-exit:
+exit :
if (match_escalation_threshold_len) {
grn_ctx_set_match_escalation_threshold(ctx, original_threshold);
}
@@ -917,9 +1161,46 @@ exit:
return ctx->rc;
}
+static void
+proc_select_find_all_drilldown_labels(grn_ctx *ctx, grn_user_data *user_data,
+ grn_obj *labels)
+{
+ grn_obj *vars = GRN_PROC_GET_VARS();
+ grn_table_cursor *cursor;
+ cursor = grn_table_cursor_open(ctx, vars, NULL, 0, NULL, 0, 0, -1, 0);
+ if (cursor) {
+ const char *prefix = "drilldown[";
+ int prefix_len = strlen(prefix);
+ const char *suffix = "].keys";
+ int suffix_len = strlen(suffix);
+ while (grn_table_cursor_next(ctx, cursor)) {
+ void *key;
+ char *name;
+ int name_len;
+ name_len = grn_table_cursor_get_key(ctx, cursor, &key);
+ name = key;
+ if (name_len < (prefix_len + 1 + suffix_len)) {
+ continue;
+ }
+ if (strncmp(prefix, name, prefix_len) != 0) {
+ continue;
+ }
+ if (strncmp(suffix, name + name_len - suffix_len, suffix_len) != 0) {
+ continue;
+ }
+ grn_vector_add_element(ctx, labels,
+ name + prefix_len,
+ name_len - prefix_len - suffix_len,
+ 0, GRN_ID_NIL);
+ }
+ grn_table_cursor_close(ctx, cursor);
+ }
+}
+
static grn_obj *
proc_select(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
{
+#define MAX_N_DRILLDOWNS 10
int offset = GRN_TEXT_LEN(VAR(7))
? grn_atoi(GRN_TEXT_VALUE(VAR(7)), GRN_BULK_CURR(VAR(7)), NULL)
: 0;
@@ -928,27 +1209,72 @@ proc_select(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
: DEFAULT_LIMIT;
const char *output_columns = GRN_TEXT_VALUE(VAR(6));
uint32_t output_columns_len = GRN_TEXT_LEN(VAR(6));
- const char *drilldown_output_columns = GRN_TEXT_VALUE(VAR(11));
- uint32_t drilldown_output_columns_len = GRN_TEXT_LEN(VAR(11));
- int drilldown_offset = GRN_TEXT_LEN(VAR(12))
- ? grn_atoi(GRN_TEXT_VALUE(VAR(12)), GRN_BULK_CURR(VAR(12)), NULL)
- : 0;
- int drilldown_limit = GRN_TEXT_LEN(VAR(13))
- ? grn_atoi(GRN_TEXT_VALUE(VAR(13)), GRN_BULK_CURR(VAR(13)), NULL)
- : DEFAULT_DRILLDOWN_LIMIT;
+ drilldown_info drilldowns[MAX_N_DRILLDOWNS];
+ unsigned int n_drilldowns = 0;
+ grn_obj drilldown_labels;
grn_obj *query_expansion = VAR(16);
grn_obj *query_expander = VAR(18);
grn_obj *adjuster = VAR(19);
+
if (GRN_TEXT_LEN(query_expander) == 0 && GRN_TEXT_LEN(query_expansion) > 0) {
query_expander = query_expansion;
}
+
if (!output_columns_len) {
output_columns = DEFAULT_OUTPUT_COLUMNS;
output_columns_len = strlen(DEFAULT_OUTPUT_COLUMNS);
}
- if (!drilldown_output_columns_len) {
- drilldown_output_columns = DEFAULT_DRILLDOWN_OUTPUT_COLUMNS;
- drilldown_output_columns_len = strlen(DEFAULT_DRILLDOWN_OUTPUT_COLUMNS);
+
+ GRN_TEXT_INIT(&drilldown_labels, GRN_OBJ_VECTOR);
+ if (GRN_TEXT_LEN(VAR(9))) {
+ drilldown_info *drilldown = &(drilldowns[0]);
+ drilldown->label = NULL;
+ drilldown->label_len = 0;
+ drilldown_info_fill(ctx, drilldown,
+ VAR(9), VAR(10), VAR(11), VAR(12), VAR(13),
+ VAR(20), VAR(21));
+ n_drilldowns++;
+ } else {
+ unsigned int i;
+ proc_select_find_all_drilldown_labels(ctx, user_data, &drilldown_labels);
+ n_drilldowns = grn_vector_size(ctx, &drilldown_labels);
+ for (i = 0; i < n_drilldowns; i++) {
+ drilldown_info *drilldown = &(drilldowns[i]);
+ const char *label;
+ int label_len;
+ char key_name[GRN_TABLE_MAX_KEY_SIZE];
+ grn_obj *keys;
+ grn_obj *sortby;
+ grn_obj *output_columns;
+ grn_obj *offset;
+ grn_obj *limit;
+ grn_obj *calc_types;
+ grn_obj *calc_target;
+
+ label_len = grn_vector_get_element(ctx, &drilldown_labels, i,
+ &label, NULL, NULL);
+ drilldown->label = label;
+ drilldown->label_len = label_len;
+
+#define GET_VAR(name)\
+ snprintf(key_name, GRN_TABLE_MAX_KEY_SIZE,\
+ "drilldown[%.*s]." # name, label_len, label);\
+ name = GRN_PROC_GET_VAR(key_name);
+
+ GET_VAR(keys);
+ GET_VAR(sortby);
+ GET_VAR(output_columns);
+ GET_VAR(offset);
+ GET_VAR(limit);
+ GET_VAR(calc_types);
+ GET_VAR(calc_target);
+
+#undef GET_VAR
+
+ drilldown_info_fill(ctx, drilldown,
+ keys, sortby, output_columns, offset, limit,
+ calc_types, calc_target);
+ }
}
if (grn_select(ctx, GRN_TEXT_VALUE(VAR(0)), GRN_TEXT_LEN(VAR(0)),
GRN_TEXT_VALUE(VAR(1)), GRN_TEXT_LEN(VAR(1)),
@@ -958,16 +1284,16 @@ proc_select(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
GRN_TEXT_VALUE(VAR(5)), GRN_TEXT_LEN(VAR(5)),
output_columns, output_columns_len,
offset, limit,
- GRN_TEXT_VALUE(VAR(9)), GRN_TEXT_LEN(VAR(9)),
- GRN_TEXT_VALUE(VAR(10)), GRN_TEXT_LEN(VAR(10)),
- drilldown_output_columns, drilldown_output_columns_len,
- drilldown_offset, drilldown_limit,
+ drilldowns, n_drilldowns,
GRN_TEXT_VALUE(VAR(14)), GRN_TEXT_LEN(VAR(14)),
GRN_TEXT_VALUE(VAR(15)), GRN_TEXT_LEN(VAR(15)),
GRN_TEXT_VALUE(query_expander), GRN_TEXT_LEN(query_expander),
GRN_TEXT_VALUE(VAR(17)), GRN_TEXT_LEN(VAR(17)),
GRN_TEXT_VALUE(adjuster), GRN_TEXT_LEN(adjuster))) {
}
+ GRN_OBJ_FIN(ctx, &drilldown_labels);
+#undef MAX_N_DRILLDOWNS
+
return NULL;
}
@@ -1105,8 +1431,8 @@ grn_parse_column_create_flags(grn_ctx *ctx, const char *nptr, const char *end)
} else if (!memcmp(nptr, "COMPRESS_ZLIB", 13)) {
flags |= GRN_OBJ_COMPRESS_ZLIB;
nptr += 13;
- } else if (!memcmp(nptr, "COMPRESS_LZO", 12)) {
- flags |= GRN_OBJ_COMPRESS_LZO;
+ } else if (!memcmp(nptr, "COMPRESS_LZ4", 12)) {
+ flags |= GRN_OBJ_COMPRESS_LZ4;
nptr += 12;
} else if (!memcmp(nptr, "WITH_SECTION", 12)) {
flags |= GRN_OBJ_WITH_SECTION;
@@ -1191,8 +1517,8 @@ grn_column_create_flags_to_text(grn_ctx *ctx, grn_obj *buf, grn_obj_flags flags)
case GRN_OBJ_COMPRESS_ZLIB:
GRN_TEXT_PUTS(ctx, buf, "|COMPRESS_ZLIB");
break;
- case GRN_OBJ_COMPRESS_LZO:
- GRN_TEXT_PUTS(ctx, buf, "|COMPRESS_LZO");
+ case GRN_OBJ_COMPRESS_LZ4:
+ GRN_TEXT_PUTS(ctx, buf, "|COMPRESS_LZ4");
break;
}
if (flags & GRN_OBJ_PERSISTENT) {
@@ -1374,7 +1700,7 @@ proc_table_create(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_d
ERR(GRN_INVALID_ARGUMENT,
"[table][create] should not create anonymous table");
}
-exit:
+exit :
GRN_OUTPUT_BOOL(!ctx->rc);
return NULL;
}
@@ -1427,7 +1753,7 @@ proc_table_rename(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_d
(int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0)),
(int)GRN_TEXT_LEN(VAR(1)), GRN_TEXT_VALUE(VAR(1)));
}
-exit:
+exit :
GRN_OUTPUT_BOOL(!rc);
if (table) { grn_obj_unlink(ctx, table); }
return NULL;
@@ -1595,7 +1921,7 @@ proc_column_create(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_
} else {
succeeded = GRN_FALSE;
}
-exit:
+exit :
GRN_OUTPUT_BOOL(succeeded);
if (table) { grn_obj_unlink(ctx, table); }
if (type) { grn_obj_unlink(ctx, type); }
@@ -1687,7 +2013,7 @@ proc_column_rename(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_
(int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0)),
(int)GRN_TEXT_LEN(VAR(2)), GRN_TEXT_VALUE(VAR(2)));
}
-exit:
+exit :
GRN_OUTPUT_BOOL(!rc);
if (column) { grn_obj_unlink(ctx, column); }
if (table) { grn_obj_unlink(ctx, table); }
@@ -1900,20 +2226,6 @@ proc_column_list(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_da
return NULL;
}
-static grn_bool
-is_table(grn_obj *obj)
-{
- switch (obj->header.type) {
- case GRN_TABLE_HASH_KEY:
- case GRN_TABLE_PAT_KEY:
- case GRN_TABLE_DAT_KEY:
- case GRN_TABLE_NO_KEY:
- return GRN_TRUE;
- default:
- return GRN_FALSE;
- }
-}
-
static int
output_table_info(grn_ctx *ctx, grn_obj *table)
{
@@ -1948,7 +2260,6 @@ output_table_info(grn_ctx *ctx, grn_obj *table)
static grn_obj *
proc_table_list(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
{
- grn_table_cursor *cur;
grn_obj tables;
int n_top_level_elements;
int n_elements_for_header = 1;
@@ -1956,26 +2267,7 @@ proc_table_list(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_dat
int i;
GRN_PTR_INIT(&tables, GRN_OBJ_VECTOR, GRN_ID_NIL);
-
- if ((cur = grn_table_cursor_open(ctx, ctx->impl->db, NULL, 0, NULL, 0, 0, -1, 0))) {
- grn_id id;
- while ((id = grn_table_cursor_next(ctx, cur)) != GRN_ID_NIL) {
- grn_obj *object;
- if ((object = grn_ctx_at(ctx, id))) {
- if (is_table(object)) {
- GRN_PTR_PUT(ctx, &tables, object);
- } else {
- grn_obj_unlink(ctx, object);
- }
- } else {
- if (ctx->rc != GRN_SUCCESS) {
- ERRCLR(ctx);
- }
- }
- }
- grn_table_cursor_close(ctx, cur);
- }
-
+ grn_ctx_get_all_tables(ctx, &tables);
n_tables = GRN_BULK_VSIZE(&tables) / sizeof(grn_obj *);
n_top_level_elements = n_elements_for_header + n_tables;
GRN_OUTPUT_ARRAY_OPEN("TABLE_LIST", n_top_level_elements);
@@ -2016,7 +2308,7 @@ proc_table_list(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_dat
GRN_OUTPUT_ARRAY_CLOSE();
for (i = 0; i < n_tables; i++) {
- grn_obj *table = ((grn_obj **)GRN_BULK_HEAD(&tables))[i];
+ grn_obj *table = GRN_PTR_VALUE_AT(&tables, i);
output_table_info(ctx, table);
grn_obj_unlink(ctx, table);
}
@@ -2081,7 +2373,8 @@ proc_shutdown(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
}
static grn_obj *
-proc_clearlock(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
+proc_lock_clear(grn_ctx *ctx, int nargs, grn_obj **args,
+ grn_user_data *user_data)
{
int target_name_len;
grn_obj *target_name;
@@ -2099,7 +2392,7 @@ proc_clearlock(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data
if (obj) {
grn_obj_clear_lock(ctx, obj);
} else {
- ERR(GRN_INVALID_ARGUMENT, "[clearlock] target object not found: <%.*s>",
+ ERR(GRN_INVALID_ARGUMENT, "[lock_clear] target object not found: <%.*s>",
target_name_len, GRN_TEXT_VALUE(target_name));
}
GRN_OUTPUT_BOOL(!ctx->rc);
@@ -2348,6 +2641,8 @@ exit :
return NULL;
}
+static const size_t DUMP_FLUSH_THRESHOLD_SIZE = 256 * 1024;
+
static void
dump_name(grn_ctx *ctx, grn_obj *outbuf, const char *name, int name_len)
{
@@ -2685,6 +2980,9 @@ dump_records(grn_ctx *ctx, grn_obj *outbuf, grn_obj *table)
}
}
GRN_TEXT_PUTC(ctx, outbuf, ']');
+ if (GRN_TEXT_LEN(outbuf) >= DUMP_FLUSH_THRESHOLD_SIZE) {
+ grn_ctx_output_flush(ctx, 0);
+ }
}
GRN_TEXT_PUTS(ctx, outbuf, "\n]\n");
GRN_TEXT_PUT(ctx, outbuf, GRN_TEXT_VALUE(&delete_commands),
@@ -2936,6 +3234,7 @@ proc_dump(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
ctx->impl->output_type = GRN_CONTENT_NONE;
ctx->impl->mime_type = "text/x-groonga-command-list";
dump_schema(ctx, outbuf);
+ grn_ctx_output_flush(ctx, 0);
/* To update index columns correctly, we first create the whole schema, then
load non-derivative records, while skipping records of index columns. That
way, groonga will silently do the job of updating index columns for us. */
@@ -2945,7 +3244,7 @@ proc_dump(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
dump_all_records(ctx, outbuf);
}
- /* remove the last newline because another one will be added by the calller.
+ /* remove the last newline because another one will be added by the caller.
maybe, the caller of proc functions currently doesn't consider the
possibility of multiple-line output from proc functions. */
if (GRN_BULK_VSIZE(outbuf) > 0) {
@@ -3106,37 +3405,56 @@ proc_check(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
static grn_obj *
proc_truncate(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
{
- int table_name_len = GRN_TEXT_LEN(VAR(0));
- if (table_name_len == 0) {
- ERR(GRN_INVALID_ARGUMENT, "table name is missing");
+ const char *target_name;
+ int target_name_len;
+
+ target_name_len = GRN_TEXT_LEN(VAR(0));
+ if (target_name_len > 0) {
+ target_name = GRN_TEXT_VALUE(VAR(0));
} else {
- const char *table_name = GRN_TEXT_VALUE(VAR(0));
- grn_obj *table = grn_ctx_get(ctx, table_name, table_name_len);
- if (!table) {
+ target_name_len = GRN_TEXT_LEN(VAR(1));
+ if (target_name_len == 0) {
+ ERR(GRN_INVALID_ARGUMENT, "[truncate] table name is missing");
+ goto exit;
+ }
+ target_name = GRN_TEXT_VALUE(VAR(1));
+ }
+
+ {
+ grn_obj *target = grn_ctx_get(ctx, target_name, target_name_len);
+ if (!target) {
ERR(GRN_INVALID_ARGUMENT,
- "no such table: <%.*s>", table_name_len, table_name);
- } else {
- switch (table->header.type) {
- case GRN_TABLE_HASH_KEY :
- case GRN_TABLE_PAT_KEY :
- case GRN_TABLE_DAT_KEY :
- case GRN_TABLE_NO_KEY :
- grn_table_truncate(ctx, table);
- break;
- default:
- {
- grn_obj buffer;
- GRN_TEXT_INIT(&buffer, 0);
- grn_inspect(ctx, &buffer, table);
- ERR(GRN_INVALID_ARGUMENT,
- "not a table object: %.*s",
- (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer));
- GRN_OBJ_FIN(ctx, &buffer);
- }
- break;
+ "[truncate] no such target: <%.*s>", target_name_len, target_name);
+ goto exit;
+ }
+
+ switch (target->header.type) {
+ case GRN_TABLE_HASH_KEY :
+ case GRN_TABLE_PAT_KEY :
+ case GRN_TABLE_DAT_KEY :
+ case GRN_TABLE_NO_KEY :
+ grn_table_truncate(ctx, target);
+ break;
+ case GRN_COLUMN_FIX_SIZE :
+ case GRN_COLUMN_VAR_SIZE :
+ case GRN_COLUMN_INDEX :
+ grn_column_truncate(ctx, target);
+ break;
+ default:
+ {
+ grn_obj buffer;
+ GRN_TEXT_INIT(&buffer, 0);
+ grn_inspect(ctx, &buffer, target);
+ ERR(GRN_INVALID_ARGUMENT,
+ "[truncate] not a table nor column object: <%.*s>",
+ (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer));
+ GRN_OBJ_FIN(ctx, &buffer);
}
+ break;
}
}
+
+exit :
GRN_OUTPUT_BOOL(!ctx->rc);
return NULL;
}
@@ -3161,7 +3479,7 @@ parse_normalize_flags(grn_ctx *ctx, grn_obj *flag_names)
if (((names_end - names) >= (sizeof(#name) - 1)) &&\
(!memcmp(names, #name, sizeof(#name) - 1))) {\
flags |= GRN_STRING_ ## name;\
- names += sizeof(#name);\
+ names += sizeof(#name) - 1;\
continue;\
}
@@ -3373,16 +3691,16 @@ parse_tokenize_flags(grn_ctx *ctx, grn_obj *flag_names)
#define CHECK_FLAG(name)\
if (((names_end - names) >= (sizeof(#name) - 1)) &&\
(!memcmp(names, #name, sizeof(#name) - 1))) {\
- flags |= GRN_TOKEN_ ## name;\
- names += sizeof(#name);\
+ flags |= GRN_TOKEN_CURSOR_ ## name;\
+ names += sizeof(#name) - 1;\
continue;\
}
CHECK_FLAG(ENABLE_TOKENIZED_DELIMITER);
-#define GRN_TOKEN_NONE 0
+#define GRN_TOKEN_CURSOR_NONE 0
CHECK_FLAG(NONE);
-#undef GRN_TOKEN_NONE
+#undef GRN_TOKEN_CURSOR_NONE
ERR(GRN_INVALID_ARGUMENT, "[tokenize] invalid flag: <%.*s>",
(int)(names_end - names), names);
@@ -3399,7 +3717,7 @@ typedef struct {
} tokenize_token;
static void
-output_tokens(grn_ctx *ctx, grn_obj *tokens, grn_hash *lexicon)
+output_tokens(grn_ctx *ctx, grn_obj *tokens, grn_obj *lexicon)
{
int i, n_tokens;
@@ -3415,8 +3733,8 @@ output_tokens(grn_ctx *ctx, grn_obj *tokens, grn_hash *lexicon)
GRN_OUTPUT_MAP_OPEN("TOKEN", 2);
GRN_OUTPUT_CSTR("value");
- value_size = grn_hash_get_key(ctx, lexicon, token->id,
- value, GRN_TABLE_MAX_KEY_SIZE);
+ value_size = grn_table_get_key(ctx, lexicon, token->id,
+ value, GRN_TABLE_MAX_KEY_SIZE);
GRN_OUTPUT_STR(value, value_size);
GRN_OUTPUT_CSTR("position");
@@ -3427,12 +3745,13 @@ output_tokens(grn_ctx *ctx, grn_obj *tokens, grn_hash *lexicon)
GRN_OUTPUT_ARRAY_CLOSE();
}
-static grn_hash *
+static grn_obj *
create_lexicon_for_tokenize(grn_ctx *ctx,
grn_obj *tokenizer_name,
- grn_obj *normalizer_name)
+ grn_obj *normalizer_name,
+ grn_obj *token_filter_names)
{
- grn_hash *lexicon;
+ grn_obj *lexicon;
grn_obj *tokenizer;
grn_obj *normalizer = NULL;
@@ -3488,35 +3807,39 @@ create_lexicon_for_tokenize(grn_ctx *ctx,
}
}
- lexicon = grn_hash_create(ctx, NULL, GRN_TABLE_MAX_KEY_SIZE, 0,
- GRN_OBJ_TABLE_HASH_KEY | GRN_OBJ_KEY_VAR_SIZE);
- grn_obj_set_info(ctx, (grn_obj *)lexicon,
+ lexicon = grn_table_create(ctx, NULL, 0,
+ NULL,
+ GRN_OBJ_TABLE_HASH_KEY,
+ grn_ctx_at(ctx, GRN_DB_SHORT_TEXT),
+ NULL);
+ grn_obj_set_info(ctx, lexicon,
GRN_INFO_DEFAULT_TOKENIZER, tokenizer);
grn_obj_unlink(ctx, tokenizer);
if (normalizer) {
- grn_obj_set_info(ctx, (grn_obj *)lexicon,
+ grn_obj_set_info(ctx, lexicon,
GRN_INFO_NORMALIZER, normalizer);
grn_obj_unlink(ctx, normalizer);
}
+ proc_table_create_set_token_filters(ctx, lexicon, token_filter_names);
return lexicon;
}
static void
-tokenize(grn_ctx *ctx, grn_hash *lexicon, grn_obj *string, grn_token_mode mode,
+tokenize(grn_ctx *ctx, grn_obj *lexicon, grn_obj *string, grn_tokenize_mode mode,
unsigned int flags, grn_obj *tokens)
{
grn_token_cursor *token_cursor;
token_cursor =
- grn_token_cursor_open(ctx, (grn_obj *)lexicon,
+ grn_token_cursor_open(ctx, lexicon,
GRN_TEXT_VALUE(string), GRN_TEXT_LEN(string),
mode, flags);
if (!token_cursor) {
return;
}
- while (token_cursor->status == GRN_TOKEN_DOING) {
+ while (token_cursor->status == GRN_TOKEN_CURSOR_DOING) {
grn_id token_id = grn_token_cursor_next(ctx, token_cursor);
tokenize_token *current_token;
if (token_id == GRN_ID_NIL) {
@@ -3538,12 +3861,14 @@ proc_tokenize(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
grn_obj *normalizer_name;
grn_obj *flag_names;
grn_obj *mode_name;
+ grn_obj *token_filter_names;
tokenizer_name = VAR(0);
string = VAR(1);
normalizer_name = VAR(2);
flag_names = VAR(3);
mode_name = VAR(4);
+ token_filter_names = VAR(5);
if (GRN_TEXT_LEN(tokenizer_name) == 0) {
ERR(GRN_INVALID_ARGUMENT, "[tokenize] tokenizer name is missing");
@@ -3557,14 +3882,17 @@ proc_tokenize(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
{
unsigned int flags;
- grn_hash *lexicon;
+ grn_obj *lexicon;
flags = parse_tokenize_flags(ctx, flag_names);
if (ctx->rc != GRN_SUCCESS) {
return NULL;
}
- lexicon = create_lexicon_for_tokenize(ctx, tokenizer_name, normalizer_name);
+ lexicon = create_lexicon_for_tokenize(ctx,
+ tokenizer_name,
+ normalizer_name,
+ token_filter_names);
if (!lexicon) {
return NULL;
}
@@ -3573,41 +3901,91 @@ proc_tokenize(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
(GRN_TEXT_LEN(mode_name) == strlen(name) &&\
memcmp(GRN_TEXT_VALUE(mode_name), name, strlen(name)) == 0)
- if (GRN_TEXT_LEN(mode_name) == 0 || MODE_NAME_EQUAL("ADD")) {
+ {
grn_obj tokens;
GRN_VALUE_FIX_SIZE_INIT(&tokens, GRN_OBJ_VECTOR, GRN_ID_NIL);
- tokenize(ctx, lexicon, string, GRN_TOKEN_ADD, flags, &tokens);
- output_tokens(ctx, &tokens, lexicon);
- GRN_OBJ_FIN(ctx, &tokens);
- } else if (MODE_NAME_EQUAL("GET")) {
- {
- grn_token_cursor *token_cursor;
- token_cursor =
- grn_token_cursor_open(ctx, (grn_obj *)lexicon,
- GRN_TEXT_VALUE(string), GRN_TEXT_LEN(string),
- GRN_TOKEN_ADD, flags);
- if (token_cursor) {
- while (token_cursor->status == GRN_TOKEN_DOING) {
- grn_token_cursor_next(ctx, token_cursor);
- }
- grn_token_cursor_close(ctx, token_cursor);
- }
- }
-
- {
- grn_obj tokens;
- GRN_VALUE_FIX_SIZE_INIT(&tokens, GRN_OBJ_VECTOR, GRN_ID_NIL);
+ if (GRN_TEXT_LEN(mode_name) == 0 || MODE_NAME_EQUAL("ADD")) {
+ tokenize(ctx, lexicon, string, GRN_TOKEN_ADD, flags, &tokens);
+ output_tokens(ctx, &tokens, lexicon);
+ } else if (MODE_NAME_EQUAL("GET")) {
+ tokenize(ctx, lexicon, string, GRN_TOKEN_ADD, flags, &tokens);
+ GRN_BULK_REWIND(&tokens);
tokenize(ctx, lexicon, string, GRN_TOKEN_GET, flags, &tokens);
output_tokens(ctx, &tokens, lexicon);
- GRN_OBJ_FIN(ctx, &tokens);
+ } else {
+ ERR(GRN_INVALID_ARGUMENT, "[tokenize] invalid mode: <%.*s>",
+ (int)GRN_TEXT_LEN(mode_name), GRN_TEXT_VALUE(mode_name));
}
+ GRN_OBJ_FIN(ctx, &tokens);
+ }
+#undef MODE_NAME_EQUAL
+
+ grn_obj_unlink(ctx, lexicon);
+ }
+
+ return NULL;
+}
+
+static grn_obj *
+proc_table_tokenize(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
+{
+ grn_obj *table_name;
+ grn_obj *string;
+ grn_obj *flag_names;
+ grn_obj *mode_name;
+
+ table_name = VAR(0);
+ string = VAR(1);
+ flag_names = VAR(2);
+ mode_name = VAR(3);
+
+ if (GRN_TEXT_LEN(table_name) == 0) {
+ ERR(GRN_INVALID_ARGUMENT, "[table_tokenize] table name is missing");
+ return NULL;
+ }
+
+ if (GRN_TEXT_LEN(string) == 0) {
+ ERR(GRN_INVALID_ARGUMENT, "[table_tokenize] string is missing");
+ return NULL;
+ }
+
+ {
+ unsigned int flags;
+ grn_obj *lexicon;
+
+ flags = parse_tokenize_flags(ctx, flag_names);
+ if (ctx->rc != GRN_SUCCESS) {
+ return NULL;
+ }
+
+ lexicon = grn_ctx_get(ctx, GRN_TEXT_VALUE(table_name), GRN_TEXT_LEN(table_name));
+
+ if (!lexicon) {
+ return NULL;
+ }
+
+#define MODE_NAME_EQUAL(name)\
+ (GRN_TEXT_LEN(mode_name) == strlen(name) &&\
+ memcmp(GRN_TEXT_VALUE(mode_name), name, strlen(name)) == 0)
+
+ {
+ grn_obj tokens;
+ GRN_VALUE_FIX_SIZE_INIT(&tokens, GRN_OBJ_VECTOR, GRN_ID_NIL);
+ if (GRN_TEXT_LEN(mode_name) == 0 || MODE_NAME_EQUAL("GET")) {
+ tokenize(ctx, lexicon, string, GRN_TOKEN_GET, flags, &tokens);
+ output_tokens(ctx, &tokens, lexicon);
+ } else if (MODE_NAME_EQUAL("ADD")) {
+ tokenize(ctx, lexicon, string, GRN_TOKEN_ADD, flags, &tokens);
+ output_tokens(ctx, &tokens, lexicon);
} else {
- ERR(GRN_INVALID_ARGUMENT, "[tokenize] invalid mode: <%.*s>",
+ ERR(GRN_INVALID_ARGUMENT, "[table_tokenize] invalid mode: <%.*s>",
(int)GRN_TEXT_LEN(mode_name), GRN_TEXT_VALUE(mode_name));
}
+ GRN_OBJ_FIN(ctx, &tokens);
+ }
#undef MODE_NAME_EQUAL
- grn_hash_close(ctx, lexicon);
+ grn_obj_unlink(ctx, lexicon);
}
return NULL;
@@ -4173,19 +4551,14 @@ selector_all_records(grn_ctx *ctx, grn_obj *table, grn_obj *index,
int nargs, grn_obj **args,
grn_obj *res, grn_operator op)
{
- grn_obj score;
-
- GRN_UINT32_INIT(&score, 0);
- GRN_UINT32_SET(ctx, &score, 1);
+ grn_ii_posting posting;
+ memset(&posting, 0, sizeof(grn_ii_posting));
GRN_TABLE_EACH(ctx, table, 0, 0, id, NULL, NULL, NULL, {
- grn_id result_id;
- result_id = grn_table_add(ctx, res, &id, sizeof(grn_id), NULL);
- grn_obj_set_value(ctx, res, result_id, &score, GRN_OBJ_SET);
+ posting.rid = id;
+ grn_ii_posting_add(ctx, &posting, (grn_hash *)res, GRN_OP_OR);
});
- GRN_OBJ_FIN(ctx, &score);
-
return ctx->rc;
}
@@ -4460,7 +4833,7 @@ run_query(grn_ctx *ctx, grn_obj *table,
rc = ctx->rc;
}
-exit:
+exit :
if (match_columns) {
grn_obj_unlink(ctx, match_columns);
}
@@ -4590,7 +4963,7 @@ run_sub_filter(grn_ctx *ctx, grn_obj *table,
grn_obj_unlink(ctx, base_res);
}
-exit:
+exit :
if (scope_domain) {
grn_obj_unlink(ctx, scope_domain);
}
@@ -4719,11 +5092,27 @@ typedef enum {
typedef struct {
grn_obj *value;
grn_obj *min;
+ grn_obj casted_min;
between_border_type min_border_type;
grn_obj *max;
+ grn_obj casted_max;
between_border_type max_border_type;
} between_data;
+static void
+between_data_init(grn_ctx *ctx, between_data *data)
+{
+ GRN_VOID_INIT(&(data->casted_min));
+ GRN_VOID_INIT(&(data->casted_max));
+}
+
+static void
+between_data_fin(grn_ctx *ctx, between_data *data)
+{
+ GRN_OBJ_FIN(ctx, &(data->casted_min));
+ GRN_OBJ_FIN(ctx, &(data->casted_max));
+}
+
static between_border_type
between_parse_border(grn_ctx *ctx, grn_obj *border,
const char *argument_description)
@@ -4752,6 +5141,41 @@ between_parse_border(grn_ctx *ctx, grn_obj *border,
}
static grn_rc
+between_cast(grn_ctx *ctx, grn_obj *source, grn_obj *destination, grn_id domain,
+ const char *target_argument_name)
+{
+ grn_rc rc;
+
+ GRN_OBJ_INIT(destination, GRN_BULK, 0, domain);
+ rc = grn_obj_cast(ctx, source, destination, GRN_FALSE);
+ if (rc != GRN_SUCCESS) {
+ grn_obj inspected_source;
+ grn_obj *domain_object;
+ char domain_name[GRN_TABLE_MAX_KEY_SIZE];
+ int domain_name_length;
+
+ GRN_TEXT_INIT(&inspected_source, 0);
+ grn_inspect(ctx, &inspected_source, source);
+
+ domain_object = grn_ctx_at(ctx, domain);
+ domain_name_length =
+ grn_obj_name(ctx, domain_object, domain_name, GRN_TABLE_MAX_KEY_SIZE);
+
+ ERR(rc, "between(): failed to cast %s: <%.*s> -> <%.*s>",
+ target_argument_name,
+ (int)GRN_TEXT_LEN(&inspected_source),
+ GRN_TEXT_VALUE(&inspected_source),
+ domain_name_length,
+ domain_name);
+
+ grn_obj_unlink(ctx, &inspected_source);
+ grn_obj_unlink(ctx, domain_object);
+ }
+
+ return rc;
+}
+
+static grn_rc
between_parse_args(grn_ctx *ctx, int nargs, grn_obj **args, between_data *data)
{
grn_rc rc = GRN_SUCCESS;
@@ -4785,43 +5209,70 @@ between_parse_args(grn_ctx *ctx, int nargs, grn_obj **args, between_data *data)
goto exit;
}
+ {
+ grn_id value_type;
+ if (data->value->header.type == GRN_BULK) {
+ value_type = data->value->header.domain;
+ } else {
+ value_type = grn_obj_get_range(ctx, data->value);
+ }
+ if (value_type != data->min->header.domain) {
+ rc = between_cast(ctx, data->min, &data->casted_min, value_type, "min");
+ if (rc != GRN_SUCCESS) {
+ goto exit;
+ }
+ data->min = &(data->casted_min);
+ }
+
+ if (value_type != data->max->header.domain) {
+ rc = between_cast(ctx, data->max, &data->casted_max, value_type, "max");
+ if (rc != GRN_SUCCESS) {
+ goto exit;
+ }
+ data->max = &(data->casted_max);
+ }
+ }
+
exit :
return rc;
}
-static grn_rc
-between_cast(grn_ctx *ctx, grn_obj *source, grn_obj *destination, grn_id domain,
- const char *target_argument_name)
+static grn_bool
+between_create_expr(grn_ctx *ctx, grn_obj *table, between_data *data,
+ grn_obj **expr, grn_obj **variable)
{
- grn_rc rc;
-
- GRN_OBJ_INIT(destination, GRN_BULK, 0, domain);
- rc = grn_obj_cast(ctx, source, destination, GRN_FALSE);
- if (rc != GRN_SUCCESS) {
- grn_obj inspected_source;
- grn_obj *domain_object;
- char domain_name[GRN_TABLE_MAX_KEY_SIZE];
- int domain_name_length;
-
- GRN_TEXT_INIT(&inspected_source, 0);
- grn_inspect(ctx, &inspected_source, source);
-
- domain_object = grn_ctx_at(ctx, domain);
- domain_name_length =
- grn_obj_name(ctx, domain_object, domain_name, GRN_TABLE_MAX_KEY_SIZE);
+ GRN_EXPR_CREATE_FOR_QUERY(ctx, table, *expr, *variable);
+ if (!*expr) {
+ return GRN_FALSE;
+ }
- ERR(rc, "between(): failed to cast %s: <%.*s> -> <%.*s>",
- target_argument_name,
- (int)GRN_TEXT_LEN(&inspected_source),
- GRN_TEXT_VALUE(&inspected_source),
- domain_name_length,
- domain_name);
+ if (data->value->header.type == GRN_BULK) {
+ grn_expr_append_obj(ctx, *expr, data->value, GRN_OP_PUSH, 1);
+ } else {
+ grn_expr_append_obj(ctx, *expr, data->value, GRN_OP_GET_VALUE, 1);
+ }
+ grn_expr_append_obj(ctx, *expr, data->min, GRN_OP_PUSH, 1);
+ if (data->min_border_type == BETWEEN_BORDER_INCLUDE) {
+ grn_expr_append_op(ctx, *expr, GRN_OP_GREATER_EQUAL, 2);
+ } else {
+ grn_expr_append_op(ctx, *expr, GRN_OP_GREATER, 2);
+ }
- grn_obj_unlink(ctx, &inspected_source);
- grn_obj_unlink(ctx, domain_object);
+ if (data->value->header.type == GRN_BULK) {
+ grn_expr_append_obj(ctx, *expr, data->value, GRN_OP_PUSH, 1);
+ } else {
+ grn_expr_append_obj(ctx, *expr, data->value, GRN_OP_GET_VALUE, 1);
+ }
+ grn_expr_append_obj(ctx, *expr, data->max, GRN_OP_PUSH, 1);
+ if (data->max_border_type == BETWEEN_BORDER_INCLUDE) {
+ grn_expr_append_op(ctx, *expr, GRN_OP_LESS_EQUAL, 2);
+ } else {
+ grn_expr_append_op(ctx, *expr, GRN_OP_LESS, 2);
}
- return rc;
+ grn_expr_append_op(ctx, *expr, GRN_OP_AND, 2);
+
+ return GRN_TRUE;
}
static grn_obj *
@@ -4832,7 +5283,7 @@ func_between(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
between_data data;
grn_obj *condition = NULL;
grn_obj *variable;
- grn_obj *table;
+ grn_obj *table = NULL;
grn_obj *between_expr;
grn_obj *between_variable;
grn_obj *result;
@@ -4853,49 +5304,246 @@ func_between(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
return found;
}
+ between_data_init(ctx, &data);
rc = between_parse_args(ctx, nargs, args, &data);
if (rc != GRN_SUCCESS) {
- return found;
+ goto exit;
}
table = grn_ctx_at(ctx, variable->header.domain);
if (!table) {
- return found;
+ goto exit;
+ }
+ if (!between_create_expr(ctx, table, &data, &between_expr, &between_variable)) {
+ goto exit;
+ }
+
+ GRN_RECORD_SET(ctx, between_variable, GRN_RECORD_VALUE(variable));
+ result = grn_expr_exec(ctx, between_expr, 0);
+ if (result) {
+ grn_bool result_boolean;
+ GRN_TRUEP(ctx, result, result_boolean);
+ if (result_boolean) {
+ GRN_BOOL_SET(ctx, found, GRN_TRUE);
+ }
}
- GRN_EXPR_CREATE_FOR_QUERY(ctx, table, between_expr, between_variable);
- if (!between_expr) {
+
+ grn_obj_unlink(ctx, between_expr);
+ grn_obj_unlink(ctx, table);
+
+exit :
+ between_data_fin(ctx, &data);
+ if (table) {
grn_obj_unlink(ctx, table);
- return found;
}
- grn_expr_append_obj(ctx, between_expr, data.value, GRN_OP_PUSH, 1);
- grn_expr_append_obj(ctx, between_expr, data.min, GRN_OP_PUSH, 1);
- if (data.min_border_type == BETWEEN_BORDER_INCLUDE) {
- grn_expr_append_op(ctx, between_expr, GRN_OP_GREATER_EQUAL, 2);
- } else {
- grn_expr_append_op(ctx, between_expr, GRN_OP_GREATER, 2);
+ return found;
+}
+
+static grn_bool
+selector_between_sequential_search_should_use(grn_ctx *ctx,
+ grn_obj *table,
+ grn_obj *index,
+ grn_obj *index_table,
+ between_data *data,
+ grn_obj *res,
+ grn_operator op,
+ double too_many_index_match_ratio)
+{
+ int n_index_keys;
+
+ if (too_many_index_match_ratio < 0.0) {
+ return GRN_FALSE;
}
- grn_expr_append_obj(ctx, between_expr, data.value, GRN_OP_PUSH, 1);
- grn_expr_append_obj(ctx, between_expr, data.max, GRN_OP_PUSH, 1);
- if (data.max_border_type == BETWEEN_BORDER_INCLUDE) {
- grn_expr_append_op(ctx, between_expr, GRN_OP_LESS_EQUAL, 2);
- } else {
- grn_expr_append_op(ctx, between_expr, GRN_OP_LESS, 2);
+ if (op != GRN_OP_AND) {
+ return GRN_FALSE;
}
- grn_expr_append_op(ctx, between_expr, GRN_OP_AND, 2);
+ if (index->header.flags & GRN_OBJ_WITH_WEIGHT) {
+ return GRN_FALSE;
+ }
- GRN_RECORD_SET(ctx, between_variable, GRN_RECORD_VALUE(variable));
- result = grn_expr_exec(ctx, between_expr, 0);
- if (result && GRN_UINT32_VALUE(result) > 0) {
- GRN_BOOL_SET(ctx, found, GRN_TRUE);
+ n_index_keys = grn_table_size(ctx, index_table);
+ if (n_index_keys == 0) {
+ return GRN_FALSE;
}
- grn_obj_unlink(ctx, between_expr);
- grn_obj_unlink(ctx, table);
+ switch (index_table->header.domain) {
+ /* TODO: */
+ /* case GRN_DB_INT8 : */
+ /* case GRN_DB_UINT8 : */
+ /* case GRN_DB_INT16 : */
+ /* case GRN_DB_UINT16 : */
+ /* case GRN_DB_INT32 : */
+ /* case GRN_DB_UINT32 : */
+ /* case GRN_DB_INT64 : */
+ /* case GRN_DB_UINT64 : */
+ /* case GRN_DB_FLOAT : */
+ case GRN_DB_TIME :
+ break;
+ default :
+ return GRN_FALSE;
+ }
- return found;
+ {
+ grn_table_cursor *cursor;
+ long long int all_min;
+ long long int all_max;
+ cursor = grn_table_cursor_open(ctx, index_table,
+ NULL, -1,
+ NULL, -1,
+ 0, 1,
+ GRN_CURSOR_BY_KEY | GRN_CURSOR_ASCENDING);
+ if (!cursor) {
+ return GRN_FALSE;
+ }
+ if (grn_table_cursor_next(ctx, cursor) == GRN_ID_NIL) {
+ grn_table_cursor_close(ctx, cursor);
+ return GRN_FALSE;
+ }
+ {
+ long long int *key;
+ grn_table_cursor_get_key(ctx, cursor, (void **)&key);
+ all_min = *key;
+ }
+ grn_table_cursor_close(ctx, cursor);
+
+ cursor = grn_table_cursor_open(ctx, index_table,
+ NULL, 0, NULL, 0,
+ 0, 1,
+ GRN_CURSOR_BY_KEY | GRN_CURSOR_DESCENDING);
+ if (!cursor) {
+ return GRN_FALSE;
+ }
+ if (grn_table_cursor_next(ctx, cursor) == GRN_ID_NIL) {
+ grn_table_cursor_close(ctx, cursor);
+ return GRN_FALSE;
+ }
+ {
+ long long int *key;
+ grn_table_cursor_get_key(ctx, cursor, (void **)&key);
+ all_max = *key;
+ }
+ grn_table_cursor_close(ctx, cursor);
+
+ /*
+ * We assume the following:
+ * * homogeneous index key distribution.
+ * * each index key matches only 1 record.
+ * TODO: Improve me.
+ */
+ {
+ int n_existing_records;
+ int n_indexed_records;
+ long long int all_difference;
+ long long int argument_difference;
+
+ n_existing_records = grn_table_size(ctx, res);
+
+ all_difference = all_max - all_min;
+ if (all_difference <= 0) {
+ return GRN_FALSE;
+ }
+ argument_difference =
+ GRN_TIME_VALUE(data->max) - GRN_TIME_VALUE(data->min);
+ if (argument_difference <= 0) {
+ return GRN_FALSE;
+ }
+ n_indexed_records =
+ n_index_keys * ((double)argument_difference / (double)all_difference);
+
+ /*
+ * Same as:
+ * ((n_existing_record / n_indexed_records) > too_many_index_match_ratio)
+ */
+ if (n_existing_records > (n_indexed_records * too_many_index_match_ratio)) {
+ return GRN_FALSE;
+ }
+ }
+ }
+
+ return GRN_TRUE;
+}
+
+static grn_bool
+selector_between_sequential_search(grn_ctx *ctx,
+ grn_obj *table,
+ grn_obj *index, grn_obj *index_table,
+ between_data *data,
+ grn_obj *res, grn_operator op)
+{
+ double too_many_index_match_ratio = 0.01;
+
+ {
+ const char *too_many_index_match_ratio_env =
+ getenv("GRN_BETWEEN_TOO_MANY_INDEX_MATCH_RATIO");
+ if (too_many_index_match_ratio_env) {
+ too_many_index_match_ratio = atof(too_many_index_match_ratio_env);
+ }
+ }
+
+ if (!selector_between_sequential_search_should_use(
+ ctx, table, index, index_table, data, res, op,
+ too_many_index_match_ratio)) {
+ return GRN_FALSE;
+ }
+
+ {
+ int offset = 0;
+ int limit = -1;
+ int flags = 0;
+ grn_table_cursor *cursor;
+ grn_obj *expr;
+ grn_obj *variable;
+ grn_id id;
+
+ if (!between_create_expr(ctx, table, data, &expr, &variable)) {
+ return GRN_FALSE;
+ }
+
+ cursor = grn_table_cursor_open(ctx, res,
+ NULL, 0,
+ NULL, 0,
+ offset, limit, flags);
+ if (!cursor) {
+ grn_obj_unlink(ctx, expr);
+ return GRN_FALSE;
+ }
+
+ while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) {
+ grn_id record_id;
+ grn_obj *result;
+ {
+ grn_id *key;
+ grn_table_cursor_get_key(ctx, cursor, (void **)&key);
+ record_id = *key;
+ }
+ GRN_RECORD_SET(ctx, variable, record_id);
+ result = grn_expr_exec(ctx, expr, 0);
+ if (ctx->rc) {
+ break;
+ }
+ if (result) {
+ grn_bool result_boolean;
+ GRN_TRUEP(ctx, result, result_boolean);
+ if (result_boolean) {
+ grn_ii_posting posting;
+ posting.rid = record_id;
+ posting.sid = 1;
+ posting.pos = 0;
+ posting.weight = 0;
+ grn_ii_posting_add(ctx, &posting, (grn_hash *)res, op);
+ }
+ }
+ }
+ grn_obj_unlink(ctx, expr);
+ grn_table_cursor_close(ctx, cursor);
+
+ grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op);
+ }
+
+ return GRN_TRUE;
}
static grn_rc
@@ -4908,9 +5556,6 @@ selector_between(grn_ctx *ctx, grn_obj *table, grn_obj *index,
int limit = -1;
int flags = GRN_CURSOR_ASCENDING | GRN_CURSOR_BY_KEY;
between_data data;
- grn_obj casted_min, casted_max;
- grn_obj *used_min = NULL;
- grn_obj *used_max = NULL;
grn_obj *index_table = NULL;
grn_table_cursor *cursor;
grn_id id;
@@ -4919,9 +5564,10 @@ selector_between(grn_ctx *ctx, grn_obj *table, grn_obj *index,
return GRN_INVALID_ARGUMENT;
}
+ between_data_init(ctx, &data);
rc = between_parse_args(ctx, nargs - 1, args + 1, &data);
if (rc != GRN_SUCCESS) {
- return rc;
+ goto exit;
}
if (data.min_border_type == BETWEEN_BORDER_EXCLUDE) {
@@ -4932,31 +5578,16 @@ selector_between(grn_ctx *ctx, grn_obj *table, grn_obj *index,
}
index_table = grn_ctx_at(ctx, index->header.domain);
- if (data.min->header.domain == index_table->header.domain) {
- used_min = data.min;
- } else {
- used_min = &casted_min;
- rc = between_cast(ctx, data.min, &casted_min, index_table->header.domain,
- "min");
- if (rc != GRN_SUCCESS) {
- goto exit;
- }
- }
- if (data.max->header.domain == index_table->header.domain) {
- used_max = data.max;
- } else {
- used_max = &casted_max;
- rc = between_cast(ctx, data.max, &casted_max, index_table->header.domain,
- "max");
- if (rc != GRN_SUCCESS) {
- goto exit;
- }
+ if (selector_between_sequential_search(ctx, table, index, index_table,
+ &data, res, op)) {
+ goto exit;
}
+
cursor = grn_table_cursor_open(ctx, index_table,
- GRN_BULK_HEAD(used_min),
- GRN_BULK_VSIZE(used_min),
- GRN_BULK_HEAD(used_max),
- GRN_BULK_VSIZE(used_max),
+ GRN_BULK_HEAD(data.min),
+ GRN_BULK_VSIZE(data.min),
+ GRN_BULK_HEAD(data.max),
+ GRN_BULK_VSIZE(data.max),
offset, limit, flags);
if (!cursor) {
rc = ctx->rc;
@@ -4970,12 +5601,7 @@ selector_between(grn_ctx *ctx, grn_obj *table, grn_obj *index,
grn_table_cursor_close(ctx, cursor);
exit :
- if (used_min == &casted_min) {
- grn_obj_unlink(ctx, &casted_min);
- }
- if (used_max == &casted_max) {
- grn_obj_unlink(ctx, &casted_max);
- }
+ between_data_fin(ctx, &data);
if (index_table) {
grn_obj_unlink(ctx, index_table);
}
@@ -5249,6 +5875,564 @@ func_highlight_full(grn_ctx *ctx, int nargs, grn_obj **args,
return highlighted;
}
+static grn_obj *
+func_in_values(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
+{
+ grn_obj *found;
+ grn_obj *target_value;
+ int i;
+
+ found = GRN_PROC_ALLOC(GRN_DB_BOOL, 0);
+ if (!found) {
+ return NULL;
+ }
+ GRN_BOOL_SET(ctx, found, GRN_FALSE);
+
+ if (nargs < 1) {
+ ERR(GRN_INVALID_ARGUMENT,
+ "in_values(): wrong number of arguments (%d for 1..)", nargs);
+ return found;
+ }
+
+ target_value = args[0];
+ for (i = 1; i < nargs; i++) {
+ grn_obj *value = args[i];
+ grn_bool result;
+
+ result = grn_operator_exec_equal(ctx, target_value, value);
+ if (ctx->rc) {
+ break;
+ }
+
+ if (result) {
+ GRN_BOOL_SET(ctx, found, GRN_TRUE);
+ break;
+ }
+ }
+
+ return found;
+}
+
+static grn_bool
+is_reference_type_column(grn_ctx *ctx, grn_obj *column)
+{
+ grn_bool is_reference_type;
+ grn_obj *range;
+
+ range = grn_ctx_at(ctx, grn_obj_get_range(ctx, column));
+ switch (range->header.type) {
+ case GRN_TABLE_HASH_KEY :
+ case GRN_TABLE_PAT_KEY :
+ case GRN_TABLE_DAT_KEY :
+ is_reference_type = GRN_TRUE;
+ break;
+ default :
+ is_reference_type = GRN_FALSE;
+ break;
+ }
+ grn_obj_unlink(ctx, range);
+
+ return is_reference_type;
+}
+
+static grn_obj *
+selector_in_values_find_source(grn_ctx *ctx, grn_obj *index, grn_obj *res)
+{
+ grn_id source_id = GRN_ID_NIL;
+ grn_obj source_ids;
+ unsigned int n_source_ids;
+
+ GRN_UINT32_INIT(&source_ids, GRN_OBJ_VECTOR);
+ grn_obj_get_info(ctx, index, GRN_INFO_SOURCE, &source_ids);
+ n_source_ids = GRN_BULK_VSIZE(&source_ids) / sizeof(grn_id);
+ if (n_source_ids == 1) {
+ source_id = GRN_UINT32_VALUE_AT(&source_ids, 0);
+ }
+ GRN_OBJ_FIN(ctx, &source_ids);
+
+ if (source_id == GRN_ID_NIL) {
+ return NULL;
+ } else {
+ return grn_ctx_at(ctx, source_id);
+ }
+}
+
+static grn_bool
+selector_in_values_sequential_search(grn_ctx *ctx,
+ grn_obj *table,
+ grn_obj *index,
+ int n_values,
+ grn_obj **values,
+ grn_obj *res,
+ grn_operator op)
+{
+ grn_obj *source;
+ int n_existing_records;
+ double too_many_index_match_ratio = 0.01;
+
+ {
+ const char *too_many_index_match_ratio_env =
+ getenv("GRN_IN_VALUES_TOO_MANY_INDEX_MATCH_RATIO");
+ if (too_many_index_match_ratio_env) {
+ too_many_index_match_ratio = atof(too_many_index_match_ratio_env);
+ }
+ }
+
+ if (too_many_index_match_ratio < 0.0) {
+ return GRN_FALSE;
+ }
+
+ if (op != GRN_OP_AND) {
+ return GRN_FALSE;
+ }
+
+ if (index->header.flags & GRN_OBJ_WITH_WEIGHT) {
+ return GRN_FALSE;
+ }
+
+ n_existing_records = grn_table_size(ctx, res);
+ if (n_existing_records == 0) {
+ return GRN_TRUE;
+ }
+
+ source = selector_in_values_find_source(ctx, index, res);
+ if (!source) {
+ return GRN_FALSE;
+ }
+
+ if (!is_reference_type_column(ctx, source)) {
+ grn_obj_unlink(ctx, source);
+ return GRN_FALSE;
+ }
+
+ {
+ grn_obj value_ids;
+ int i, n_value_ids;
+ int n_indexed_records = 0;
+
+ {
+ grn_id range_id;
+ grn_obj *range;
+
+ range_id = grn_obj_get_range(ctx, source);
+ range = grn_ctx_at(ctx, range_id);
+ if (!range) {
+ grn_obj_unlink(ctx, source);
+ return GRN_FALSE;
+ }
+
+ GRN_RECORD_INIT(&value_ids, GRN_OBJ_VECTOR, range_id);
+ for (i = 0; i < n_values; i++) {
+ grn_obj *value = values[i];
+ grn_id value_id;
+
+ value_id = grn_table_get(ctx, range,
+ GRN_TEXT_VALUE(value), GRN_TEXT_LEN(value));
+ if (value_id == GRN_ID_NIL) {
+ continue;
+ }
+ GRN_RECORD_PUT(ctx, &value_ids, value_id);
+ }
+ grn_obj_unlink(ctx, range);
+ }
+
+ n_value_ids = GRN_BULK_VSIZE(&value_ids) / sizeof(grn_id);
+ for (i = 0; i < n_value_ids; i++) {
+ grn_id value_id = GRN_RECORD_VALUE_AT(&value_ids, i);
+ n_indexed_records += grn_ii_estimate_size(ctx, (grn_ii *)index, value_id);
+ }
+
+ /*
+ * Same as:
+ * ((n_existing_record / n_indexed_records) > too_many_index_match_ratio)
+ */
+ if (n_existing_records > (n_indexed_records * too_many_index_match_ratio)) {
+ grn_obj_unlink(ctx, &value_ids);
+ grn_obj_unlink(ctx, source);
+ return GRN_FALSE;
+ }
+
+ {
+ grn_obj *accessor;
+ char local_source_name[GRN_TABLE_MAX_KEY_SIZE];
+ int local_source_name_length;
+
+ local_source_name_length = grn_column_name(ctx, source,
+ local_source_name,
+ GRN_TABLE_MAX_KEY_SIZE);
+ grn_obj_unlink(ctx, source);
+ accessor = grn_obj_column(ctx, res,
+ local_source_name,
+ local_source_name_length);
+ {
+ grn_table_cursor *cursor;
+ grn_id record_id;
+ grn_obj record_value;
+ GRN_RECORD_INIT(&record_value, 0, grn_obj_id(ctx, res));
+ cursor = grn_table_cursor_open(ctx, res,
+ NULL, 0, NULL, 0,
+ 0, -1, GRN_CURSOR_ASCENDING);
+ while ((record_id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) {
+ GRN_BULK_REWIND(&record_value);
+ grn_obj_get_value(ctx, accessor, record_id, &record_value);
+ for (i = 0; i < n_value_ids; i++) {
+ grn_id value_id = GRN_RECORD_VALUE_AT(&value_ids, i);
+ if (value_id == GRN_RECORD_VALUE(&record_value)) {
+ grn_ii_posting posting;
+ posting.rid = record_id;
+ posting.sid = 1;
+ posting.pos = 0;
+ posting.weight = 0;
+ grn_ii_posting_add(ctx, &posting, (grn_hash *)res, op);
+ }
+ }
+ }
+ grn_table_cursor_close(ctx, cursor);
+ grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op);
+ GRN_OBJ_FIN(ctx, &record_value);
+ }
+ grn_obj_unlink(ctx, accessor);
+ }
+ grn_obj_unlink(ctx, &value_ids);
+ }
+ grn_obj_unlink(ctx, source);
+
+ return GRN_TRUE;
+}
+
+static grn_rc
+selector_in_values(grn_ctx *ctx, grn_obj *table, grn_obj *index,
+ int nargs, grn_obj **args,
+ grn_obj *res, grn_operator op)
+{
+ grn_rc rc = GRN_SUCCESS;
+ int i, n_values;
+ grn_obj **values;
+
+ if (!index) {
+ return GRN_INVALID_ARGUMENT;
+ }
+
+ if (nargs < 2) {
+ ERR(GRN_INVALID_ARGUMENT,
+ "in_values(): wrong number of arguments (%d for 1..)", nargs);
+ return ctx->rc;
+ }
+
+ n_values = nargs - 2;
+ values = args + 2;
+
+ if (n_values == 0) {
+ return rc;
+ }
+
+ if (selector_in_values_sequential_search(ctx, table, index,
+ n_values, values,
+ res, op)) {
+ return ctx->rc;
+ }
+
+ ctx->flags |= GRN_CTX_TEMPORARY_DISABLE_II_RESOLVE_SEL_AND;
+ for (i = 0; i < n_values; i++) {
+ grn_obj *value = values[i];
+ grn_search_optarg search_options;
+ memset(&search_options, 0, sizeof(grn_search_optarg));
+ search_options.mode = GRN_OP_EXACT;
+ search_options.similarity_threshold = 0;
+ search_options.max_interval = 0;
+ search_options.weight_vector = NULL;
+ search_options.vector_size = 0;
+ search_options.proc = NULL;
+ search_options.max_size = 0;
+ search_options.scorer = NULL;
+ if (i == n_values - 1) {
+ ctx->flags &= ~GRN_CTX_TEMPORARY_DISABLE_II_RESOLVE_SEL_AND;
+ }
+ rc = grn_obj_search(ctx, index, value, res, op, &search_options);
+ if (rc != GRN_SUCCESS) {
+ break;
+ }
+ }
+
+ return rc;
+}
+
+static grn_obj *
+proc_range_filter(grn_ctx *ctx, int nargs, grn_obj **args,
+ grn_user_data *user_data)
+{
+ grn_obj *table_name = VAR(0);
+ grn_obj *column_name = VAR(1);
+ grn_obj *min = VAR(2);
+ grn_obj *min_border = VAR(3);
+ grn_obj *max = VAR(4);
+ grn_obj *max_border = VAR(5);
+ grn_obj *offset = VAR(6);
+ grn_obj *limit = VAR(7);
+ grn_obj *filter = VAR(8);
+ grn_obj *output_columns = VAR(9);
+ grn_obj *table;
+ grn_obj *res = NULL;
+ grn_obj *filter_expr = NULL;
+ grn_obj *filter_variable = NULL;
+ int real_offset;
+ int real_limit;
+
+ table = grn_ctx_get(ctx, GRN_TEXT_VALUE(table_name), GRN_TEXT_LEN(table_name));
+ if (!table) {
+ ERR(GRN_INVALID_ARGUMENT,
+ "[range_filter] nonexistent table <%.*s>",
+ (int)GRN_TEXT_LEN(table_name), GRN_TEXT_VALUE(table_name));
+ return NULL;
+ }
+
+ if (GRN_TEXT_LEN(filter) > 0) {
+ GRN_EXPR_CREATE_FOR_QUERY(ctx, table, filter_expr, filter_variable);
+ if (!filter_expr) {
+ ERR(GRN_INVALID_ARGUMENT,
+ "[range_filter] failed to create expression");
+ goto exit;
+ }
+
+ grn_expr_parse(ctx, filter_expr,
+ GRN_TEXT_VALUE(filter), GRN_TEXT_LEN(filter),
+ NULL, GRN_OP_MATCH, GRN_OP_AND, GRN_EXPR_SYNTAX_SCRIPT);
+ if (ctx->rc != GRN_SUCCESS) {
+ goto exit;
+ }
+ }
+
+ res = grn_table_create(ctx, NULL, 0, NULL,
+ GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC,
+ table, NULL);
+ if (!res) {
+ ERR(GRN_INVALID_ARGUMENT,
+ "[range_filter] failed to result table");
+ goto exit;
+ }
+
+ {
+ grn_obj int32_value;
+
+ GRN_INT32_INIT(&int32_value, 0);
+
+ if (GRN_TEXT_LEN(offset) > 0) {
+ if (grn_obj_cast(ctx, offset, &int32_value, GRN_FALSE) != GRN_SUCCESS) {
+ ERR(GRN_INVALID_ARGUMENT,
+ "[range_filter] invalid offset format: <%.*s>",
+ (int)GRN_TEXT_LEN(offset), GRN_TEXT_VALUE(offset));
+ GRN_OBJ_FIN(ctx, &int32_value);
+ goto exit;
+ }
+ real_offset = GRN_INT32_VALUE(&int32_value);
+ } else {
+ real_offset = 0;
+ }
+
+ GRN_BULK_REWIND(&int32_value);
+
+ if (GRN_TEXT_LEN(limit) > 0) {
+ if (grn_obj_cast(ctx, limit, &int32_value, GRN_FALSE) != GRN_SUCCESS) {
+ ERR(GRN_INVALID_ARGUMENT,
+ "[range_filter] invalid limit format: <%.*s>",
+ (int)GRN_TEXT_LEN(limit), GRN_TEXT_VALUE(limit));
+ GRN_OBJ_FIN(ctx, &int32_value);
+ goto exit;
+ }
+ real_limit = GRN_INT32_VALUE(&int32_value);
+ } else {
+ real_limit = DEFAULT_LIMIT;
+ }
+
+ GRN_OBJ_FIN(ctx, &int32_value);
+ }
+ {
+ grn_rc rc;
+ int original_offset = real_offset;
+ int original_limit = real_limit;
+ rc = grn_normalize_offset_and_limit(ctx, grn_table_size(ctx, table),
+ &real_offset, &real_limit);
+ switch (rc) {
+ case GRN_TOO_SMALL_OFFSET :
+ ERR(GRN_INVALID_ARGUMENT,
+ "[range_filter] too small offset: <%d>", original_offset);
+ goto exit;
+ case GRN_TOO_LARGE_OFFSET :
+ ERR(GRN_INVALID_ARGUMENT,
+ "[range_filter] too large offset: <%d>", original_offset);
+ goto exit;
+ case GRN_TOO_SMALL_LIMIT :
+ ERR(GRN_INVALID_ARGUMENT,
+ "[range_filter] too small limit: <%d>", original_limit);
+ goto exit;
+ default :
+ break;
+ }
+ }
+
+ if (real_limit != 0) {
+ grn_table_sort_key *sort_keys;
+ unsigned int n_sort_keys;
+ sort_keys = grn_table_sort_key_from_str(ctx,
+ GRN_TEXT_VALUE(column_name),
+ GRN_TEXT_LEN(column_name),
+ table,
+ &n_sort_keys);
+ if (n_sort_keys == 1) {
+ grn_table_sort_key *sort_key;
+ grn_obj *index;
+ int n_indexes;
+ grn_operator op = GRN_OP_OR;
+
+ sort_key = &(sort_keys[0]);
+ n_indexes = grn_column_index(ctx, sort_key->key, GRN_OP_LESS,
+ &index, 1, NULL);
+ if (n_indexes > 0) {
+ grn_obj *lexicon;
+ grn_table_cursor *table_cursor;
+ int table_cursor_flags = 0;
+ between_border_type min_border_type;
+ between_border_type max_border_type;
+ grn_obj real_min;
+ grn_obj real_max;
+ int n_records = 0;
+ grn_obj *index_cursor;
+ int index_cursor_flags = 0;
+ grn_posting *posting;
+
+ lexicon = grn_ctx_at(ctx, index->header.domain);
+ if (sort_key->flags & GRN_TABLE_SORT_DESC) {
+ table_cursor_flags |= GRN_CURSOR_DESCENDING;
+ } else {
+ table_cursor_flags |= GRN_CURSOR_ASCENDING;
+ }
+ if (GRN_TEXT_LEN(min_border) > 0) {
+ min_border_type = between_parse_border(ctx, min_border, "min_border");
+ } else {
+ min_border_type = BETWEEN_BORDER_INCLUDE;
+ }
+ if (GRN_TEXT_LEN(max_border) > 0) {
+ max_border_type = between_parse_border(ctx, max_border, "max_border");
+ } else {
+ max_border_type = BETWEEN_BORDER_INCLUDE;
+ }
+ if (min_border_type == BETWEEN_BORDER_EXCLUDE) {
+ table_cursor_flags |= GRN_CURSOR_GT;
+ }
+ if (max_border_type == BETWEEN_BORDER_EXCLUDE) {
+ table_cursor_flags |= GRN_CURSOR_LT;
+ }
+ GRN_OBJ_INIT(&real_min, GRN_BULK, 0, lexicon->header.domain);
+ GRN_OBJ_INIT(&real_max, GRN_BULK, 0, lexicon->header.domain);
+ if (GRN_TEXT_LEN(min) > 0) {
+ grn_obj_cast(ctx, min, &real_min, GRN_FALSE);
+ }
+ if (GRN_TEXT_LEN(max) > 0) {
+ grn_obj_cast(ctx, max, &real_max, GRN_FALSE);
+ }
+ table_cursor = grn_table_cursor_open(ctx, lexicon,
+ GRN_BULK_HEAD(&real_min),
+ GRN_BULK_VSIZE(&real_min),
+ GRN_BULK_HEAD(&real_max),
+ GRN_BULK_VSIZE(&real_max),
+ 0, -1, table_cursor_flags);
+ index_cursor = grn_index_cursor_open(ctx, table_cursor,
+ index, GRN_ID_NIL, GRN_ID_NIL,
+ index_cursor_flags);
+ while ((posting = grn_index_cursor_next(ctx, index_cursor, NULL))) {
+ grn_bool result_boolean = GRN_FALSE;
+
+ if (filter_expr) {
+ grn_obj *result;
+ GRN_RECORD_SET(ctx, filter_variable, posting->rid);
+ result = grn_expr_exec(ctx, filter_expr, 0);
+ if (ctx->rc) {
+ break;
+ }
+ if (result) {
+ GRN_TRUEP(ctx, result, result_boolean);
+ }
+ } else {
+ result_boolean = GRN_TRUE;
+ }
+
+ if (result_boolean) {
+ if (n_records >= real_offset) {
+ grn_ii_posting ii_posting;
+ ii_posting.rid = posting->rid;
+ ii_posting.sid = posting->sid;
+ ii_posting.pos = posting->pos;
+ ii_posting.weight = posting->weight;
+ grn_ii_posting_add(ctx, &ii_posting, (grn_hash *)res, op);
+ }
+ n_records++;
+ if (n_records == real_limit) {
+ break;
+ }
+ }
+ }
+ grn_obj_unlink(ctx, index_cursor);
+ grn_table_cursor_close(ctx, table_cursor);
+
+ GRN_OBJ_FIN(ctx, &real_min);
+ GRN_OBJ_FIN(ctx, &real_max);
+ }
+ grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op);
+ }
+ grn_table_sort_key_close(ctx, sort_keys, n_sort_keys);
+ }
+
+ if (ctx->rc == GRN_SUCCESS) {
+ const char *raw_output_columns;
+ int raw_output_columns_len;
+
+ raw_output_columns = GRN_TEXT_VALUE(output_columns);
+ raw_output_columns_len = GRN_TEXT_LEN(output_columns);
+ if (raw_output_columns_len == 0) {
+ raw_output_columns = DEFAULT_OUTPUT_COLUMNS;
+ raw_output_columns_len = strlen(raw_output_columns);
+ }
+ grn_select_output_columns(ctx, res, -1, real_offset, real_limit,
+ raw_output_columns,
+ raw_output_columns_len,
+ filter_expr);
+ }
+
+exit :
+ if (filter_expr) {
+ grn_obj_unlink(ctx, filter_expr);
+ }
+ if (res) {
+ grn_obj_unlink(ctx, res);
+ }
+
+ return NULL;
+}
+
+static grn_obj *
+proc_request_cancel(grn_ctx *ctx, int nargs, grn_obj **args,
+ grn_user_data *user_data)
+{
+ grn_obj *id = VAR(0);
+ grn_bool canceled;
+
+ if (GRN_TEXT_LEN(id) == 0) {
+ ERR(GRN_INVALID_ARGUMENT, "[request_cancel] ID is missing");
+ return NULL;
+ }
+
+ canceled = grn_request_canceler_cancel(GRN_TEXT_VALUE(id), GRN_TEXT_LEN(id));
+
+ GRN_OUTPUT_MAP_OPEN("result", 2);
+ GRN_OUTPUT_CSTR("id");
+ GRN_OUTPUT_STR(GRN_TEXT_VALUE(id), GRN_TEXT_LEN(id));
+ GRN_OUTPUT_CSTR("canceled");
+ GRN_OUTPUT_BOOL(canceled);
+ GRN_OUTPUT_MAP_CLOSE();
+
+ return NULL;
+}
+
#define DEF_VAR(v,name_str) do {\
(v).name = (name_str);\
(v).name_size = GRN_STRLEN(name_str);\
@@ -5262,7 +6446,7 @@ func_highlight_full(grn_ctx *ctx, int nargs, grn_obj **args,
void
grn_db_init_builtin_query(grn_ctx *ctx)
{
- grn_expr_var vars[21];
+ grn_expr_var vars[23];
DEF_VAR(vars[0], "name");
DEF_VAR(vars[1], "table");
@@ -5286,8 +6470,10 @@ grn_db_init_builtin_query(grn_ctx *ctx)
DEF_VAR(vars[18], "query_flags");
DEF_VAR(vars[19], "query_expander");
DEF_VAR(vars[20], "adjuster");
- DEF_COMMAND("define_selector", proc_define_selector, 21, vars);
- DEF_COMMAND("select", proc_select, 20, vars + 1);
+ DEF_VAR(vars[21], "drilldown_calc_types");
+ DEF_VAR(vars[22], "drilldown_calc_target");
+ DEF_COMMAND("define_selector", proc_define_selector, 23, vars);
+ DEF_COMMAND("select", proc_select, 22, vars + 1);
DEF_VAR(vars[0], "values");
DEF_VAR(vars[1], "table");
@@ -5343,8 +6529,12 @@ grn_db_init_builtin_query(grn_ctx *ctx)
DEF_COMMAND("shutdown", proc_shutdown, 0, vars);
+ /* Deprecated. Use "lock_clear" instead. */
+ DEF_VAR(vars[0], "target_name");
+ DEF_COMMAND("clearlock", proc_lock_clear, 1, vars);
+
DEF_VAR(vars[0], "target_name");
- DEF_COMMAND("clearlock", proc_clearlock, 1, vars);
+ DEF_COMMAND("lock_clear", proc_lock_clear, 1, vars);
DEF_VAR(vars[0], "target_name");
DEF_VAR(vars[1], "threshold");
@@ -5377,8 +6567,9 @@ grn_db_init_builtin_query(grn_ctx *ctx)
DEF_VAR(vars[0], "obj");
DEF_COMMAND("check", proc_check, 1, vars);
- DEF_VAR(vars[0], "table");
- DEF_COMMAND("truncate", proc_truncate, 1, vars);
+ DEF_VAR(vars[0], "target_name");
+ DEF_VAR(vars[1], "table");
+ DEF_COMMAND("truncate", proc_truncate, 2, vars);
DEF_VAR(vars[0], "normalizer");
DEF_VAR(vars[1], "string");
@@ -5390,7 +6581,14 @@ grn_db_init_builtin_query(grn_ctx *ctx)
DEF_VAR(vars[2], "normalizer");
DEF_VAR(vars[3], "flags");
DEF_VAR(vars[4], "mode");
- DEF_COMMAND("tokenize", proc_tokenize, 5, vars);
+ DEF_VAR(vars[5], "token_filters");
+ DEF_COMMAND("tokenize", proc_tokenize, 6, vars);
+
+ DEF_VAR(vars[0], "table");
+ DEF_VAR(vars[1], "string");
+ DEF_VAR(vars[2], "flags");
+ DEF_VAR(vars[3], "mode");
+ DEF_COMMAND("table_tokenize", proc_table_tokenize, 4, vars);
DEF_COMMAND("tokenizer_list", proc_tokenizer_list, 0, vars);
@@ -5479,4 +6677,27 @@ grn_db_init_builtin_query(grn_ctx *ctx)
grn_proc_create(ctx, "highlight_full", -1, GRN_PROC_FUNCTION,
func_highlight_full, NULL, NULL, 0, NULL);
+
+ {
+ grn_obj *selector_proc;
+
+ selector_proc = grn_proc_create(ctx, "in_values", -1, GRN_PROC_FUNCTION,
+ func_in_values, NULL, NULL, 0, NULL);
+ grn_proc_set_selector(ctx, selector_proc, selector_in_values);
+ }
+
+ DEF_VAR(vars[0], "table");
+ DEF_VAR(vars[1], "column");
+ DEF_VAR(vars[2], "min");
+ DEF_VAR(vars[3], "min_border");
+ DEF_VAR(vars[4], "max");
+ DEF_VAR(vars[5], "max_border");
+ DEF_VAR(vars[6], "offset");
+ DEF_VAR(vars[7], "limit");
+ DEF_VAR(vars[8], "filter");
+ DEF_VAR(vars[9], "output_columns");
+ DEF_COMMAND("range_filter", proc_range_filter, 10, vars);
+
+ DEF_VAR(vars[0], "id");
+ DEF_COMMAND("request_cancel", proc_request_cancel, 1, vars);
}
diff --git a/storage/mroonga/vendor/groonga/lib/request_canceler.c b/storage/mroonga/vendor/groonga/lib/request_canceler.c
new file mode 100644
index 00000000000..866292f73de
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/request_canceler.c
@@ -0,0 +1,123 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "grn_ctx.h"
+#include "grn_request_canceler.h"
+
+typedef struct _grn_request_canceler grn_request_canceler;
+struct _grn_request_canceler {
+ grn_hash *entries;
+ grn_mutex mutex;
+};
+
+typedef struct _grn_request_canceler_entry grn_request_canceler_entry;
+struct _grn_request_canceler_entry {
+ grn_ctx *ctx;
+};
+
+static grn_request_canceler *grn_the_request_canceler = NULL;
+
+grn_bool
+grn_request_canceler_init(void)
+{
+ grn_ctx *ctx = &grn_gctx;
+
+ grn_the_request_canceler = GRN_MALLOC(sizeof(grn_request_canceler));
+ if (!grn_the_request_canceler) {
+ ERR(GRN_NO_MEMORY_AVAILABLE,
+ "[request-canceler] failed to allocate the global request canceler");
+ return GRN_FALSE;
+ }
+
+ grn_the_request_canceler->entries =
+ grn_hash_create(ctx, NULL, GRN_TABLE_MAX_KEY_SIZE,
+ sizeof(grn_request_canceler_entry), GRN_OBJ_KEY_VAR_SIZE);
+ if (!grn_the_request_canceler->entries) {
+ return GRN_FALSE;
+ }
+ MUTEX_INIT(grn_the_request_canceler->mutex);
+
+ return GRN_TRUE;
+}
+
+void
+grn_request_canceler_register(grn_ctx *ctx,
+ const char *request_id, unsigned int size)
+{
+ MUTEX_LOCK(grn_the_request_canceler->mutex);
+ {
+ grn_hash *entries = grn_the_request_canceler->entries;
+ grn_id id;
+ void *value;
+ id = grn_hash_add(&grn_gctx, entries, request_id, size, &value, NULL);
+ if (id) {
+ grn_request_canceler_entry *entry = value;
+ entry->ctx = ctx;
+ }
+ }
+ MUTEX_UNLOCK(grn_the_request_canceler->mutex);
+}
+
+void
+grn_request_canceler_unregister(grn_ctx *ctx,
+ const char *request_id, unsigned int size)
+{
+ MUTEX_LOCK(grn_the_request_canceler->mutex);
+ {
+ grn_hash *entries = grn_the_request_canceler->entries;
+ grn_hash_delete(&grn_gctx, entries, request_id, size, NULL);
+ }
+ MUTEX_UNLOCK(grn_the_request_canceler->mutex);
+
+ if (ctx->rc == GRN_INTERRUPTED_FUNCTION_CALL) {
+ ERRSET(ctx, GRN_LOG_NOTICE, ctx->rc,
+ "[request-canceler] a request is canceled: <%.*s>",
+ size, request_id);
+ }
+}
+
+grn_bool
+grn_request_canceler_cancel(const char *request_id, unsigned int size)
+{
+ grn_bool canceled = GRN_FALSE;
+ MUTEX_LOCK(grn_the_request_canceler->mutex);
+ {
+ grn_hash *entries = grn_the_request_canceler->entries;
+ void *value;
+ if (grn_hash_get(&grn_gctx, entries, request_id, size, &value)) {
+ grn_request_canceler_entry *entry = value;
+ if (entry->ctx->rc == GRN_SUCCESS) {
+ entry->ctx->rc = GRN_INTERRUPTED_FUNCTION_CALL;
+ canceled = GRN_TRUE;
+ }
+ }
+ }
+ MUTEX_UNLOCK(grn_the_request_canceler->mutex);
+ return canceled;
+}
+
+void
+grn_request_canceler_fin(void)
+{
+ grn_ctx *ctx = &grn_gctx;
+
+ grn_hash_close(ctx, grn_the_request_canceler->entries);
+ MUTEX_FIN(grn_the_request_canceler->mutex);
+ GRN_FREE(grn_the_request_canceler);
+ grn_the_request_canceler = NULL;
+}
diff --git a/storage/mroonga/vendor/groonga/lib/rset.c b/storage/mroonga/vendor/groonga/lib/rset.c
new file mode 100644
index 00000000000..85a9e1c529e
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/rset.c
@@ -0,0 +1,324 @@
+/* -*- c-basic-offset: 2 -*- */
+/* Copyright(C) 2009-2015 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#include "grn_db.h"
+
+uint32_t
+grn_rset_recinfo_calc_values_size(grn_ctx *ctx, grn_table_group_flags flags)
+{
+ uint32_t size = 0;
+
+ if (flags & GRN_TABLE_GROUP_CALC_MAX) {
+ size += GRN_RSET_MAX_SIZE;
+ }
+ if (flags & GRN_TABLE_GROUP_CALC_MIN) {
+ size += GRN_RSET_MIN_SIZE;
+ }
+ if (flags & GRN_TABLE_GROUP_CALC_SUM) {
+ size += GRN_RSET_SUM_SIZE;
+ }
+ if (flags & GRN_TABLE_GROUP_CALC_AVG) {
+ size += GRN_RSET_AVG_SIZE;
+ }
+
+ return size;
+}
+
+void
+grn_rset_recinfo_update_calc_values(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table,
+ grn_obj *value)
+{
+ grn_table_group_flags flags;
+ byte *values;
+ grn_obj value_int64;
+ grn_obj value_float;
+
+ flags = DB_OBJ(table)->flags.group;
+
+ values = (((byte *)ri->subrecs) +
+ GRN_RSET_SUBRECS_SIZE(DB_OBJ(table)->subrec_size,
+ DB_OBJ(table)->max_n_subrecs));
+
+ GRN_INT64_INIT(&value_int64, 0);
+ GRN_FLOAT_INIT(&value_float, 0);
+
+ if (flags & (GRN_TABLE_GROUP_CALC_MAX |
+ GRN_TABLE_GROUP_CALC_MIN |
+ GRN_TABLE_GROUP_CALC_SUM)) {
+ grn_obj_cast(ctx, value, &value_int64, GRN_FALSE);
+ }
+ if (flags & GRN_TABLE_GROUP_CALC_AVG) {
+ grn_obj_cast(ctx, value, &value_float, GRN_FALSE);
+ }
+
+ if (flags & GRN_TABLE_GROUP_CALC_MAX) {
+ int64_t current_max = *((int64_t *)values);
+ int64_t value_raw = GRN_INT64_VALUE(&value_int64);
+ if (ri->n_subrecs == 1 || value_raw > current_max) {
+ *((int64_t *)values) = value_raw;
+ }
+ values += GRN_RSET_MAX_SIZE;
+ }
+ if (flags & GRN_TABLE_GROUP_CALC_MIN) {
+ int64_t current_min = *((int64_t *)values);
+ int64_t value_raw = GRN_INT64_VALUE(&value_int64);
+ if (ri->n_subrecs == 1 || value_raw < current_min) {
+ *((int64_t *)values) = value_raw;
+ }
+ values += GRN_RSET_MIN_SIZE;
+ }
+ if (flags & GRN_TABLE_GROUP_CALC_SUM) {
+ int64_t value_raw = GRN_INT64_VALUE(&value_int64);
+ *((int64_t *)values) += value_raw;
+ values += GRN_RSET_SUM_SIZE;
+ }
+ if (flags & GRN_TABLE_GROUP_CALC_AVG) {
+ double current_average = *((double *)values);
+ double value_raw = GRN_FLOAT_VALUE(&value_float);
+ *((double *)values) += (value_raw - current_average) / ri->n_subrecs;
+ values += GRN_RSET_AVG_SIZE;
+ }
+
+ GRN_OBJ_FIN(ctx, &value_float);
+ GRN_OBJ_FIN(ctx, &value_int64);
+}
+
+int64_t *
+grn_rset_recinfo_get_max_(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table)
+{
+ grn_table_group_flags flags;
+ byte *values;
+
+ flags = DB_OBJ(table)->flags.group;
+ if (!(flags & GRN_TABLE_GROUP_CALC_MAX)) {
+ return NULL;
+ }
+
+ values = (((byte *)ri->subrecs) +
+ GRN_RSET_SUBRECS_SIZE(DB_OBJ(table)->subrec_size,
+ DB_OBJ(table)->max_n_subrecs));
+
+ return (int64_t *)values;
+}
+
+int64_t
+grn_rset_recinfo_get_max(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table)
+{
+ int64_t *max_address;
+
+ max_address = grn_rset_recinfo_get_max_(ctx, ri, table);
+ if (max_address) {
+ return *max_address;
+ } else {
+ return 0;
+ }
+}
+
+void
+grn_rset_recinfo_set_max(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table,
+ int64_t max)
+{
+ int64_t *max_address;
+
+ max_address = grn_rset_recinfo_get_max_(ctx, ri, table);
+ if (!max_address) {
+ return;
+ }
+
+ *max_address = max;
+}
+
+int64_t *
+grn_rset_recinfo_get_min_(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table)
+{
+ grn_table_group_flags flags;
+ byte *values;
+
+ flags = DB_OBJ(table)->flags.group;
+ if (!(flags & GRN_TABLE_GROUP_CALC_MIN)) {
+ return NULL;
+ }
+
+ values = (((byte *)ri->subrecs) +
+ GRN_RSET_SUBRECS_SIZE(DB_OBJ(table)->subrec_size,
+ DB_OBJ(table)->max_n_subrecs));
+
+ if (flags & GRN_TABLE_GROUP_CALC_MAX) {
+ values += GRN_RSET_MAX_SIZE;
+ }
+
+ return (int64_t *)values;
+}
+
+int64_t
+grn_rset_recinfo_get_min(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table)
+{
+ int64_t *min_address;
+
+ min_address = grn_rset_recinfo_get_min_(ctx, ri, table);
+ if (min_address) {
+ return *min_address;
+ } else {
+ return 0;
+ }
+}
+
+void
+grn_rset_recinfo_set_min(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table,
+ int64_t min)
+{
+ int64_t *min_address;
+
+ min_address = grn_rset_recinfo_get_min_(ctx, ri, table);
+ if (!min_address) {
+ return;
+ }
+
+ *min_address = min;
+}
+
+int64_t *
+grn_rset_recinfo_get_sum_(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table)
+{
+ grn_table_group_flags flags;
+ byte *values;
+
+ flags = DB_OBJ(table)->flags.group;
+ if (!(flags & GRN_TABLE_GROUP_CALC_SUM)) {
+ return NULL;
+ }
+
+ values = (((byte *)ri->subrecs) +
+ GRN_RSET_SUBRECS_SIZE(DB_OBJ(table)->subrec_size,
+ DB_OBJ(table)->max_n_subrecs));
+
+ if (flags & GRN_TABLE_GROUP_CALC_MAX) {
+ values += GRN_RSET_MAX_SIZE;
+ }
+ if (flags & GRN_TABLE_GROUP_CALC_MIN) {
+ values += GRN_RSET_MIN_SIZE;
+ }
+
+ return (int64_t *)values;
+}
+
+int64_t
+grn_rset_recinfo_get_sum(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table)
+{
+ int64_t *sum_address;
+
+ sum_address = grn_rset_recinfo_get_sum_(ctx, ri, table);
+ if (sum_address) {
+ return *sum_address;
+ } else {
+ return 0;
+ }
+}
+
+void
+grn_rset_recinfo_set_sum(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table,
+ int64_t sum)
+{
+ int64_t *sum_address;
+
+ sum_address = grn_rset_recinfo_get_sum_(ctx, ri, table);
+ if (!sum_address) {
+ return;
+ }
+
+ *sum_address = sum;
+}
+
+double *
+grn_rset_recinfo_get_avg_(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table)
+{
+ grn_table_group_flags flags;
+ byte *values;
+
+ flags = DB_OBJ(table)->flags.group;
+ if (!(flags & GRN_TABLE_GROUP_CALC_AVG)) {
+ return NULL;
+ }
+
+ values = (((byte *)ri->subrecs) +
+ GRN_RSET_SUBRECS_SIZE(DB_OBJ(table)->subrec_size,
+ DB_OBJ(table)->max_n_subrecs));
+
+ if (flags & GRN_TABLE_GROUP_CALC_MAX) {
+ values += GRN_RSET_MAX_SIZE;
+ }
+ if (flags & GRN_TABLE_GROUP_CALC_MIN) {
+ values += GRN_RSET_MIN_SIZE;
+ }
+ if (flags & GRN_TABLE_GROUP_CALC_SUM) {
+ values += GRN_RSET_SUM_SIZE;
+ }
+
+ return (double *)values;
+}
+
+double
+grn_rset_recinfo_get_avg(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table)
+{
+ double *avg_address;
+
+ avg_address = grn_rset_recinfo_get_avg_(ctx, ri, table);
+ if (avg_address) {
+ return *avg_address;
+ } else {
+ return 0;
+ }
+}
+
+void
+grn_rset_recinfo_set_avg(grn_ctx *ctx,
+ grn_rset_recinfo *ri,
+ grn_obj *table,
+ double avg)
+{
+ double *avg_address;
+
+ avg_address = grn_rset_recinfo_get_avg_(ctx, ri, table);
+ if (!avg_address) {
+ return;
+ }
+
+ *avg_address = avg;
+}
diff --git a/storage/mroonga/vendor/groonga/lib/scorer.c b/storage/mroonga/vendor/groonga/lib/scorer.c
new file mode 100644
index 00000000000..f5bc0435108
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/scorer.c
@@ -0,0 +1,134 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2015 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <string.h>
+
+#include "grn.h"
+#include "grn_db.h"
+#include "grn_scorer.h"
+#include <groonga/scorer.h>
+
+grn_obj *
+grn_scorer_matched_record_get_table(grn_ctx *ctx,
+ grn_scorer_matched_record *record)
+{
+ return record->table;
+}
+
+grn_obj *
+grn_scorer_matched_record_get_lexicon(grn_ctx *ctx,
+ grn_scorer_matched_record *record)
+{
+ return record->lexicon;
+}
+
+grn_id
+grn_scorer_matched_record_get_id(grn_ctx *ctx,
+ grn_scorer_matched_record *record)
+{
+ return record->id;
+}
+
+grn_obj *
+grn_scorer_matched_record_get_terms(grn_ctx *ctx,
+ grn_scorer_matched_record *record)
+{
+ return &(record->terms);
+}
+
+grn_obj *
+grn_scorer_matched_record_get_term_weights(grn_ctx *ctx,
+ grn_scorer_matched_record *record)
+{
+ return &(record->term_weights);
+}
+
+unsigned int
+grn_scorer_matched_record_get_total_term_weights(grn_ctx *ctx,
+ grn_scorer_matched_record *record)
+{
+ return record->total_term_weights;
+}
+
+long long unsigned int
+grn_scorer_matched_record_get_n_documents(grn_ctx *ctx,
+ grn_scorer_matched_record *record)
+{
+ return record->n_documents;
+}
+
+unsigned int
+grn_scorer_matched_record_get_n_occurrences(grn_ctx *ctx,
+ grn_scorer_matched_record *record)
+{
+ return record->n_occurrences;
+}
+
+long long unsigned int
+grn_scorer_matched_record_get_n_candidates(grn_ctx *ctx,
+ grn_scorer_matched_record *record)
+{
+ return record->n_candidates;
+}
+
+unsigned int
+grn_scorer_matched_record_get_n_tokens(grn_ctx *ctx,
+ grn_scorer_matched_record *record)
+{
+ return record->n_tokens;
+}
+
+int
+grn_scorer_matched_record_get_weight(grn_ctx *ctx,
+ grn_scorer_matched_record *record)
+{
+ return record->weight;
+}
+
+grn_rc
+grn_scorer_register(grn_ctx *ctx,
+ const char *plugin_name_ptr,
+ int plugin_name_length,
+ grn_scorer_score_func *score)
+{
+ if (plugin_name_length == -1) {
+ plugin_name_length = strlen(plugin_name_ptr);
+ }
+
+ {
+ grn_obj *scorer_object = grn_proc_create(ctx,
+ plugin_name_ptr,
+ plugin_name_length,
+ GRN_PROC_SCORER,
+ NULL, NULL, NULL, 0, NULL);
+ if (scorer_object == NULL) {
+ GRN_PLUGIN_ERROR(ctx, GRN_SCORER_ERROR,
+ "[scorer][%.*s] failed to grn_proc_create()",
+ plugin_name_length, plugin_name_ptr);
+ return ctx->rc;
+ }
+
+ {
+ grn_proc *scorer = (grn_proc *)scorer_object;
+ scorer->callbacks.scorer.score = score;
+ }
+ }
+
+ return GRN_SUCCESS;
+}
+
diff --git a/storage/mroonga/vendor/groonga/lib/scorers.c b/storage/mroonga/vendor/groonga/lib/scorers.c
new file mode 100644
index 00000000000..b039e011920
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/scorers.c
@@ -0,0 +1,57 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2015 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <groonga/scorer.h>
+
+#include <math.h>
+
+static double
+scorer_tf_idf(grn_ctx *ctx, grn_scorer_matched_record *record)
+{
+ double min_score = 1.0;
+ double tf;
+ double n_all_documents;
+ double n_candidates;
+ double n_tokens;
+ double n_estimated_match_documents;
+
+ tf = grn_scorer_matched_record_get_n_occurrences(ctx, record) +
+ grn_scorer_matched_record_get_total_term_weights(ctx, record);
+ n_all_documents = grn_scorer_matched_record_get_n_documents(ctx, record);
+ n_candidates = grn_scorer_matched_record_get_n_candidates(ctx, record);
+ n_tokens = grn_scorer_matched_record_get_n_tokens(ctx, record);
+ n_estimated_match_documents = n_candidates / n_tokens;
+
+ if (n_estimated_match_documents >= n_all_documents) {
+ return min_score;
+ } else {
+ double idf;
+ double tf_idf;
+
+ idf = log(n_all_documents / n_estimated_match_documents);
+ tf_idf = tf * idf;
+ return fmax(tf_idf, min_score);
+ }
+}
+
+grn_rc
+grn_db_init_builtin_scorers(grn_ctx *ctx)
+{
+ grn_scorer_register(ctx, "scorer_tf_idf", -1, scorer_tf_idf);
+ return GRN_SUCCESS;
+}
diff --git a/storage/mroonga/vendor/groonga/lib/snip.c b/storage/mroonga/vendor/groonga/lib/snip.c
index 78c6ef54387..739ee345738 100644
--- a/storage/mroonga/vendor/groonga/lib/snip.c
+++ b/storage/mroonga/vendor/groonga/lib/snip.c
@@ -14,11 +14,11 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "groonga_in.h"
+#include "grn.h"
#include <string.h>
#include <stddef.h>
-#include "snip.h"
-#include "ctx.h"
+#include "grn_snip.h"
+#include "grn_ctx.h"
#if !defined MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
diff --git a/storage/mroonga/vendor/groonga/lib/sources.am b/storage/mroonga/vendor/groonga/lib/sources.am
index 8b371081fe6..25e5df5fd4d 100644
--- a/storage/mroonga/vendor/groonga/lib/sources.am
+++ b/storage/mroonga/vendor/groonga/lib/sources.am
@@ -1,52 +1,65 @@
libgroonga_la_SOURCES = \
com.c \
- com.h \
+ grn_com.h \
+ command.c \
ctx.c \
- ctx.h \
- ctx_impl.h \
+ grn_ctx.h \
+ grn_ctx_impl.h \
ctx_impl_mrb.c \
- ctx_impl_mrb.h \
+ grn_ctx_impl_mrb.h \
dat.cpp \
- dat.h \
+ grn_dat.h \
db.c \
- db.h \
+ grn_db.h \
error.c \
- error.h \
+ grn_error.h \
expr.c \
- expr.h \
+ grn_expr.h \
geo.c \
- geo.h \
- groonga_in.h \
+ grn_geo.h \
+ grn.h \
hash.c \
- hash.h \
+ grn_hash.h \
ii.c \
- ii.h \
+ grn_ii.h \
io.c \
- io.h \
+ grn_io.h \
mrb.c \
- mrb.h \
+ grn_mrb.h \
nfkc.c \
normalizer.c \
- normalizer_in.h \
+ grn_normalizer.h \
+ obj.c \
+ operator.c \
output.c \
- output.h \
+ grn_output.h \
pat.c \
- pat.h \
+ grn_pat.h \
plugin.c \
- plugin_in.h \
+ grn_plugin.h \
proc.c \
- proc.h \
+ grn_proc.h \
+ request_canceler.c \
+ grn_request_canceler.h \
+ rset.c \
+ grn_rset.h \
+ scorer.c \
+ grn_scorer.h \
+ scorers.c \
+ grn_scorers.h \
snip.c \
- snip.h \
+ grn_snip.h \
store.c \
- store.h \
+ grn_store.h \
str.c \
- str.h \
+ grn_str.h \
string.c \
- string_in.h \
- token.c \
- token.h \
+ grn_string.h \
+ token_cursor.c \
+ grn_token_cursor.h \
tokenizer.c \
+ tokenizers.c \
+ grn_tokenizers.h \
token_filter.c \
util.c \
- util.h
+ grn_util.h
diff --git a/storage/mroonga/vendor/groonga/lib/store.c b/storage/mroonga/vendor/groonga/lib/store.c
index 3649611a560..6b3b01ce4be 100644
--- a/storage/mroonga/vendor/groonga/lib/store.c
+++ b/storage/mroonga/vendor/groonga/lib/store.c
@@ -1,5 +1,5 @@
/* -*- c-basic-offset: 2 -*- */
-/* Copyright(C) 2009-2014 Brazil
+/* Copyright(C) 2009-2015 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -14,11 +14,11 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "groonga_in.h"
-#include "str.h"
-#include "store.h"
-#include "ctx_impl.h"
-#include "output.h"
+#include "grn.h"
+#include "grn_str.h"
+#include "grn_store.h"
+#include "grn_ctx_impl.h"
+#include "grn_output.h"
#include <string.h>
/* rectangular arrays */
@@ -524,7 +524,7 @@ grn_ja_ref_raw(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *va
iw->size = 0;
iw->addr = NULL;
iw->pseg = pseg;
- iw->value = NULL;
+ iw->uncompressed_value = NULL;
if (pseg != JA_ESEG_VOID) {
grn_ja_einfo *einfo = NULL;
GRN_IO_SEG_REF(ja->io, pseg, einfo);
@@ -545,7 +545,7 @@ grn_ja_ref_raw(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *va
} else {
EINFO_DEC(ei, jag, vpos, vsize);
}
- grn_io_win_map2(ja->io, ctx, iw, jag, vpos, vsize, grn_io_rdonly);
+ grn_io_win_map(ja->io, ctx, iw, jag, vpos, vsize, grn_io_rdonly);
}
if (!iw->addr) { GRN_IO_SEG_UNREF(ja->io, pseg); }
}
@@ -557,13 +557,13 @@ grn_ja_ref_raw(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *va
grn_rc
grn_ja_unref(grn_ctx *ctx, grn_io_win *iw)
{
- if (iw->value) {
- GRN_FREE(iw->value);
- iw->value = NULL;
+ if (iw->uncompressed_value) {
+ GRN_FREE(iw->uncompressed_value);
+ iw->uncompressed_value = NULL;
} else {
if (!iw->addr) { return GRN_INVALID_ARGUMENT; }
GRN_IO_SEG_UNREF(iw->io, iw->pseg);
- if (!iw->tiny_p) { grn_io_win_unmap2(iw); }
+ if (!iw->tiny_p) { grn_io_win_unmap(iw); }
}
return GRN_SUCCESS;
}
@@ -711,7 +711,7 @@ exit :
#define JA_N_GARBAGES_TH 10
-// todo : grn_io_win_map2 cause verbose copy when nseg > 1, it should be copied directly.
+// todo : grn_io_win_map cause verbose copy when nseg > 1, it should be copied directly.
static grn_rc
grn_ja_alloc(grn_ctx *ctx, grn_ja *ja, grn_id id,
uint32_t element_size, grn_ja_einfo *einfo, grn_io_win *iw)
@@ -736,7 +736,7 @@ grn_ja_alloc(grn_ctx *ctx, grn_ja *ja, grn_id id,
} else {
if (i == j + n) {
j++;
- addr = grn_io_win_map2(ja->io, ctx, iw, j, 0, element_size, grn_io_wronly);
+ addr = grn_io_win_map(ja->io, ctx, iw, j, 0, element_size, grn_io_wronly);
if (!addr) {
grn_io_unlock(ja->io);
return GRN_NO_MEMORY_AVAILABLE;
@@ -864,7 +864,7 @@ grn_ja_alloc(grn_ctx *ctx, grn_ja *ja, grn_id id,
vp->seg = 0;
vp->pos = 0;
}
- iw->value = NULL;
+ iw->uncompressed_value = NULL;
grn_io_unlock(ja->io);
return GRN_SUCCESS;
}
@@ -883,11 +883,11 @@ set_value(grn_ctx *ctx, grn_ja *ja, grn_id id, void *value, uint32_t value_len,
}
memcpy(iw.addr, value, value_len);
memset((byte *)iw.addr + value_len, 0, sizeof(uint32_t));
- grn_io_win_unmap2(&iw);
+ grn_io_win_unmap(&iw);
} else {
if ((rc = grn_ja_alloc(ctx, ja, id, value_len, einfo, &iw))) { return rc; }
memcpy(iw.addr, value, value_len);
- grn_io_win_unmap2(&iw);
+ grn_io_win_unmap(&iw);
}
return rc;
}
@@ -953,7 +953,7 @@ grn_ja_put_raw(grn_ctx *ctx, grn_ja *ja, grn_id id,
memcpy(iw.addr, oldvalue, old_len);
memcpy((byte *)iw.addr + old_len, value, value_len);
memset((byte *)iw.addr + old_len + value_len, 0, sizeof(uint32_t));
- grn_io_win_unmap2(&iw);
+ grn_io_win_unmap(&iw);
}
} else {
if ((rc = grn_ja_alloc(ctx, ja, id, value_len + old_len, &einfo, &iw))) {
@@ -962,7 +962,7 @@ grn_ja_put_raw(grn_ctx *ctx, grn_ja *ja, grn_id id,
}
memcpy(iw.addr, oldvalue, old_len);
memcpy((byte *)iw.addr + old_len, value, value_len);
- grn_io_win_unmap2(&iw);
+ grn_io_win_unmap(&iw);
}
grn_ja_unref(ctx, &jw);
} else {
@@ -1003,7 +1003,7 @@ grn_ja_put_raw(grn_ctx *ctx, grn_ja *ja, grn_id id,
memcpy(iw.addr, value, value_len);
memcpy((byte *)iw.addr + value_len, oldvalue, old_len);
memset((byte *)iw.addr + value_len + old_len, 0, sizeof(uint32_t));
- grn_io_win_unmap2(&iw);
+ grn_io_win_unmap(&iw);
}
} else {
if ((rc = grn_ja_alloc(ctx, ja, id, value_len + old_len, &einfo, &iw))) {
@@ -1012,7 +1012,7 @@ grn_ja_put_raw(grn_ctx *ctx, grn_ja *ja, grn_id id,
}
memcpy(iw.addr, value, value_len);
memcpy((byte *)iw.addr + value_len, oldvalue, old_len);
- grn_io_win_unmap2(&iw);
+ grn_io_win_unmap(&iw);
}
grn_ja_unref(ctx, &jw);
} else {
@@ -1103,7 +1103,7 @@ grn_ja_putv(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_obj *vector, int flags)
memcpy(iw.addr, GRN_BULK_HEAD(&header), sizeh);
if (body) { memcpy((char *)iw.addr + sizeh, GRN_BULK_HEAD(body), sizev); }
if (f) { memcpy((char *)iw.addr + sizeh + sizev, GRN_BULK_HEAD(&footer), sizef); }
- grn_io_win_unmap2(&iw);
+ grn_io_win_unmap(&iw);
rc = grn_ja_replace(ctx, ja, id, &einfo, NULL);
}
exit :
@@ -1187,7 +1187,7 @@ grn_ja_ref_zlib(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *v
void *zvalue;
uint32_t zvalue_len;
if (!(zvalue = grn_ja_ref_raw(ctx, ja, id, iw, &zvalue_len))) {
- iw->value = NULL;
+ iw->uncompressed_value = NULL;
*value_len = 0;
return NULL;
}
@@ -1196,74 +1196,74 @@ grn_ja_ref_zlib(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *v
zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL;
if (inflateInit2(&zstream, 15 /* windowBits */) != Z_OK) {
- iw->value = NULL;
+ iw->uncompressed_value = NULL;
*value_len = 0;
return NULL;
}
- if (!(iw->value = GRN_MALLOC(*((uint64_t *)zvalue)))) {
+ if (!(iw->uncompressed_value = GRN_MALLOC(*((uint64_t *)zvalue)))) {
inflateEnd(&zstream);
- iw->value = NULL;
+ iw->uncompressed_value = NULL;
*value_len = 0;
return NULL;
}
- zstream.next_out = (Bytef *)iw->value;
+ zstream.next_out = (Bytef *)iw->uncompressed_value;
zstream.avail_out = *(uint64_t *)zvalue;
if (inflate(&zstream, Z_FINISH) != Z_STREAM_END) {
inflateEnd(&zstream);
- GRN_FREE(iw->value);
- iw->value = NULL;
+ GRN_FREE(iw->uncompressed_value);
+ iw->uncompressed_value = NULL;
*value_len = 0;
return NULL;
}
*value_len = zstream.total_out;
if (inflateEnd(&zstream) != Z_OK) {
- GRN_FREE(iw->value);
- iw->value = NULL;
+ GRN_FREE(iw->uncompressed_value);
+ iw->uncompressed_value = NULL;
*value_len = 0;
return NULL;
}
- return iw->value;
+ return iw->uncompressed_value;
}
#endif /* GRN_WITH_ZLIB */
-#ifdef GRN_WITH_LZO
-#include <lzo/lzo1x.h>
+#ifdef GRN_WITH_LZ4
+#include <lz4.h>
static void *
-grn_ja_ref_lzo(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *value_len)
+grn_ja_ref_lz4(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *value_len)
{
- void *lvalue;
- uint32_t lvalue_len;
- lzo_uint lout_len;
- if (!(lvalue = grn_ja_ref_raw(ctx, ja, id, iw, &lvalue_len))) {
- iw->value = NULL;
+ void *packed_value;
+ int packed_value_len;
+ void *lz4_value;
+ int lz4_value_len;
+ int original_value_len;
+
+ if (!(packed_value = grn_ja_ref_raw(ctx, ja, id, iw, &packed_value_len))) {
+ iw->uncompressed_value = NULL;
*value_len = 0;
return NULL;
}
- if (!(iw->value = GRN_MALLOC(*((uint64_t *)lvalue)))) {
- iw->value = NULL;
+ original_value_len = *((uint64_t *)packed_value);
+ if (!(iw->uncompressed_value = GRN_MALLOC(original_value_len))) {
+ iw->uncompressed_value = NULL;
*value_len = 0;
return NULL;
}
- lout_len = *((uint64_t *)lvalue);
- switch (lzo1x_decompress((lzo_bytep)(((uint64_t *)lvalue) + 1),
- lvalue_len,
- (lzo_bytep)(iw->value),
- &lout_len,
- NULL)) {
- case LZO_E_OK :
- case LZO_E_INPUT_NOT_CONSUMED :
- break;
- default :
- GRN_FREE(iw->value);
- iw->value = NULL;
+ lz4_value = (void *)((uint64_t *)packed_value + 1);
+ lz4_value_len = packed_value_len - sizeof(uint64_t);
+ if (LZ4_decompress_safe((const char *)(lz4_value),
+ (char *)(iw->uncompressed_value),
+ lz4_value_len,
+ original_value_len) < 0) {
+ GRN_FREE(iw->uncompressed_value);
+ iw->uncompressed_value = NULL;
*value_len = 0;
return NULL;
}
- *value_len = lout_len;
- return iw->value;
+ *value_len = original_value_len;
+ return iw->uncompressed_value;
}
-#endif /* GRN_WITH_LZO */
+#endif /* GRN_WITH_LZ4 */
void *
grn_ja_ref(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *value_len)
@@ -1273,11 +1273,11 @@ grn_ja_ref(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *value_
return grn_ja_ref_zlib(ctx, ja, id, iw, value_len);
}
#endif /* GRN_WITH_ZLIB */
-#ifdef GRN_WITH_LZO
- if (ja->header->flags & GRN_OBJ_COMPRESS_LZO) {
- return grn_ja_ref_lzo(ctx, ja, id, iw, value_len);
+#ifdef GRN_WITH_LZ4
+ if (ja->header->flags & GRN_OBJ_COMPRESS_LZ4) {
+ return grn_ja_ref_lz4(ctx, ja, id, iw, value_len);
}
-#endif /* GRN_WITH_LZO */
+#endif /* GRN_WITH_LZ4 */
return grn_ja_ref_raw(ctx, ja, id, iw, value_len);
}
@@ -1359,34 +1359,48 @@ grn_ja_put_zlib(grn_ctx *ctx, grn_ja *ja, grn_id id,
}
#endif /* GRN_WITH_ZLIB */
-#ifdef GRN_WITH_LZO
+#ifdef GRN_WITH_LZ4
inline static grn_rc
-grn_ja_put_lzo(grn_ctx *ctx, grn_ja *ja, grn_id id,
+grn_ja_put_lz4(grn_ctx *ctx, grn_ja *ja, grn_id id,
void *value, uint32_t value_len, int flags, uint64_t *cas)
{
grn_rc rc;
- void *lvalue, *lwork;
- lzo_uint lvalue_len = value_len + value_len / 16 + 64 + 3;
+ void *packed_value;
+ int packed_value_len;
+ char *lz4_value;
+ int lz4_value_len;
if (value_len == 0) {
return grn_ja_put_raw(ctx, ja, id, value, value_len, flags, cas);
}
- if (!(lvalue = GRN_MALLOC(lvalue_len + sizeof(uint64_t)))) { return GRN_NO_MEMORY_AVAILABLE; }
- if (!(lwork = GRN_MALLOC(LZO1X_1_MEM_COMPRESS))) { GRN_FREE(lvalue); return GRN_NO_MEMORY_AVAILABLE; }
- if (lzo1x_1_compress(value, value_len, (lzo_bytep)((uint64_t *)lvalue + 1), &lvalue_len, lwork) != LZO_E_OK) {
- GRN_FREE(lwork);
- GRN_FREE(lvalue);
- ERR(GRN_LZO_ERROR, "lzo1x_1_compress");
+ if (value_len > (uint32_t)LZ4_MAX_INPUT_SIZE) {
+ ERR(GRN_INVALID_ARGUMENT,
+ "[ja][lz4] too large value size: <%u>: max: <%d>",
+ value_len, LZ4_MAX_INPUT_SIZE);
+ return ctx->rc;
+ }
+
+ lz4_value_len = LZ4_compressBound(value_len);
+
+ if (!(packed_value = GRN_MALLOC(lz4_value_len + sizeof(uint64_t)))) {
+ return GRN_NO_MEMORY_AVAILABLE;
+ }
+ lz4_value = (char *)((uint64_t *)packed_value + 1);
+ lz4_value_len = LZ4_compress((const char*)value, lz4_value, value_len);
+
+ if (lz4_value_len <= 0) {
+ GRN_FREE(packed_value);
+ ERR(GRN_LZ4_ERROR, "LZ4_compress");
return ctx->rc;
}
- GRN_FREE(lwork);
- *(uint64_t *)lvalue = value_len;
- rc = grn_ja_put_raw(ctx, ja, id, lvalue, lvalue_len + sizeof(uint64_t), flags, cas);
- GRN_FREE(lvalue);
+ *(uint64_t *)packed_value = value_len;
+ packed_value_len = lz4_value_len + sizeof(uint64_t);
+ rc = grn_ja_put_raw(ctx, ja, id, packed_value, packed_value_len, flags, cas);
+ GRN_FREE(packed_value);
return rc;
}
-#endif /* GRN_WITH_LZO */
+#endif /* GRN_WITH_LZ4 */
grn_rc
grn_ja_put(grn_ctx *ctx, grn_ja *ja, grn_id id, void *value, uint32_t value_len,
@@ -1397,11 +1411,11 @@ grn_ja_put(grn_ctx *ctx, grn_ja *ja, grn_id id, void *value, uint32_t value_len,
return grn_ja_put_zlib(ctx, ja, id, value, value_len, flags, cas);
}
#endif /* GRN_WITH_ZLIB */
-#ifdef GRN_WITH_LZO
- if (ja->header->flags & GRN_OBJ_COMPRESS_LZO) {
- return grn_ja_put_lzo(ctx, ja, id, value, value_len, flags, cas);
+#ifdef GRN_WITH_LZ4
+ if (ja->header->flags & GRN_OBJ_COMPRESS_LZ4) {
+ return grn_ja_put_lz4(ctx, ja, id, value, value_len, flags, cas);
}
-#endif /* GRN_WITH_LZO */
+#endif /* GRN_WITH_LZ4 */
return grn_ja_put_raw(ctx, ja, id, value, value_len, flags, cas);
}
diff --git a/storage/mroonga/vendor/groonga/lib/str.c b/storage/mroonga/vendor/groonga/lib/str.c
index 29e532a8021..f91b89c96c0 100644
--- a/storage/mroonga/vendor/groonga/lib/str.c
+++ b/storage/mroonga/vendor/groonga/lib/str.c
@@ -1,5 +1,5 @@
/* -*- c-basic-offset: 2 -*- */
-/* Copyright(C) 2009-2013 Brazil
+/* Copyright(C) 2009-2015 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -14,13 +14,13 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "groonga_in.h"
+#include "grn.h"
#include <limits.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
-#include "db.h"
-#include "str.h"
+#include "grn_db.h"
+#include "grn_str.h"
#ifndef _ISOC99_SOURCE
#define _ISOC99_SOURCE
@@ -2441,14 +2441,20 @@ grn_text_time2rfc1123(grn_ctx *ctx, grn_obj *bulk, int sec)
{
time_t tsec;
struct tm *t;
-#ifdef HAVE_GMTIME_R
+#ifdef HAVE__GMTIME64_S
+ struct tm tm;
+ tsec = (time_t)sec;
+ t = (gmtime_s(&tm, &tsec) == 0) ? &tm : NULL;
+#else /* HAVE__GMTIME64_S */
+# ifdef HAVE_GMTIME_R
struct tm tm;
tsec = (time_t)sec;
t = gmtime_r(&tsec, &tm);
-#else /* HAVE_GMTIME_R */
+# else /* HAVE_GMTIME_R */
tsec = (time_t)sec;
t = gmtime(&tsec);
-#endif /* HAVE_GMTIME_R */
+# endif /* HAVE_GMTIME_R */
+#endif /* HAVE__GMTIME64_S */
if (t) {
GRN_TEXT_SET(ctx, bulk, weekdays[t->tm_wday], 3);
GRN_TEXT_PUTS(ctx, bulk, ", ");
@@ -2576,10 +2582,10 @@ grn_text_atoj(grn_ctx *ctx, grn_obj *bulk, grn_obj *obj, grn_id id)
buf.header.domain = GRN_DB_INT32; /* fix me */
break;
case GRN_ACCESSOR_GET_SCORE :
- grn_obj_get_value(ctx, a->obj, id, &buf);
{
grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs);
- GRN_INT32_PUT(ctx, &buf, ri->score);
+ int32_t int32_score = ri->score;
+ GRN_INT32_PUT(ctx, &buf, int32_score);
}
buf.header.domain = GRN_DB_INT32;
break;
@@ -2941,6 +2947,8 @@ grn_text_otoj(grn_ctx *ctx, grn_obj *bulk, grn_obj *obj, grn_obj_format *format)
}
}
GRN_TEXT_PUTC(ctx, bulk, ']');
+ GRN_OBJ_FIN(ctx, &value);
+ GRN_OBJ_FIN(ctx, &weight);
}
break;
case GRN_PVECTOR :
diff --git a/storage/mroonga/vendor/groonga/lib/string.c b/storage/mroonga/vendor/groonga/lib/string.c
index f0fcf561b5e..132d51257ac 100644
--- a/storage/mroonga/vendor/groonga/lib/string.c
+++ b/storage/mroonga/vendor/groonga/lib/string.c
@@ -16,12 +16,12 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "groonga_in.h"
+#include "grn.h"
#include <string.h>
-#include "string_in.h"
-#include "normalizer_in.h"
-#include "str.h"
-#include "util.h"
+#include "grn_string.h"
+#include "grn_normalizer.h"
+#include "grn_str.h"
+#include "grn_util.h"
#include <groonga/tokenizer.h>
diff --git a/storage/mroonga/vendor/groonga/lib/token_cursor.c b/storage/mroonga/vendor/groonga/lib/token_cursor.c
new file mode 100644
index 00000000000..d3e2e2d8523
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/lib/token_cursor.c
@@ -0,0 +1,357 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2009-2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#include "grn_token_cursor.h"
+#include "grn_string.h"
+#include "grn_pat.h"
+#include "grn_dat.h"
+
+static void
+grn_token_cursor_open_initialize_token_filters(grn_ctx *ctx,
+ grn_token_cursor *token_cursor)
+{
+ grn_obj *token_filters = token_cursor->token_filters;
+ unsigned int i, n_token_filters;
+
+ if (token_filters) {
+ n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *);
+ } else {
+ n_token_filters = 0;
+ }
+
+ for (i = 0; i < n_token_filters; i++) {
+ grn_obj *token_filter_object = GRN_PTR_VALUE_AT(token_filters, i);
+ grn_proc *token_filter = (grn_proc *)token_filter_object;
+
+ token_filter->user_data =
+ token_filter->callbacks.token_filter.init(ctx,
+ token_cursor->table,
+ token_cursor->mode);
+ }
+}
+
+grn_token_cursor *
+grn_token_cursor_open(grn_ctx *ctx, grn_obj *table,
+ const char *str, size_t str_len,
+ grn_tokenize_mode mode, unsigned int flags)
+{
+ grn_token_cursor *token_cursor;
+ grn_encoding encoding;
+ grn_obj *tokenizer;
+ grn_obj *normalizer;
+ grn_obj *token_filters;
+ grn_obj_flags table_flags;
+ if (grn_table_get_info(ctx, table, &table_flags, &encoding, &tokenizer,
+ &normalizer, &token_filters)) {
+ return NULL;
+ }
+ if (!(token_cursor = GRN_MALLOC(sizeof(grn_token_cursor)))) { return NULL; }
+ token_cursor->table = table;
+ token_cursor->mode = mode;
+ token_cursor->encoding = encoding;
+ token_cursor->tokenizer = tokenizer;
+ token_cursor->token_filters = token_filters;
+ token_cursor->orig = (const unsigned char *)str;
+ token_cursor->orig_blen = str_len;
+ token_cursor->curr = NULL;
+ token_cursor->nstr = NULL;
+ token_cursor->curr_size = 0;
+ token_cursor->pos = -1;
+ token_cursor->status = GRN_TOKEN_CURSOR_DOING;
+ token_cursor->force_prefix = GRN_FALSE;
+ if (tokenizer) {
+ grn_obj str_, flags_, mode_;
+ GRN_TEXT_INIT(&str_, GRN_OBJ_DO_SHALLOW_COPY);
+ GRN_TEXT_SET_REF(&str_, str, str_len);
+ GRN_UINT32_INIT(&flags_, 0);
+ GRN_UINT32_SET(ctx, &flags_, flags);
+ GRN_UINT32_INIT(&mode_, 0);
+ GRN_UINT32_SET(ctx, &mode_, mode);
+ token_cursor->pctx.caller = NULL;
+ token_cursor->pctx.user_data.ptr = NULL;
+ token_cursor->pctx.proc = (grn_proc *)tokenizer;
+ token_cursor->pctx.hooks = NULL;
+ token_cursor->pctx.currh = NULL;
+ token_cursor->pctx.phase = PROC_INIT;
+ grn_ctx_push(ctx, &mode_);
+ grn_ctx_push(ctx, &str_);
+ grn_ctx_push(ctx, &flags_);
+ ((grn_proc *)tokenizer)->funcs[PROC_INIT](ctx, 1, &table, &token_cursor->pctx.user_data);
+ grn_obj_close(ctx, &flags_);
+ grn_obj_close(ctx, &str_);
+ grn_obj_close(ctx, &mode_);
+ } else {
+ int nflags = 0;
+ token_cursor->nstr = grn_string_open_(ctx, str, str_len,
+ normalizer,
+ nflags,
+ token_cursor->encoding);
+ if (token_cursor->nstr) {
+ const char *normalized;
+ grn_string_get_normalized(ctx, token_cursor->nstr,
+ &normalized, &(token_cursor->curr_size), NULL);
+ token_cursor->curr = (const unsigned char *)normalized;
+ } else {
+ ERR(GRN_TOKENIZER_ERROR,
+ "[token-cursor][open] failed to grn_string_open()");
+ }
+ }
+
+ grn_token_cursor_open_initialize_token_filters(ctx, token_cursor);
+
+ if (ctx->rc) {
+ grn_token_cursor_close(ctx, token_cursor);
+ token_cursor = NULL;
+ }
+ return token_cursor;
+}
+
+static int
+grn_token_cursor_next_apply_token_filters(grn_ctx *ctx,
+ grn_token_cursor *token_cursor,
+ grn_obj *current_token_data,
+ grn_obj *status)
+{
+ grn_obj *token_filters = token_cursor->token_filters;
+ unsigned int i, n_token_filters;
+ grn_token current_token;
+ grn_token next_token;
+
+ if (token_filters) {
+ n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *);
+ } else {
+ n_token_filters = 0;
+ }
+
+ GRN_TEXT_INIT(&(current_token.data), GRN_OBJ_DO_SHALLOW_COPY);
+ GRN_TEXT_SET(ctx, &(current_token.data),
+ GRN_TEXT_VALUE(current_token_data),
+ GRN_TEXT_LEN(current_token_data));
+ current_token.status = GRN_INT32_VALUE(status);
+ GRN_TEXT_INIT(&(next_token.data), GRN_OBJ_DO_SHALLOW_COPY);
+ GRN_TEXT_SET(ctx, &(next_token.data),
+ GRN_TEXT_VALUE(&(current_token.data)),
+ GRN_TEXT_LEN(&(current_token.data)));
+ next_token.status = current_token.status;
+
+ for (i = 0; i < n_token_filters; i++) {
+ grn_obj *token_filter_object = GRN_PTR_VALUE_AT(token_filters, i);
+ grn_proc *token_filter = (grn_proc *)token_filter_object;
+
+#define SKIP_FLAGS\
+ (GRN_TOKEN_SKIP |\
+ GRN_TOKEN_SKIP_WITH_POSITION)
+ if (current_token.status & SKIP_FLAGS) {
+ break;
+ }
+#undef SKIP_FLAGS
+
+ token_filter->callbacks.token_filter.filter(ctx,
+ &current_token,
+ &next_token,
+ token_filter->user_data);
+ GRN_TEXT_SET(ctx, &(current_token.data),
+ GRN_TEXT_VALUE(&(next_token.data)),
+ GRN_TEXT_LEN(&(next_token.data)));
+ current_token.status = next_token.status;
+ }
+
+ token_cursor->curr =
+ (const unsigned char *)GRN_TEXT_VALUE(&(current_token.data));
+ token_cursor->curr_size = GRN_TEXT_LEN(&(current_token.data));
+
+ return current_token.status;
+}
+
+grn_id
+grn_token_cursor_next(grn_ctx *ctx, grn_token_cursor *token_cursor)
+{
+ int status;
+ grn_id tid = GRN_ID_NIL;
+ grn_obj *table = token_cursor->table;
+ grn_obj *tokenizer = token_cursor->tokenizer;
+ while (token_cursor->status != GRN_TOKEN_CURSOR_DONE) {
+ if (tokenizer) {
+ grn_obj *curr_, *stat_;
+ ((grn_proc *)tokenizer)->funcs[PROC_NEXT](ctx, 1, &table, &token_cursor->pctx.user_data);
+ stat_ = grn_ctx_pop(ctx);
+ curr_ = grn_ctx_pop(ctx);
+ status = grn_token_cursor_next_apply_token_filters(ctx, token_cursor,
+ curr_, stat_);
+ token_cursor->status =
+ ((status & GRN_TOKEN_LAST) ||
+ (token_cursor->mode == GRN_TOKENIZE_GET &&
+ (status & GRN_TOKEN_REACH_END)))
+ ? GRN_TOKEN_CURSOR_DONE : GRN_TOKEN_CURSOR_DOING;
+ token_cursor->force_prefix = GRN_FALSE;
+#define SKIP_FLAGS \
+ (GRN_TOKEN_SKIP | GRN_TOKEN_SKIP_WITH_POSITION)
+ if (status & SKIP_FLAGS) {
+ if (status & GRN_TOKEN_SKIP) {
+ token_cursor->pos++;
+ }
+ if (token_cursor->status == GRN_TOKEN_CURSOR_DONE && tid == GRN_ID_NIL) {
+ token_cursor->status = GRN_TOKEN_CURSOR_DONE_SKIP;
+ break;
+ } else {
+ continue;
+ }
+ }
+#undef SKIP_FLAGS
+ if (status & GRN_TOKEN_FORCE_PREFIX) {
+ token_cursor->force_prefix = GRN_TRUE;
+ }
+ if (token_cursor->curr_size == 0) {
+ char tokenizer_name[GRN_TABLE_MAX_KEY_SIZE];
+ int tokenizer_name_length;
+ tokenizer_name_length =
+ grn_obj_name(ctx, token_cursor->tokenizer,
+ tokenizer_name, GRN_TABLE_MAX_KEY_SIZE);
+ GRN_LOG(ctx, GRN_WARN,
+ "[token_next] ignore an empty token: <%.*s>: <%.*s>",
+ tokenizer_name_length, tokenizer_name,
+ token_cursor->orig_blen, token_cursor->orig);
+ continue;
+ }
+ if (token_cursor->curr_size > GRN_TABLE_MAX_KEY_SIZE) {
+ GRN_LOG(ctx, GRN_WARN,
+ "[token_next] ignore too long token. "
+ "Token must be less than or equal to %d: <%d>(<%.*s>)",
+ GRN_TABLE_MAX_KEY_SIZE,
+ token_cursor->curr_size,
+ token_cursor->curr_size, token_cursor->curr);
+ continue;
+ }
+ if (status & GRN_TOKEN_UNMATURED) {
+ if (status & GRN_TOKEN_OVERLAP) {
+ if (token_cursor->mode == GRN_TOKENIZE_GET) {
+ token_cursor->pos++;
+ continue;
+ }
+ } else {
+ if (status & GRN_TOKEN_LAST) {
+ token_cursor->force_prefix = GRN_TRUE;
+ }
+ }
+ }
+ } else {
+ token_cursor->status = GRN_TOKEN_CURSOR_DONE;
+ }
+ if (token_cursor->mode == GRN_TOKENIZE_ADD) {
+ switch (table->header.type) {
+ case GRN_TABLE_PAT_KEY :
+ if (grn_io_lock(ctx, ((grn_pat *)table)->io, grn_lock_timeout)) {
+ tid = GRN_ID_NIL;
+ } else {
+ tid = grn_pat_add(ctx, (grn_pat *)table, token_cursor->curr, token_cursor->curr_size,
+ NULL, NULL);
+ grn_io_unlock(((grn_pat *)table)->io);
+ }
+ break;
+ case GRN_TABLE_DAT_KEY :
+ if (grn_io_lock(ctx, ((grn_dat *)table)->io, grn_lock_timeout)) {
+ tid = GRN_ID_NIL;
+ } else {
+ tid = grn_dat_add(ctx, (grn_dat *)table, token_cursor->curr, token_cursor->curr_size,
+ NULL, NULL);
+ grn_io_unlock(((grn_dat *)table)->io);
+ }
+ break;
+ case GRN_TABLE_HASH_KEY :
+ if (grn_io_lock(ctx, ((grn_hash *)table)->io, grn_lock_timeout)) {
+ tid = GRN_ID_NIL;
+ } else {
+ tid = grn_hash_add(ctx, (grn_hash *)table, token_cursor->curr, token_cursor->curr_size,
+ NULL, NULL);
+ grn_io_unlock(((grn_hash *)table)->io);
+ }
+ break;
+ case GRN_TABLE_NO_KEY :
+ if (token_cursor->curr_size == sizeof(grn_id)) {
+ tid = *((grn_id *)token_cursor->curr);
+ } else {
+ tid = GRN_ID_NIL;
+ }
+ break;
+ }
+ } else {
+ switch (table->header.type) {
+ case GRN_TABLE_PAT_KEY :
+ tid = grn_pat_get(ctx, (grn_pat *)table, token_cursor->curr, token_cursor->curr_size, NULL);
+ break;
+ case GRN_TABLE_DAT_KEY :
+ tid = grn_dat_get(ctx, (grn_dat *)table, token_cursor->curr, token_cursor->curr_size, NULL);
+ break;
+ case GRN_TABLE_HASH_KEY :
+ tid = grn_hash_get(ctx, (grn_hash *)table, token_cursor->curr, token_cursor->curr_size, NULL);
+ break;
+ case GRN_TABLE_NO_KEY :
+ if (token_cursor->curr_size == sizeof(grn_id)) {
+ tid = *((grn_id *)token_cursor->curr);
+ } else {
+ tid = GRN_ID_NIL;
+ }
+ break;
+ }
+ }
+ if (tid == GRN_ID_NIL && token_cursor->status != GRN_TOKEN_CURSOR_DONE) {
+ token_cursor->status = GRN_TOKEN_CURSOR_NOT_FOUND;
+ }
+ token_cursor->pos++;
+ break;
+ }
+ return tid;
+}
+
+static void
+grn_token_cursor_close_token_filters(grn_ctx *ctx,
+ grn_token_cursor *token_cursor)
+{
+ grn_obj *token_filters = token_cursor->token_filters;
+ unsigned int i, n_token_filters;
+
+ if (token_filters) {
+ n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *);
+ } else {
+ n_token_filters = 0;
+ }
+ for (i = 0; i < n_token_filters; i++) {
+ grn_obj *token_filter_object = GRN_PTR_VALUE_AT(token_filters, i);
+ grn_proc *token_filter = (grn_proc *)token_filter_object;
+
+ token_filter->callbacks.token_filter.fin(ctx, token_filter->user_data);
+ }
+}
+
+grn_rc
+grn_token_cursor_close(grn_ctx *ctx, grn_token_cursor *token_cursor)
+{
+ if (token_cursor) {
+ if (token_cursor->tokenizer) {
+ ((grn_proc *)token_cursor->tokenizer)->funcs[PROC_FIN](ctx, 1, &token_cursor->table,
+ &token_cursor->pctx.user_data);
+ }
+ grn_token_cursor_close_token_filters(ctx, token_cursor);
+ if (token_cursor->nstr) {
+ grn_obj_close(ctx, token_cursor->nstr);
+ }
+ GRN_FREE(token_cursor);
+ return GRN_SUCCESS;
+ } else {
+ return GRN_INVALID_ARGUMENT;
+ }
+}
diff --git a/storage/mroonga/vendor/groonga/lib/token_filter.c b/storage/mroonga/vendor/groonga/lib/token_filter.c
index 910bb9a5715..c57650c2b55 100644
--- a/storage/mroonga/vendor/groonga/lib/token_filter.c
+++ b/storage/mroonga/vendor/groonga/lib/token_filter.c
@@ -18,8 +18,8 @@
#include <string.h>
-#include "groonga_in.h"
-#include "db.h"
+#include "grn.h"
+#include "grn_db.h"
#include <groonga/token_filter.h>
grn_rc
diff --git a/storage/mroonga/vendor/groonga/lib/tokenizer.c b/storage/mroonga/vendor/groonga/lib/tokenizer.c
index ac4628ba5de..ef9eb5bf7b5 100644
--- a/storage/mroonga/vendor/groonga/lib/tokenizer.c
+++ b/storage/mroonga/vendor/groonga/lib/tokenizer.c
@@ -15,18 +15,16 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "groonga_in.h"
-#include "groonga/tokenizer.h"
+#include "grn.h"
+#include <groonga/tokenizer.h>
-#include <stdarg.h>
-#include <stdio.h>
#include <string.h>
-#include "ctx.h"
-#include "db.h"
-#include "str.h"
-#include "string_in.h"
-#include "token.h"
+#include "grn_ctx.h"
+#include "grn_db.h"
+#include "grn_str.h"
+#include "grn_string.h"
+#include "grn_token_cursor.h"
/*
Just for backward compatibility. See grn_plugin_charlen() instead.
@@ -102,7 +100,7 @@ grn_tokenizer_query_open(grn_ctx *ctx, int num_args, grn_obj **args,
{
grn_obj *flags = grn_ctx_pop(ctx);
grn_obj *query_str = grn_ctx_pop(ctx);
- grn_obj *token_mode = grn_ctx_pop(ctx);
+ grn_obj *tokenize_mode = grn_ctx_pop(ctx);
if (query_str == NULL) {
GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, "missing argument");
@@ -127,11 +125,12 @@ grn_tokenizer_query_open(grn_ctx *ctx, int num_args, grn_obj **args,
} else {
query->flags = 0;
}
- if (token_mode) {
- query->token_mode = GRN_UINT32_VALUE(token_mode);
+ if (tokenize_mode) {
+ query->tokenize_mode = GRN_UINT32_VALUE(tokenize_mode);
} else {
- query->token_mode = GRN_TOKEN_ADD;
+ query->tokenize_mode = GRN_TOKENIZE_ADD;
}
+ query->token_mode = query->tokenize_mode;
{
grn_obj * const table = args[0];
@@ -176,7 +175,7 @@ grn_tokenizer_query_open(grn_ctx *ctx, int num_args, grn_obj **args,
}
query->encoding = table_encoding;
- if (query->flags & GRN_TOKEN_ENABLE_TOKENIZED_DELIMITER) {
+ if (query->flags & GRN_TOKEN_CURSOR_ENABLE_TOKENIZED_DELIMITER) {
const char *normalized_string;
unsigned int normalized_string_length;
@@ -241,7 +240,7 @@ grn_tokenizer_token_fin(grn_ctx *ctx, grn_tokenizer_token *token)
void
grn_tokenizer_token_push(grn_ctx *ctx, grn_tokenizer_token *token,
const char *str_ptr, unsigned int str_length,
- grn_tokenizer_status status)
+ grn_token_status status)
{
GRN_TEXT_SET_REF(&token->str, str_ptr, str_length);
GRN_UINT32_SET(ctx, &token->status, status);
@@ -262,7 +261,7 @@ grn_tokenizer_tokenized_delimiter_next(grn_ctx *ctx,
const char *end = str_ptr + str_length;
const char *next_start = NULL;
unsigned int token_length;
- grn_tokenizer_status status;
+ grn_token_status status;
for (current = start; current < end; current += char_length) {
char_length = grn_charlen_(ctx, current, end, encoding);
@@ -349,13 +348,13 @@ exit:
GRN_API_RETURN(ctx->rc);
}
-grn_tokenizer_status
+grn_token_status
grn_token_get_status(grn_ctx *ctx, grn_token *token)
{
GRN_API_ENTER;
if (!token) {
ERR(GRN_INVALID_ARGUMENT, "token must not be NULL");
- GRN_API_RETURN(GRN_TOKENIZER_TOKEN_CONTINUE);
+ GRN_API_RETURN(GRN_TOKEN_CONTINUE);
}
GRN_API_RETURN(token->status);
}
@@ -363,7 +362,7 @@ grn_token_get_status(grn_ctx *ctx, grn_token *token)
grn_rc
grn_token_set_status(grn_ctx *ctx,
grn_token *token,
- grn_tokenizer_status status)
+ grn_token_status status)
{
GRN_API_ENTER;
if (!token) {
diff --git a/storage/mroonga/vendor/groonga/lib/token.c b/storage/mroonga/vendor/groonga/lib/tokenizers.c
index 00b3de2ebdd..3f6df15a690 100644
--- a/storage/mroonga/vendor/groonga/lib/token.c
+++ b/storage/mroonga/vendor/groonga/lib/tokenizers.c
@@ -15,19 +15,13 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "groonga_in.h"
#include <string.h>
-#include <ctype.h>
-#include "ctx_impl.h"
-#include "token.h"
-#include "pat.h"
-#include "dat.h"
-#include "hash.h"
-#include "string_in.h"
-#include "plugin_in.h"
+#include "grn_token_cursor.h"
+#include "grn_string.h"
+#include "grn_plugin.h"
#include <groonga/tokenizer.h>
-grn_obj *grn_token_uvector = NULL;
+grn_obj *grn_tokenizer_uvector = NULL;
typedef struct {
grn_tokenizer_token token;
@@ -76,13 +70,13 @@ uvector_next(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
if (tokenizer->tail < p) {
grn_tokenizer_token_push(ctx, &(tokenizer->token),
(const char *)tokenizer->curr, 0,
- GRN_TOKENIZER_TOKEN_LAST);
+ GRN_TOKEN_LAST);
} else {
- grn_tokenizer_status status;
+ grn_token_status status;
if (tokenizer->tail == p) {
- status = GRN_TOKENIZER_TOKEN_LAST;
+ status = GRN_TOKEN_LAST;
} else {
- status = GRN_TOKENIZER_TOKEN_CONTINUE;
+ status = GRN_TOKEN_CONTINUE;
}
grn_tokenizer_token_push(ctx, &(tokenizer->token),
(const char *)tokenizer->curr, tokenizer->unit,
@@ -177,7 +171,7 @@ delimited_next(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data
size_t cl;
const unsigned char *p = tokenizer->next, *r;
const unsigned char *e = tokenizer->end;
- grn_tokenizer_status status;
+ grn_token_status status;
for (r = p; r < e; r += cl) {
if (!(cl = grn_charlen_(ctx, (char *)r, (char *)e,
tokenizer->query->encoding))) {
@@ -200,9 +194,9 @@ delimited_next(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data
}
}
if (r == e) {
- status = GRN_TOKENIZER_LAST;
+ status = GRN_TOKEN_LAST;
} else {
- status = GRN_TOKENIZER_CONTINUE;
+ status = GRN_TOKEN_CONTINUE;
}
grn_tokenizer_token_push(ctx,
&(tokenizer->token),
@@ -356,7 +350,8 @@ ngram_next(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
size_t cl;
grn_ngram_tokenizer *tokenizer = user_data->ptr;
const unsigned char *p = tokenizer->next, *r = p, *e = tokenizer->end;
- int32_t len = 0, pos = tokenizer->pos + tokenizer->skip, status = 0;
+ int32_t len = 0, pos = tokenizer->pos + tokenizer->skip;
+ grn_token_status status = 0;
const uint_least8_t *cp = tokenizer->ctypes ? tokenizer->ctypes + pos : NULL;
if (cp && tokenizer->uni_alpha && GRN_STR_CTYPE(*cp) == GRN_CHAR_ALPHA) {
while ((cl = grn_charlen_(ctx, (char *)r, (char *)e,
@@ -398,7 +393,7 @@ ngram_next(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
// todo : grn_pat_lcp_search
if ((tid = grn_sym_common_prefix_search(sym, p))) {
if (!(key = _grn_sym_key(sym, tid))) {
- tokenizer->status = GRN_TOKEN_NOT_FOUND;
+ tokenizer->status = GRN_TOKEN_CURSOR_NOT_FOUND;
return NULL;
}
len = grn_str_len(key, tokenizer->query->encoding, NULL);
@@ -408,7 +403,7 @@ ngram_next(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
if (r != p && pos + len - 1 <= tokenizer->tail) { continue; }
p += strlen(key);
if (!*p && tokenizer->mode == GRN_TOKEN_GET) {
- tokenizer->status = GRN_TOKEN_DONE;
+ tokenizer->status = GRN_TOKEN_CURSOR_DONE;
}
}
#endif /* PRE_DEFINED_UNSPLIT_WORDS */
@@ -433,10 +428,10 @@ ngram_next(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
r += cl;
}
if (tokenizer->overlap) {
- status |= GRN_TOKENIZER_TOKEN_OVERLAP;
+ status |= GRN_TOKEN_OVERLAP;
}
if (len < tokenizer->ngram_unit) {
- status |= GRN_TOKENIZER_TOKEN_UNMATURED;
+ status |= GRN_TOKEN_UNMATURED;
}
tokenizer->overlap = (len > 1) ? 1 : 0;
}
@@ -446,11 +441,11 @@ ngram_next(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
tokenizer->tail = pos + len - 1;
if (p == r || tokenizer->next == e) {
tokenizer->skip = 0;
- status |= GRN_TOKENIZER_TOKEN_LAST;
+ status |= GRN_TOKEN_LAST;
} else {
tokenizer->skip = tokenizer->overlap ? 1 : len;
}
- if (r == e) { status |= GRN_TOKENIZER_TOKEN_REACH_END; }
+ if (r == e) { status |= GRN_TOKEN_REACH_END; }
grn_tokenizer_token_push(ctx,
&(tokenizer->token),
(const char *)p,
@@ -475,354 +470,26 @@ ngram_fin(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
/* external */
grn_rc
-grn_token_init(void)
+grn_tokenizers_init(void)
{
- static grn_proc _grn_token_uvector;
- _grn_token_uvector.obj.db = NULL;
- _grn_token_uvector.obj.id = GRN_ID_NIL;
- _grn_token_uvector.obj.header.domain = GRN_ID_NIL;
- _grn_token_uvector.obj.range = GRN_ID_NIL;
- _grn_token_uvector.funcs[PROC_INIT] = uvector_init;
- _grn_token_uvector.funcs[PROC_NEXT] = uvector_next;
- _grn_token_uvector.funcs[PROC_FIN] = uvector_fin;
- grn_token_uvector = (grn_obj *)&_grn_token_uvector;
+ static grn_proc _grn_tokenizer_uvector;
+ _grn_tokenizer_uvector.obj.db = NULL;
+ _grn_tokenizer_uvector.obj.id = GRN_ID_NIL;
+ _grn_tokenizer_uvector.obj.header.domain = GRN_ID_NIL;
+ _grn_tokenizer_uvector.obj.range = GRN_ID_NIL;
+ _grn_tokenizer_uvector.funcs[PROC_INIT] = uvector_init;
+ _grn_tokenizer_uvector.funcs[PROC_NEXT] = uvector_next;
+ _grn_tokenizer_uvector.funcs[PROC_FIN] = uvector_fin;
+ grn_tokenizer_uvector = (grn_obj *)&_grn_tokenizer_uvector;
return GRN_SUCCESS;
}
grn_rc
-grn_token_fin(void)
+grn_tokenizers_fin(void)
{
return GRN_SUCCESS;
}
-static void
-grn_token_cursor_open_initialize_token_filters(grn_ctx *ctx,
- grn_token_cursor *token_cursor)
-{
- grn_obj *token_filters = token_cursor->token_filters;
- unsigned int i, n_token_filters;
-
- if (token_filters) {
- n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *);
- } else {
- n_token_filters = 0;
- }
-
- for (i = 0; i < n_token_filters; i++) {
- grn_obj *token_filter_object = GRN_PTR_VALUE_AT(token_filters, i);
- grn_proc *token_filter = (grn_proc *)token_filter_object;
-
- token_filter->user_data =
- token_filter->callbacks.token_filter.init(ctx,
- token_cursor->table,
- token_cursor->mode);
- }
-}
-
-grn_token_cursor *
-grn_token_cursor_open(grn_ctx *ctx, grn_obj *table,
- const char *str, size_t str_len,
- grn_token_mode mode, unsigned int flags)
-{
- grn_token_cursor *token_cursor;
- grn_encoding encoding;
- grn_obj *tokenizer;
- grn_obj *normalizer;
- grn_obj *token_filters;
- grn_obj_flags table_flags;
- if (grn_table_get_info(ctx, table, &table_flags, &encoding, &tokenizer,
- &normalizer, &token_filters)) {
- return NULL;
- }
- if (!(token_cursor = GRN_MALLOC(sizeof(grn_token_cursor)))) { return NULL; }
- token_cursor->table = table;
- token_cursor->mode = mode;
- token_cursor->encoding = encoding;
- token_cursor->tokenizer = tokenizer;
- token_cursor->token_filters = token_filters;
- token_cursor->orig = (const unsigned char *)str;
- token_cursor->orig_blen = str_len;
- token_cursor->curr = NULL;
- token_cursor->nstr = NULL;
- token_cursor->curr_size = 0;
- token_cursor->pos = -1;
- token_cursor->status = GRN_TOKEN_DOING;
- token_cursor->force_prefix = 0;
- if (tokenizer) {
- grn_obj str_, flags_, mode_;
- GRN_TEXT_INIT(&str_, GRN_OBJ_DO_SHALLOW_COPY);
- GRN_TEXT_SET_REF(&str_, str, str_len);
- GRN_UINT32_INIT(&flags_, 0);
- GRN_UINT32_SET(ctx, &flags_, flags);
- GRN_UINT32_INIT(&mode_, 0);
- GRN_UINT32_SET(ctx, &mode_, mode);
- token_cursor->pctx.caller = NULL;
- token_cursor->pctx.user_data.ptr = NULL;
- token_cursor->pctx.proc = (grn_proc *)tokenizer;
- token_cursor->pctx.hooks = NULL;
- token_cursor->pctx.currh = NULL;
- token_cursor->pctx.phase = PROC_INIT;
- grn_ctx_push(ctx, &mode_);
- grn_ctx_push(ctx, &str_);
- grn_ctx_push(ctx, &flags_);
- ((grn_proc *)tokenizer)->funcs[PROC_INIT](ctx, 1, &table, &token_cursor->pctx.user_data);
- grn_obj_close(ctx, &flags_);
- grn_obj_close(ctx, &str_);
- grn_obj_close(ctx, &mode_);
- } else {
- int nflags = 0;
- token_cursor->nstr = grn_string_open_(ctx, str, str_len,
- normalizer,
- nflags,
- token_cursor->encoding);
- if (token_cursor->nstr) {
- const char *normalized;
- grn_string_get_normalized(ctx, token_cursor->nstr,
- &normalized, &(token_cursor->curr_size), NULL);
- token_cursor->curr = (const unsigned char *)normalized;
- } else {
- ERR(GRN_TOKENIZER_ERROR,
- "[token-cursor][open] failed to grn_string_open()");
- }
- }
-
- grn_token_cursor_open_initialize_token_filters(ctx, token_cursor);
-
- if (ctx->rc) {
- grn_token_cursor_close(ctx, token_cursor);
- token_cursor = NULL;
- }
- return token_cursor;
-}
-
-static int
-grn_token_cursor_next_apply_token_filters(grn_ctx *ctx,
- grn_token_cursor *token_cursor,
- grn_obj *current_token_data,
- grn_obj *status)
-{
- grn_obj *token_filters = token_cursor->token_filters;
- unsigned int i, n_token_filters;
- grn_token current_token;
- grn_token next_token;
-
- if (token_filters) {
- n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *);
- } else {
- n_token_filters = 0;
- }
-
- GRN_TEXT_INIT(&(current_token.data), GRN_OBJ_DO_SHALLOW_COPY);
- GRN_TEXT_SET(ctx, &(current_token.data),
- GRN_TEXT_VALUE(current_token_data),
- GRN_TEXT_LEN(current_token_data));
- current_token.status = GRN_INT32_VALUE(status);
- GRN_TEXT_INIT(&(next_token.data), GRN_OBJ_DO_SHALLOW_COPY);
- GRN_TEXT_SET(ctx, &(next_token.data),
- GRN_TEXT_VALUE(&(current_token.data)),
- GRN_TEXT_LEN(&(current_token.data)));
- next_token.status = current_token.status;
-
- for (i = 0; i < n_token_filters; i++) {
- grn_obj *token_filter_object = GRN_PTR_VALUE_AT(token_filters, i);
- grn_proc *token_filter = (grn_proc *)token_filter_object;
-
-#define SKIP_FLAGS\
- (GRN_TOKENIZER_TOKEN_SKIP |\
- GRN_TOKENIZER_TOKEN_SKIP_WITH_POSITION)
- if (current_token.status & SKIP_FLAGS) {
- break;
- }
-#undef SKIP_FLAGS
-
- token_filter->callbacks.token_filter.filter(ctx,
- &current_token,
- &next_token,
- token_filter->user_data);
- GRN_TEXT_SET(ctx, &(current_token.data),
- GRN_TEXT_VALUE(&(next_token.data)),
- GRN_TEXT_LEN(&(next_token.data)));
- current_token.status = next_token.status;
- }
-
- token_cursor->curr =
- (const unsigned char *)GRN_TEXT_VALUE(&(current_token.data));
- token_cursor->curr_size = GRN_TEXT_LEN(&(current_token.data));
-
- return current_token.status;
-}
-
-grn_id
-grn_token_cursor_next(grn_ctx *ctx, grn_token_cursor *token_cursor)
-{
- int status;
- grn_id tid = GRN_ID_NIL;
- grn_obj *table = token_cursor->table;
- grn_obj *tokenizer = token_cursor->tokenizer;
- while (token_cursor->status != GRN_TOKEN_DONE) {
- if (tokenizer) {
- grn_obj *curr_, *stat_;
- ((grn_proc *)tokenizer)->funcs[PROC_NEXT](ctx, 1, &table, &token_cursor->pctx.user_data);
- stat_ = grn_ctx_pop(ctx);
- curr_ = grn_ctx_pop(ctx);
- status = grn_token_cursor_next_apply_token_filters(ctx, token_cursor,
- curr_, stat_);
- token_cursor->status =
- ((status & GRN_TOKENIZER_TOKEN_LAST) ||
- (token_cursor->mode == GRN_TOKEN_GET &&
- (status & GRN_TOKENIZER_TOKEN_REACH_END)))
- ? GRN_TOKEN_DONE : GRN_TOKEN_DOING;
- token_cursor->force_prefix = 0;
-#define SKIP_FLAGS \
- (GRN_TOKENIZER_TOKEN_SKIP | GRN_TOKENIZER_TOKEN_SKIP_WITH_POSITION)
- if (status & SKIP_FLAGS) {
- if (status & GRN_TOKENIZER_TOKEN_SKIP) {
- token_cursor->pos++;
- }
- if (token_cursor->status == GRN_TOKEN_DONE && tid == GRN_ID_NIL) {
- token_cursor->status = GRN_TOKEN_DONE_SKIP;
- break;
- } else {
- continue;
- }
- }
-#undef SKIP_FLAGS
- if (token_cursor->curr_size == 0) {
- char tokenizer_name[GRN_TABLE_MAX_KEY_SIZE];
- int tokenizer_name_length;
- tokenizer_name_length =
- grn_obj_name(ctx, token_cursor->tokenizer,
- tokenizer_name, GRN_TABLE_MAX_KEY_SIZE);
- GRN_LOG(ctx, GRN_WARN,
- "[token_next] ignore an empty token: <%.*s>: <%.*s>",
- tokenizer_name_length, tokenizer_name,
- token_cursor->orig_blen, token_cursor->orig);
- continue;
- }
- if (token_cursor->curr_size > GRN_TABLE_MAX_KEY_SIZE) {
- GRN_LOG(ctx, GRN_WARN,
- "[token_next] ignore too long token. "
- "Token must be less than or equal to %d: <%d>(<%.*s>)",
- GRN_TABLE_MAX_KEY_SIZE,
- token_cursor->curr_size,
- token_cursor->curr_size, token_cursor->curr);
- continue;
- }
- if (status & GRN_TOKENIZER_TOKEN_UNMATURED) {
- if (status & GRN_TOKENIZER_TOKEN_OVERLAP) {
- if (token_cursor->mode == GRN_TOKEN_GET) { token_cursor->pos++; continue; }
- } else {
- if (status & GRN_TOKENIZER_TOKEN_LAST) { token_cursor->force_prefix = 1; }
- }
- }
- } else {
- token_cursor->status = GRN_TOKEN_DONE;
- }
- if (token_cursor->mode == GRN_TOKEN_ADD) {
- switch (table->header.type) {
- case GRN_TABLE_PAT_KEY :
- if (grn_io_lock(ctx, ((grn_pat *)table)->io, grn_lock_timeout)) {
- tid = GRN_ID_NIL;
- } else {
- tid = grn_pat_add(ctx, (grn_pat *)table, token_cursor->curr, token_cursor->curr_size,
- NULL, NULL);
- grn_io_unlock(((grn_pat *)table)->io);
- }
- break;
- case GRN_TABLE_DAT_KEY :
- if (grn_io_lock(ctx, ((grn_dat *)table)->io, grn_lock_timeout)) {
- tid = GRN_ID_NIL;
- } else {
- tid = grn_dat_add(ctx, (grn_dat *)table, token_cursor->curr, token_cursor->curr_size,
- NULL, NULL);
- grn_io_unlock(((grn_dat *)table)->io);
- }
- break;
- case GRN_TABLE_HASH_KEY :
- if (grn_io_lock(ctx, ((grn_hash *)table)->io, grn_lock_timeout)) {
- tid = GRN_ID_NIL;
- } else {
- tid = grn_hash_add(ctx, (grn_hash *)table, token_cursor->curr, token_cursor->curr_size,
- NULL, NULL);
- grn_io_unlock(((grn_hash *)table)->io);
- }
- break;
- case GRN_TABLE_NO_KEY :
- if (token_cursor->curr_size == sizeof(grn_id)) {
- tid = *((grn_id *)token_cursor->curr);
- } else {
- tid = GRN_ID_NIL;
- }
- break;
- }
- } else {
- switch (table->header.type) {
- case GRN_TABLE_PAT_KEY :
- tid = grn_pat_get(ctx, (grn_pat *)table, token_cursor->curr, token_cursor->curr_size, NULL);
- break;
- case GRN_TABLE_DAT_KEY :
- tid = grn_dat_get(ctx, (grn_dat *)table, token_cursor->curr, token_cursor->curr_size, NULL);
- break;
- case GRN_TABLE_HASH_KEY :
- tid = grn_hash_get(ctx, (grn_hash *)table, token_cursor->curr, token_cursor->curr_size, NULL);
- break;
- case GRN_TABLE_NO_KEY :
- if (token_cursor->curr_size == sizeof(grn_id)) {
- tid = *((grn_id *)token_cursor->curr);
- } else {
- tid = GRN_ID_NIL;
- }
- break;
- }
- }
- if (tid == GRN_ID_NIL && token_cursor->status != GRN_TOKEN_DONE) {
- token_cursor->status = GRN_TOKEN_NOT_FOUND;
- }
- token_cursor->pos++;
- break;
- }
- return tid;
-}
-
-static void
-grn_token_cursor_close_token_filters(grn_ctx *ctx,
- grn_token_cursor *token_cursor)
-{
- grn_obj *token_filters = token_cursor->token_filters;
- unsigned int i, n_token_filters;
-
- if (token_filters) {
- n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *);
- } else {
- n_token_filters = 0;
- }
- for (i = 0; i < n_token_filters; i++) {
- grn_obj *token_filter_object = GRN_PTR_VALUE_AT(token_filters, i);
- grn_proc *token_filter = (grn_proc *)token_filter_object;
-
- token_filter->callbacks.token_filter.fin(ctx, token_filter->user_data);
- }
-}
-
-grn_rc
-grn_token_cursor_close(grn_ctx *ctx, grn_token_cursor *token_cursor)
-{
- if (token_cursor) {
- if (token_cursor->tokenizer) {
- ((grn_proc *)token_cursor->tokenizer)->funcs[PROC_FIN](ctx, 1, &token_cursor->table,
- &token_cursor->pctx.user_data);
- }
- grn_token_cursor_close_token_filters(ctx, token_cursor);
- if (token_cursor->nstr) {
- grn_obj_close(ctx, token_cursor->nstr);
- }
- GRN_FREE(token_cursor);
- return GRN_SUCCESS;
- } else {
- return GRN_INVALID_ARGUMENT;
- }
-}
-
grn_rc
grn_db_init_mecab_tokenizer(grn_ctx *ctx)
{
diff --git a/storage/mroonga/vendor/groonga/lib/util.c b/storage/mroonga/vendor/groonga/lib/util.c
index 67f0ff32125..dd703b53928 100644
--- a/storage/mroonga/vendor/groonga/lib/util.c
+++ b/storage/mroonga/vendor/groonga/lib/util.c
@@ -1,5 +1,5 @@
/* -*- c-basic-offset: 2 -*- */
-/* Copyright(C) 2010-2014 Brazil
+/* Copyright(C) 2010-2015 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -15,11 +15,11 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "db.h"
-#include "pat.h"
-#include "ii.h"
-#include "util.h"
-#include "string_in.h"
+#include "grn_db.h"
+#include "grn_pat.h"
+#include "grn_ii.h"
+#include "grn_util.h"
+#include "grn_string.h"
#include <string.h>
#include <stdio.h>
@@ -254,6 +254,9 @@ grn_proc_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
case GRN_PROC_TOKEN_FILTER :
GRN_TEXT_PUTS(ctx, buf, "token-filter");
break;
+ case GRN_PROC_SCORER :
+ GRN_TEXT_PUTS(ctx, buf, "scorer");
+ break;
}
GRN_TEXT_PUTS(ctx, buf, " ");
@@ -275,6 +278,90 @@ grn_proc_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
return GRN_SUCCESS;
}
+grn_rc
+grn_expr_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *expr)
+{
+ grn_expr *e = (grn_expr *)expr;
+
+ GRN_TEXT_PUTS(ctx, buffer, "#<expr\n");
+ {
+ int i = 0;
+ grn_obj *value;
+ const char *name;
+ uint32_t name_len;
+ unsigned int n_vars;
+ grn_hash *vars = grn_expr_get_vars(ctx, expr, &n_vars);
+ GRN_TEXT_PUTS(ctx, buffer, " vars:{");
+ GRN_HASH_EACH(ctx, vars, id, &name, &name_len, &value, {
+ if (i++) {
+ GRN_TEXT_PUTC(ctx, buffer, ',');
+ }
+ GRN_TEXT_PUTS(ctx, buffer, "\n ");
+ GRN_TEXT_PUT(ctx, buffer, name, name_len);
+ GRN_TEXT_PUTC(ctx, buffer, ':');
+ grn_inspect_indented(ctx, buffer, value, " ");
+ });
+ GRN_TEXT_PUTS(ctx, buffer, "\n },");
+ }
+
+ {
+ uint32_t i, j;
+ grn_expr_var *var;
+ grn_expr_code *code;
+ GRN_TEXT_PUTS(ctx, buffer, "\n codes:{");
+ for (j = 0, code = e->codes; j < e->codes_curr; j++, code++) {
+ if (j) { GRN_TEXT_PUTC(ctx, buffer, ','); }
+ GRN_TEXT_PUTS(ctx, buffer, "\n ");
+ grn_text_itoa(ctx, buffer, j);
+ GRN_TEXT_PUTS(ctx, buffer, ":<");
+ GRN_TEXT_PUTS(ctx, buffer, grn_operator_to_string(code->op));
+ GRN_TEXT_PUTS(ctx, buffer, "(");
+ for (i = 0, var = e->vars; i < e->nvars; i++, var++) {
+ if (i) { GRN_TEXT_PUTC(ctx, buffer, ','); }
+ GRN_TEXT_PUTC(ctx, buffer, '?');
+ if (var->name_size) {
+ GRN_TEXT_PUT(ctx, buffer, var->name, var->name_size);
+ } else {
+ grn_text_itoa(ctx, buffer, (int)i);
+ }
+ }
+ GRN_TEXT_PUTS(ctx, buffer, "), ");
+ GRN_TEXT_PUTS(ctx, buffer, "modify:");
+ grn_text_itoa(ctx, buffer, code->modify);
+ GRN_TEXT_PUTS(ctx, buffer, ", ");
+ GRN_TEXT_PUTS(ctx, buffer, "value:");
+ grn_inspect_indented(ctx, buffer, code->value, " ");
+ GRN_TEXT_PUTS(ctx, buffer, ">");
+ }
+ GRN_TEXT_PUTS(ctx, buffer, "\n }");
+ }
+
+ GRN_TEXT_PUTS(ctx, buffer, "\n>");
+
+ return GRN_SUCCESS;
+}
+
+static grn_rc
+grn_pvector_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *pvector)
+{
+ int i, n;
+
+ GRN_TEXT_PUTS(ctx, buffer, "[");
+ n = GRN_BULK_VSIZE(pvector) / sizeof(grn_obj *);
+ for (i = 0; i < n; i++) {
+ grn_obj *element = GRN_PTR_VALUE_AT(pvector, i);
+
+ if (i > 0) {
+ GRN_TEXT_PUTS(ctx, buffer, ", ");
+ }
+
+ grn_inspect(ctx, buffer, element);
+ }
+ GRN_TEXT_PUTS(ctx, buffer, "]");
+
+ return GRN_SUCCESS;
+}
+
static grn_rc
grn_vector_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *vector)
{
@@ -400,8 +487,8 @@ grn_store_inspect_body(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
case GRN_OBJ_COMPRESS_ZLIB :
GRN_TEXT_PUTS(ctx, buf, "zlib");
break;
- case GRN_OBJ_COMPRESS_LZO :
- GRN_TEXT_PUTS(ctx, buf, "lzo");
+ case GRN_OBJ_COMPRESS_LZ4 :
+ GRN_TEXT_PUTS(ctx, buf, "lz4");
break;
default:
break;
@@ -481,9 +568,6 @@ grn_ii_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
GRN_TEXT_PUTS(ctx, buf, "NONE");
}
- GRN_TEXT_PUTS(ctx, buf, " elements:");
- grn_ii_inspect_elements(ctx, (grn_ii *)obj, buf);
-
GRN_TEXT_PUTS(ctx, buf, ">");
return GRN_SUCCESS;
@@ -499,6 +583,9 @@ grn_table_type_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
case GRN_TABLE_PAT_KEY:
GRN_TEXT_PUTS(ctx, buf, "pat");
break;
+ case GRN_TABLE_DAT_KEY:
+ GRN_TEXT_PUTS(ctx, buf, "dat");
+ break;
case GRN_TABLE_NO_KEY:
GRN_TEXT_PUTS(ctx, buf, "no_key");
break;
@@ -742,6 +829,24 @@ grn_table_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
}
static grn_rc
+grn_db_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
+{
+ grn_db *db = (grn_db *)obj;
+
+ GRN_TEXT_PUTS(ctx, buf, "#<db");
+
+ GRN_TEXT_PUTS(ctx, buf, " key_type:");
+ grn_table_type_inspect(ctx, buf, db->keys);
+
+ GRN_TEXT_PUTS(ctx, buf, " size:");
+ grn_text_lltoa(ctx, buf, grn_table_size(ctx, obj));
+
+ GRN_TEXT_PUTS(ctx, buf, ">");
+
+ return GRN_SUCCESS;
+}
+
+static grn_rc
grn_geo_point_inspect_point(grn_ctx *ctx, grn_obj *buf, int point)
{
GRN_TEXT_PUTS(ctx, buf, "(");
@@ -850,7 +955,6 @@ grn_json_load_open_brace_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
static grn_rc
grn_record_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
{
- grn_id id;
grn_obj *table;
grn_hash *cols;
@@ -867,6 +971,11 @@ grn_record_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
}
GRN_TEXT_PUTS(ctx, buf, " id:");
+ if (GRN_BULK_VSIZE(obj) == 0) {
+ GRN_TEXT_PUTS(ctx, buf, "(no value)");
+ } else {
+ grn_id id;
+
id = GRN_RECORD_VALUE(obj);
grn_text_lltoa(ctx, buf, id);
@@ -903,6 +1012,8 @@ grn_record_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
} else {
GRN_TEXT_PUTS(ctx, buf, "(nonexistent)");
}
+ }
+
GRN_TEXT_PUTS(ctx, buf, ">");
if (table) {
@@ -1008,8 +1119,8 @@ grn_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *obj)
}
break;
case GRN_PVECTOR :
- /* TODO */
- break;
+ grn_pvector_inspect(ctx, buffer, obj);
+ return buffer;
case GRN_VECTOR :
grn_vector_inspect(ctx, buffer, obj);
return buffer;
@@ -1054,7 +1165,7 @@ grn_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *obj)
grn_table_inspect(ctx, buffer, obj);
return buffer;
case GRN_DB :
- /* TODO */
+ grn_db_inspect(ctx, buffer, obj);
break;
case GRN_COLUMN_FIX_SIZE :
grn_ra_inspect(ctx, buffer, obj);
@@ -1073,6 +1184,45 @@ grn_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *obj)
return buffer;
}
+grn_obj *
+grn_inspect_indented(grn_ctx *ctx, grn_obj *buffer, grn_obj *obj,
+ const char *indent)
+{
+ grn_obj sub_buffer;
+
+ GRN_TEXT_INIT(&sub_buffer, 0);
+ grn_inspect(ctx, &sub_buffer, obj);
+ {
+ const char *inspected = GRN_TEXT_VALUE(&sub_buffer);
+ size_t inspected_size = GRN_TEXT_LEN(&sub_buffer);
+ size_t i, line_start;
+
+ if (!buffer) {
+ buffer = grn_obj_open(ctx, GRN_BULK, 0, GRN_DB_TEXT);
+ }
+
+ line_start = 0;
+ for (i = 0; i < inspected_size; i++) {
+ if (inspected[i] == '\n') {
+ if (line_start != 0) {
+ GRN_TEXT_PUTS(ctx, buffer, indent);
+ }
+ GRN_TEXT_PUT(ctx, buffer, inspected + line_start, i + 1 - line_start);
+ line_start = i + 1;
+ }
+ }
+ if (line_start != 0) {
+ GRN_TEXT_PUTS(ctx, buffer, indent);
+ }
+ GRN_TEXT_PUT(ctx, buffer,
+ inspected + line_start,
+ inspected_size - line_start);
+ }
+ GRN_OBJ_FIN(ctx, &sub_buffer);
+
+ return buffer;
+}
+
void
grn_p(grn_ctx *ctx, grn_obj *obj)
{
@@ -1095,6 +1245,17 @@ grn_p_geo_point(grn_ctx *ctx, grn_geo_point *point)
grn_obj_unlink(ctx, &obj);
}
+void
+grn_p_ii_values(grn_ctx *ctx, grn_obj *ii)
+{
+ grn_obj buffer;
+
+ GRN_TEXT_INIT(&buffer, 0);
+ grn_ii_inspect_values(ctx, (grn_ii *)ii, &buffer);
+ printf("%.*s\n", (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer));
+ grn_obj_unlink(ctx, &buffer);
+}
+
#ifdef WIN32
static char *win32_base_dir = NULL;
const char *
diff --git a/storage/mroonga/vendor/groonga/nginx_version b/storage/mroonga/vendor/groonga/nginx_version
index de28578affc..f65dc1e213e 100644
--- a/storage/mroonga/vendor/groonga/nginx_version
+++ b/storage/mroonga/vendor/groonga/nginx_version
@@ -1 +1 @@
-1.7.6
+1.7.9
diff --git a/storage/mroonga/vendor/groonga/plugins/CMakeLists.txt b/storage/mroonga/vendor/groonga/plugins/CMakeLists.txt
index 42a3045a415..89a28f50b99 100644
--- a/storage/mroonga/vendor/groonga/plugins/CMakeLists.txt
+++ b/storage/mroonga/vendor/groonga/plugins/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright(C) 2012-2014 Brazil
+# Copyright(C) 2012-2015 Brazil
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -19,3 +19,10 @@ add_subdirectory(table)
add_subdirectory(query_expanders)
add_subdirectory(ruby)
add_subdirectory(token_filters)
+add_subdirectory(sharding)
+
+if(GRN_WITH_MRUBY)
+ read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/ruby_scripts.am RUBY_SCRIPTS)
+ install(FILES ${RUBY_SCRIPTS}
+ DESTINATION "${GRN_RELATIVE_PLUGINS_DIR}")
+endif()
diff --git a/storage/mroonga/vendor/groonga/plugins/Makefile.am b/storage/mroonga/vendor/groonga/plugins/Makefile.am
index 1d1abf1dee9..92007edd732 100644
--- a/storage/mroonga/vendor/groonga/plugins/Makefile.am
+++ b/storage/mroonga/vendor/groonga/plugins/Makefile.am
@@ -4,7 +4,15 @@ SUBDIRS = \
table \
query_expanders \
ruby \
- token_filters
+ token_filters \
+ sharding
EXTRA_DIST = \
CMakeLists.txt
+
+if WITH_MRUBY
+dist_plugins_DATA = \
+ $(ruby_scripts)
+endif
+
+include ruby_scripts.am
diff --git a/storage/mroonga/vendor/groonga/plugins/query_expanders/CMakeLists.txt b/storage/mroonga/vendor/groonga/plugins/query_expanders/CMakeLists.txt
index 1e2a2c23b09..57d11abfbcb 100644
--- a/storage/mroonga/vendor/groonga/plugins/query_expanders/CMakeLists.txt
+++ b/storage/mroonga/vendor/groonga/plugins/query_expanders/CMakeLists.txt
@@ -27,6 +27,4 @@ set_target_properties(tsv_query_expander PROPERTIES
PREFIX ""
OUTPUT_NAME "tsv")
target_link_libraries(tsv_query_expander libgroonga)
-if(NOT MRN_GROONGA_BUNDLED)
- install(TARGETS tsv_query_expander DESTINATION "${QUERY_EXPANDERS_DIR}")
-endif()
+install(TARGETS tsv_query_expander DESTINATION "${QUERY_EXPANDERS_DIR}")
diff --git a/storage/mroonga/vendor/groonga/plugins/query_expanders/tsv.c b/storage/mroonga/vendor/groonga/plugins/query_expanders/tsv.c
index 6b1fc51d6dc..1b9f177711a 100644
--- a/storage/mroonga/vendor/groonga/plugins/query_expanders/tsv.c
+++ b/storage/mroonga/vendor/groonga/plugins/query_expanders/tsv.c
@@ -15,17 +15,20 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include <groonga/plugin.h>
-
/* groonga's internal headers */
/* for grn_text_fgets(): We don't want to require stdio.h for groonga.h.
What should we do? Should we split header file such as groonga/stdio.h? */
-#include <str.h>
+#include <grn_str.h>
+
+#include <groonga/plugin.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE__STRNICMP
+# ifdef strncasecmp
+# undef strncasecmp
+# endif /* strncasecmp */
# define strncasecmp(s1,s2,n) _strnicmp(s1,s2,n)
#endif /* HAVE__STRNICMP */
@@ -42,7 +45,6 @@ get_system_synonyms_file(void)
const char *base_dir;
const char *relative_path = GRN_QUERY_EXPANDER_TSV_RELATIVE_SYNONYMS_FILE;
char *synonyms_file;
- char *path;
size_t base_dir_length;
base_dir = grn_plugin_win32_base_dir();
diff --git a/storage/mroonga/vendor/groonga/plugins/ruby/CMakeLists.txt b/storage/mroonga/vendor/groonga/plugins/ruby/CMakeLists.txt
index d82b154098c..ba7deafe0d3 100644
--- a/storage/mroonga/vendor/groonga/plugins/ruby/CMakeLists.txt
+++ b/storage/mroonga/vendor/groonga/plugins/ruby/CMakeLists.txt
@@ -27,9 +27,7 @@ if(GRN_WITH_MRUBY)
COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}")
set_target_properties(eval PROPERTIES PREFIX "")
target_link_libraries(eval libgroonga)
- if(NOT MRN_GROONGA_BUNDLED)
- install(TARGETS eval DESTINATION "${GRN_RELATIVE_RUBY_PLUGINS_DIR}")
- endif()
+ install(TARGETS eval DESTINATION "${GRN_RELATIVE_RUBY_PLUGINS_DIR}")
read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/load_sources.am RUBY_LOAD_SOURCES)
add_library(load MODULE ${RUBY_LOAD_SOURCES})
@@ -38,7 +36,5 @@ if(GRN_WITH_MRUBY)
COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}")
set_target_properties(load PROPERTIES PREFIX "")
target_link_libraries(load libgroonga)
- if(NOT MRN_GROONGA_BUNDLED)
- install(TARGETS load DESTINATION "${GRN_RELATIVE_RUBY_PLUGINS_DIR}")
- endif()
+ install(TARGETS load DESTINATION "${GRN_RELATIVE_RUBY_PLUGINS_DIR}")
endif()
diff --git a/storage/mroonga/vendor/groonga/plugins/ruby/ruby_plugin.h b/storage/mroonga/vendor/groonga/plugins/ruby/ruby_plugin.h
index 5314ea68fe5..57cab2885b1 100644
--- a/storage/mroonga/vendor/groonga/plugins/ruby/ruby_plugin.h
+++ b/storage/mroonga/vendor/groonga/plugins/ruby/ruby_plugin.h
@@ -16,11 +16,11 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include <mrb.h>
-#include <output.h>
-#include <db.h>
-#include <ctx_impl.h>
-#include <util.h>
+#include <grn_mrb.h>
+#include <grn_output.h>
+#include <grn_db.h>
+#include <grn_ctx_impl.h>
+#include <grn_util.h>
#include <groonga/plugin.h>
diff --git a/storage/mroonga/vendor/groonga/plugins/ruby_scripts.am b/storage/mroonga/vendor/groonga/plugins/ruby_scripts.am
new file mode 100644
index 00000000000..0262dbb94ef
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/plugins/ruby_scripts.am
@@ -0,0 +1,2 @@
+ruby_scripts = \
+ sharding.rb
diff --git a/storage/mroonga/vendor/groonga/plugins/sharding.rb b/storage/mroonga/vendor/groonga/plugins/sharding.rb
new file mode 100644
index 00000000000..8902d7e6c27
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/plugins/sharding.rb
@@ -0,0 +1,3 @@
+require "sharding/logical_enumerator"
+require "sharding/logical_count"
+require "sharding/logical_range_filter"
diff --git a/storage/mroonga/vendor/groonga/plugins/sharding/CMakeLists.txt b/storage/mroonga/vendor/groonga/plugins/sharding/CMakeLists.txt
new file mode 100644
index 00000000000..8d0cdd976dc
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/plugins/sharding/CMakeLists.txt
@@ -0,0 +1,22 @@
+# Copyright(C) 2015 Brazil
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1 as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+if(GRN_WITH_MRUBY)
+ set(GRN_RELATIVE_SHARDING_PLUGINS_DIR "${GRN_RELATIVE_PLUGINS_DIR}/sharding")
+
+ read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/sources.am SHARDING_SCRIPTS)
+ install(FILES ${SHARDING_SCRIPTS}
+ DESTINATION "${GRN_RELATIVE_SHARDING_PLUGINS_DIR}")
+endif()
diff --git a/storage/mroonga/vendor/groonga/plugins/sharding/Makefile.am b/storage/mroonga/vendor/groonga/plugins/sharding/Makefile.am
new file mode 100644
index 00000000000..8104ab6d729
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/plugins/sharding/Makefile.am
@@ -0,0 +1,9 @@
+EXTRA_DIST = \
+ CMakeLists.txt
+
+if WITH_MRUBY
+dist_sharding_plugins_DATA = \
+ $(sharding_scripts)
+endif
+
+include sources.am
diff --git a/storage/mroonga/vendor/groonga/plugins/sharding/logical_count.rb b/storage/mroonga/vendor/groonga/plugins/sharding/logical_count.rb
new file mode 100644
index 00000000000..ef993b40dc8
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/plugins/sharding/logical_count.rb
@@ -0,0 +1,160 @@
+module Groonga
+ module Sharding
+ class LogicalCountCommand < Command
+ register("logical_count",
+ [
+ "logical_table",
+ "shard_key",
+ "min",
+ "min_border",
+ "max",
+ "max_border",
+ "filter",
+ ])
+
+ def run_body(input)
+ enumerator = LogicalEnumerator.new("logical_count", input)
+ filter = input[:filter]
+
+ total = 0
+ enumerator.each do |table, shard_key, shard_range|
+ total += count_n_records(table, filter,
+ shard_key, shard_range,
+ enumerator.target_range)
+ end
+ writer.write(total)
+ end
+
+ private
+ def count_n_records(table, filter,
+ shard_key, shard_range,
+ target_range)
+ cover_type = target_range.cover_type(shard_range)
+ return 0 if cover_type == :none
+
+ if cover_type == :all
+ if filter.nil?
+ return table.size
+ else
+ return filtered_count_n_records(table, filter)
+ end
+ end
+
+ use_range_index = false
+ range_index = nil
+ if filter.nil?
+ index_info = shard_key.find_index(Operator::LESS)
+ if index_info
+ range_index = index_info.index
+ use_range_index = true
+ end
+ end
+
+ case cover_type
+ when :partial_min
+ if use_range_index
+ count_n_records_in_range(range_index,
+ target_range.min, target_range.min_border,
+ nil, nil)
+ else
+ filtered_count_n_records(table, filter) do |expression|
+ expression.append_object(shard_key, Operator::PUSH, 1)
+ expression.append_operator(Operator::GET_VALUE, 1)
+ expression.append_constant(target_range.min, Operator::PUSH, 1)
+ if target_range.min_border == :include
+ expression.append_operator(Operator::GREATER_EQUAL, 2)
+ else
+ expression.append_operator(Operator::GREATER, 2)
+ end
+ end
+ end
+ when :partial_max
+ if use_range_index
+ count_n_records_in_range(range_index,
+ nil, nil,
+ target_range.max, target_range.max_border)
+ else
+ filtered_count_n_records(table, filter) do |expression|
+ expression.append_object(shard_key, Operator::PUSH, 1)
+ expression.append_operator(Operator::GET_VALUE, 1)
+ expression.append_constant(target_range.max, Operator::PUSH, 1)
+ if target_range.max_border == :include
+ expression.append_operator(Operator::LESS_EQUAL, 2)
+ else
+ expression.append_operator(Operator::LESS, 2)
+ end
+ end
+ end
+ when :partial_min_and_max
+ if use_range_index
+ count_n_records_in_range(range_index,
+ target_range.min, target_range.min_border,
+ target_range.max, target_range.max_border)
+ else
+ filtered_count_n_records(table, filter) do |expression|
+ expression.append_object(context["between"], Operator::PUSH, 1)
+ expression.append_object(shard_key, Operator::PUSH, 1)
+ expression.append_operator(Operator::GET_VALUE, 1)
+ expression.append_constant(target_range.min, Operator::PUSH, 1)
+ expression.append_constant(target_range.min_border,
+ Operator::PUSH, 1)
+ expression.append_constant(target_range.max, Operator::PUSH, 1)
+ expression.append_constant(target_range.max_border,
+ Operator::PUSH, 1)
+ expression.append_operator(Operator::CALL, 5)
+ end
+ end
+ end
+ end
+
+ def filtered_count_n_records(table, filter)
+ expression = nil
+ filtered_table = nil
+
+ begin
+ expression = Expression.create(table)
+ if block_given?
+ yield(expression)
+ if filter
+ expression.parse(filter)
+ expression.append_operator(Operator::AND, 2)
+ end
+ else
+ expression.parse(filter)
+ end
+ filtered_table = table.select(expression)
+ filtered_table.size
+ ensure
+ filtered_table.close if filtered_table
+ expression.close if expression
+ end
+ end
+
+ def count_n_records_in_range(range_index,
+ min, min_border, max, max_border)
+ flags = TableCursorFlags::BY_KEY
+ case min_border
+ when :include
+ flags |= TableCursorFlags::GE
+ when :exclude
+ flags |= TableCursorFlags::GT
+ end
+ case max_border
+ when :include
+ flags |= TableCursorFlags::LE
+ when :exclude
+ flags |= TableCursorFlags::LT
+ end
+
+ TableCursor.open(range_index.table,
+ :min => min,
+ :max => max,
+ :flags => flags) do |table_cursor|
+ IndexCursor.open(table_cursor, range_index) do |index_cursor|
+ index_cursor.count
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/storage/mroonga/vendor/groonga/plugins/sharding/logical_enumerator.rb b/storage/mroonga/vendor/groonga/plugins/sharding/logical_enumerator.rb
new file mode 100644
index 00000000000..7ad5393ae77
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/plugins/sharding/logical_enumerator.rb
@@ -0,0 +1,170 @@
+module Groonga
+ module Sharding
+ class LogicalEnumerator
+ attr_reader :target_range
+ attr_reader :shard_key_name
+ def initialize(command_name, input)
+ @command_name = command_name
+ @input = input
+ initialize_parameters
+ end
+
+ def each
+ prefix = "#{@logical_table}_"
+ context = Context.instance
+ context.database.each_table(:prefix => prefix,
+ :order_by => :key,
+ :order => :ascending) do |table|
+ shard_range_raw = table.name[prefix.size..-1]
+
+ next unless /\A(\d{4})(\d{2})(\d{2})\z/ =~ shard_range_raw
+ shard_range = ShardRange.new($1.to_i, $2.to_i, $3.to_i)
+
+ physical_shard_key_name = "#{table.name}.#{@shard_key_name}"
+ shard_key = context[physical_shard_key_name]
+ if shard_key.nil?
+ message =
+ "[#{@command_name}] shard_key doesn't exist: " +
+ "<#{physical_shard_key_name}>"
+ raise InvalidArgument, message
+ end
+
+ yield(table, shard_key, shard_range)
+ end
+ end
+
+ private
+ def initialize_parameters
+ @logical_table = @input[:logical_table]
+ if @logical_table.nil?
+ raise InvalidArgument, "[#{@command_name}] logical_table is missing"
+ end
+
+ @shard_key_name = @input[:shard_key]
+ if @shard_key_name.nil?
+ raise InvalidArgument, "[#{@command_name}] shard_key is missing"
+ end
+
+ @target_range = TargetRange.new(@command_name, @input)
+ end
+
+ class ShardRange
+ attr_reader :year, :month, :day
+ def initialize(year, month, day)
+ @year = year
+ @month = month
+ @day = day
+ end
+ end
+
+ class TargetRange
+ attr_reader :min, :min_border
+ attr_reader :max, :max_border
+ def initialize(command_name, input)
+ @command_name = command_name
+ @input = input
+ @min = parse_value(:min)
+ @min_border = parse_border(:min_border)
+ @max = parse_value(:max)
+ @max_border = parse_border(:max_border)
+ end
+
+ def cover_type(shard_range)
+ return :all if @min.nil? and @max.nil?
+
+ if @min and @max
+ return :none unless in_min?(shard_range)
+ return :none unless in_max?(shard_range)
+ min_partial_p = in_min_partial?(shard_range)
+ max_partial_p = in_max_partial?(shard_range)
+ if min_partial_p and max_partial_p
+ :partial_min_and_max
+ elsif min_partial_p
+ :partial_min
+ elsif max_partial_p
+ :partial_max
+ else
+ :all
+ end
+ elsif @min
+ return :none unless in_min?(shard_range)
+ if in_min_partial?(shard_range)
+ :partial_min
+ else
+ :all
+ end
+ else
+ return :none unless in_max?(shard_range)
+ if in_max_partial?(shard_range)
+ :partial_max
+ else
+ :all
+ end
+ end
+ end
+
+ private
+ def parse_value(name)
+ value = @input[name]
+ return nil if value.nil?
+
+ Converter.convert(value, Time)
+ end
+
+ def parse_border(name)
+ border = @input[name]
+ return :include if border.nil?
+
+ case border
+ when "include"
+ :include
+ when "exclude"
+ :exclude
+ else
+ message =
+ "[#{@command_name}] #{name} must be \"include\" or \"exclude\": " +
+ "<#{border}>"
+ raise InvalidArgument, message
+ end
+ end
+
+ def in_min?(shard_range)
+ base_time = Time.local(shard_range.year,
+ shard_range.month,
+ shard_range.day + 1)
+ @min < base_time
+ end
+
+ def in_min_partial?(shard_range)
+ return false unless @min.year == shard_range.year
+ return false unless @min.month == shard_range.month
+ return false unless @min.day == shard_range.day
+
+ return true if @min_border == :exclude
+
+ @min.hour != 0 and
+ @min.min != 0 and
+ @min.sec != 0 and
+ @min.usec != 0
+ end
+
+ def in_max?(shard_range)
+ max_base_time = Time.local(shard_range.year,
+ shard_range.month,
+ shard_range.day)
+ if @max_border == :include
+ @max >= max_base_time
+ else
+ @max > max_base_time
+ end
+ end
+
+ def in_max_partial?(shard_range)
+ @max.year == shard_range.year and
+ @max.month == shard_range.month and
+ @max.day == shard_range.day
+ end
+ end
+ end
+ end
+end
diff --git a/storage/mroonga/vendor/groonga/plugins/sharding/logical_range_filter.rb b/storage/mroonga/vendor/groonga/plugins/sharding/logical_range_filter.rb
new file mode 100644
index 00000000000..7e765f7d3c2
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/plugins/sharding/logical_range_filter.rb
@@ -0,0 +1,186 @@
+module Groonga
+ module Sharding
+ class LogicalRangeFilterCommand < Command
+ register("logical_range_filter",
+ [
+ "logical_table",
+ "shard_key",
+ "min",
+ "min_border",
+ "max",
+ "max_border",
+ "order",
+ "filter",
+ "offset",
+ "limit",
+ "output_columns",
+ ])
+
+ def run_body(input)
+ enumerator = LogicalEnumerator.new("logical_range_filter", input)
+ filter = input[:filter]
+ offset = (input[:offset] || 0).to_i
+ limit = (input[:limit] || 10).to_i
+ output_columns = input[:output_columns] || "_key, *"
+
+ result_sets = []
+ n_records = 0
+ enumerator.each do |table, shard_key, shard_range|
+ result_set = filter_shard(table, filter,
+ shard_key, shard_range,
+ enumerator.target_range)
+ next if result_set.nil?
+ if result_set.empty?
+ result_set.close if result_set.temporary?
+ next
+ end
+ result_sets << result_set
+ n_records += result_set.size
+ break if n_records >= offset + limit
+ end
+
+ if result_sets.empty?
+ n_elements = 0
+ else
+ n_elements = 1 # for columns
+ result_sets.each do |result_set|
+ n_elements += result_set.size
+ end
+ end
+
+ sort_keys = [
+ {
+ :key => enumerator.shard_key_name,
+ :order => :ascending,
+ },
+ ]
+ current_offset = offset
+ current_limit = limit
+ writer.array("RESULTSET", n_elements) do
+ first_result_set = result_sets.first
+ if first_result_set
+ writer.write_table_columns(first_result_set, output_columns)
+ end
+ result_sets.each do |result_set|
+ if result_set.size <= current_offset
+ current_offset -= result_set.size
+ next
+ end
+ sorted_result_set = result_set.sort(sort_keys,
+ :offset => current_offset,
+ :limit => current_limit)
+ writer.write_table_records(sorted_result_set, output_columns)
+ current_limit -= sorted_result_set.size
+ sorted_result_set.close
+ end
+ end
+
+ result_sets.each do |result_set|
+ result_set.close if result_set.temporary?
+ end
+ end
+
+ def filter_shard(table, filter, shard_key, shard_range, target_range)
+ cover_type = target_range.cover_type(shard_range)
+ return nil if cover_type == :none
+
+ if cover_type == :all
+ if filter.nil?
+ return table
+ else
+ return filter_table(table, filter)
+ end
+ end
+
+ use_range_index = false
+ range_index = nil
+ # TODO
+ # if filter.nil?
+ # index_info = shard_key.find_index(Operator::LESS)
+ # if index_info
+ # range_index = index_info.index
+ # use_range_index = true
+ # end
+ # end
+
+ case cover_type
+ when :partial_min
+ if use_range_index
+ # TODO
+ # count_n_records_in_range(range_index,
+ # target_range.min, target_range.min_border,
+ # nil, nil)
+ else
+ filter_table(table, filter) do |expression|
+ expression.append_object(shard_key, Operator::PUSH, 1)
+ expression.append_operator(Operator::GET_VALUE, 1)
+ expression.append_constant(target_range.min, Operator::PUSH, 1)
+ if target_range.min_border == :include
+ expression.append_operator(Operator::GREATER_EQUAL, 2)
+ else
+ expression.append_operator(Operator::GREATER, 2)
+ end
+ end
+ end
+ when :partial_max
+ if use_range_index
+ # TODO
+ # count_n_records_in_range(range_index,
+ # nil, nil,
+ # target_range.max, target_range.max_border)
+ else
+ filter_table(table, filter) do |expression|
+ expression.append_object(shard_key, Operator::PUSH, 1)
+ expression.append_operator(Operator::GET_VALUE, 1)
+ expression.append_constant(target_range.max, Operator::PUSH, 1)
+ if target_range.max_border == :include
+ expression.append_operator(Operator::LESS_EQUAL, 2)
+ else
+ expression.append_operator(Operator::LESS, 2)
+ end
+ end
+ end
+ when :partial_min_and_max
+ if use_range_index
+ # TODO
+ # count_n_records_in_range(range_index,
+ # target_range.min, target_range.min_border,
+ # target_range.max, target_range.max_border)
+ else
+ filter_table(table, filter) do |expression|
+ expression.append_object(context["between"], Operator::PUSH, 1)
+ expression.append_object(shard_key, Operator::PUSH, 1)
+ expression.append_operator(Operator::GET_VALUE, 1)
+ expression.append_constant(target_range.min, Operator::PUSH, 1)
+ expression.append_constant(target_range.min_border,
+ Operator::PUSH, 1)
+ expression.append_constant(target_range.max, Operator::PUSH, 1)
+ expression.append_constant(target_range.max_border,
+ Operator::PUSH, 1)
+ expression.append_operator(Operator::CALL, 5)
+ end
+ end
+ end
+ end
+
+ def filter_table(table, filter)
+ expression = nil
+ begin
+ expression = Expression.create(table)
+ if block_given?
+ yield(expression)
+ if filter
+ expression.parse(filter)
+ expression.append_operator(Operator::AND, 2)
+ end
+ else
+ expression.parse(filter)
+ end
+ table.select(expression)
+ ensure
+ expression.close if expression
+ end
+ end
+ end
+ end
+end
diff --git a/storage/mroonga/vendor/groonga/plugins/sharding/sources.am b/storage/mroonga/vendor/groonga/plugins/sharding/sources.am
new file mode 100644
index 00000000000..11b5382a6df
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/plugins/sharding/sources.am
@@ -0,0 +1,4 @@
+sharding_scripts = \
+ logical_count.rb \
+ logical_enumerator.rb \
+ logical_range_filter.rb
diff --git a/storage/mroonga/vendor/groonga/plugins/suggest/CMakeLists.txt b/storage/mroonga/vendor/groonga/plugins/suggest/CMakeLists.txt
index 72b86362c55..519193918b4 100644
--- a/storage/mroonga/vendor/groonga/plugins/suggest/CMakeLists.txt
+++ b/storage/mroonga/vendor/groonga/plugins/suggest/CMakeLists.txt
@@ -24,6 +24,4 @@ set_source_files_properties(${SUGGEST_SOURCES}
COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}")
set_target_properties(suggest PROPERTIES PREFIX "")
target_link_libraries(suggest libgroonga)
-if(NOT MRN_GROONGA_BUNDLED)
- install(TARGETS suggest DESTINATION "${GRN_RELATIVE_PLUGINS_DIR}/suggest")
-endif()
+install(TARGETS suggest DESTINATION "${GRN_RELATIVE_PLUGINS_DIR}/suggest")
diff --git a/storage/mroonga/vendor/groonga/plugins/suggest/suggest.c b/storage/mroonga/vendor/groonga/plugins/suggest/suggest.c
index 3e291b96d90..863ffcf13e3 100644
--- a/storage/mroonga/vendor/groonga/plugins/suggest/suggest.c
+++ b/storage/mroonga/vendor/groonga/plugins/suggest/suggest.c
@@ -15,15 +15,19 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "ctx.h"
-#include "db.h"
-#include "ii.h"
-#include "token.h"
-#include "output.h"
-#include <groonga/plugin.h>
#include <string.h>
+#include "grn_ctx.h"
+#include "grn_db.h"
+#include "grn_ii.h"
+#include "grn_token_cursor.h"
+#include "grn_output.h"
+#include <groonga/plugin.h>
+
#ifdef HAVE__STRNICMP
+# ifdef strncasecmp
+# undef strncasecmp
+# endif /* strcasecmp */
# define strncasecmp(s1,s2,n) _strnicmp(s1,s2,n)
#endif /* HAVE__STRNICMP */
@@ -130,12 +134,12 @@ grn_parse_suggest_types(grn_obj *text)
return types;
}
-static int32_t
+static double
cooccurrence_search(grn_ctx *ctx, grn_obj *items, grn_obj *items_boost, grn_id id,
grn_obj *res, int query_type, int frequency_threshold,
double conditional_probability_threshold)
{
- int32_t max_score = 0;
+ double max_score = 0.0;
if (id) {
grn_ii_cursor *c;
grn_obj *co = grn_obj_column(ctx, items, CONST_STR_LEN("co"));
@@ -194,7 +198,7 @@ cooccurrence_search(grn_ctx *ctx, grn_obj *items, grn_obj *items_boost, grn_id i
boost >= 0) {
grn_rset_recinfo *ri;
void *value;
- int32_t score = pfreq;
+ double score = pfreq;
int added;
if (max_score < score + boost) { max_score = score + boost; }
/* put any formula if desired */
@@ -275,7 +279,7 @@ complete_add_item(grn_ctx *ctx, grn_id id, grn_obj *res, int frequency_threshold
grn_obj_get_value(ctx, items_freq, id, item_freq);
grn_obj_get_value(ctx, items_boost, id, item_boost);
if (GRN_INT32_VALUE(item_boost) >= 0) {
- int32_t score;
+ double score;
score = 1 +
GRN_INT32_VALUE(item_freq) +
GRN_INT32_VALUE(item_boost);
@@ -380,12 +384,12 @@ correct(grn_ctx *ctx, grn_obj *items, grn_obj *items_boost,
if ((res = grn_table_create(ctx, NULL, 0, NULL,
GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, items, NULL))) {
grn_id tid = grn_table_get(ctx, items, TEXT_VALUE_LEN(query));
- int32_t max_score;
+ double max_score;
max_score = cooccurrence_search(ctx, items, items_boost, tid, res, CORRECT,
frequency_threshold,
conditional_probability_threshold);
GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SCORE,
- ":", "cooccur(%d)", max_score);
+ ":", "cooccur(%f)", max_score);
if (GRN_TEXT_LEN(query) &&
((similar_search_mode == GRN_SUGGEST_SEARCH_YES) ||
(similar_search_mode == GRN_SUGGEST_SEARCH_AUTO &&
@@ -419,7 +423,7 @@ correct(grn_ctx *ctx, grn_obj *items, grn_obj *items_boost,
grn_obj_get_value(ctx, items_freq2, *rp, &item_freq2);
grn_obj_get_value(ctx, items_boost, *rp, &item_boost);
if (GRN_INT32_VALUE(&item_boost) >= 0) {
- int32_t score;
+ double score;
grn_rset_recinfo *ri;
score = 1 +
(GRN_INT32_VALUE(&item_freq2) >> 4) +
@@ -467,13 +471,13 @@ correct(grn_ctx *ctx, grn_obj *items, grn_obj *items_boost,
if ((tc = grn_table_cursor_open(ctx, res, NULL, 0, NULL, 0, 0, -1, 0))) {
grn_id id;
grn_obj score_value;
- GRN_INT32_INIT(&score_value, 0);
+ GRN_FLOAT_INIT(&score_value, 0);
while ((id = grn_table_cursor_next(ctx, tc)) != GRN_ID_NIL) {
GRN_RECORD_SET(ctx, var, id);
grn_expr_exec(ctx, expr, 0);
GRN_BULK_REWIND(&score_value);
grn_obj_get_value(ctx, score, id, &score_value);
- if (GRN_INT32_VALUE(&score_value) < frequency_threshold) {
+ if (GRN_FLOAT_VALUE(&score_value) < frequency_threshold) {
grn_table_cursor_delete(ctx, tc);
}
}
@@ -573,7 +577,18 @@ command_suggest(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_dat
if ((items = grn_ctx_get(ctx, TEXT_VALUE_LEN(VAR(1))))) {
if ((items_boost = grn_obj_column(ctx, items, CONST_STR_LEN("boost")))) {
- GRN_OUTPUT_MAP_OPEN("RESULT_SET", -1);
+ int n_outputs = 0;
+ if (types & COMPLETE) {
+ n_outputs++;
+ }
+ if (types & CORRECT) {
+ n_outputs++;
+ }
+ if (types & SUGGEST) {
+ n_outputs++;
+ }
+ GRN_OUTPUT_MAP_OPEN("RESULT_SET", n_outputs);
+
if (types & COMPLETE) {
if ((col = grn_obj_column(ctx, items, TEXT_VALUE_LEN(VAR(2))))) {
GRN_OUTPUT_CSTR("complete");
diff --git a/storage/mroonga/vendor/groonga/plugins/table/CMakeLists.txt b/storage/mroonga/vendor/groonga/plugins/table/CMakeLists.txt
index cba4697f042..eada0395080 100644
--- a/storage/mroonga/vendor/groonga/plugins/table/CMakeLists.txt
+++ b/storage/mroonga/vendor/groonga/plugins/table/CMakeLists.txt
@@ -24,6 +24,4 @@ set_source_files_properties(${TABLE_SOURCES}
COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}")
set_target_properties(table PROPERTIES PREFIX "")
target_link_libraries(table libgroonga)
-if(NOT MRN_GROONGA_BUNDLED)
- install(TARGETS table DESTINATION "${GRN_RELATIVE_PLUGINS_DIR}/table")
-endif()
+install(TARGETS table DESTINATION "${GRN_RELATIVE_PLUGINS_DIR}/table")
diff --git a/storage/mroonga/vendor/groonga/plugins/table/table.c b/storage/mroonga/vendor/groonga/plugins/table/table.c
index a4fcd17bf90..3b0c09d9a91 100644
--- a/storage/mroonga/vendor/groonga/plugins/table/table.c
+++ b/storage/mroonga/vendor/groonga/plugins/table/table.c
@@ -17,10 +17,10 @@
#include <string.h>
-#include "ctx.h"
-#include "db.h"
-#include "output.h"
-#include "util.h"
+#include "grn_ctx.h"
+#include "grn_db.h"
+#include "grn_output.h"
+#include "grn_util.h"
#include <groonga/plugin.h>
#define VAR GRN_PROC_GET_VAR_BY_OFFSET
diff --git a/storage/mroonga/vendor/groonga/plugins/token_filters/CMakeLists.txt b/storage/mroonga/vendor/groonga/plugins/token_filters/CMakeLists.txt
index 9ffe53d2e8d..a0b964fb659 100644
--- a/storage/mroonga/vendor/groonga/plugins/token_filters/CMakeLists.txt
+++ b/storage/mroonga/vendor/groonga/plugins/token_filters/CMakeLists.txt
@@ -29,6 +29,19 @@ set_target_properties(stop_word_token_filter PROPERTIES
PREFIX ""
OUTPUT_NAME "stop_word")
target_link_libraries(stop_word_token_filter libgroonga)
-if(NOT MRN_GROONGA_BUNDLED)
- install(TARGETS stop_word_token_filter DESTINATION "${TOKEN_FILTERS_DIR}")
+install(TARGETS stop_word_token_filter DESTINATION "${TOKEN_FILTERS_DIR}")
+
+if(GRN_WITH_LIBSTEMMER)
+ read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/stem_sources.am STEM_SOURCES)
+ include_directories(${LIBSTEMMER_INCLUDE_DIRS})
+ link_directories(${LIBSTEMMER_LIBRARY_DIRS})
+ add_library(stem_token_filter MODULE ${STEM_SOURCES})
+ set_source_files_properties(${STEM_SOURCES}
+ PROPERTIES
+ COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}")
+ set_target_properties(stem_token_filter PROPERTIES
+ PREFIX ""
+ OUTPUT_NAME "stem")
+ target_link_libraries(stem_token_filter libgroonga ${LIBSTEMMER_LIBRARIES})
+ install(TARGETS stem_token_filter DESTINATION "${TOKEN_FILTERS_DIR}")
endif()
diff --git a/storage/mroonga/vendor/groonga/plugins/token_filters/Makefile.am b/storage/mroonga/vendor/groonga/plugins/token_filters/Makefile.am
index 8d77466f053..c63bef7ac56 100644
--- a/storage/mroonga/vendor/groonga/plugins/token_filters/Makefile.am
+++ b/storage/mroonga/vendor/groonga/plugins/token_filters/Makefile.am
@@ -16,5 +16,13 @@ LIBS = \
token_filter_plugins_LTLIBRARIES =
token_filter_plugins_LTLIBRARIES += stop_word.la
+if WITH_LIBSTEMMER
+token_filter_plugins_LTLIBRARIES += stem.la
+endif
include stop_word_sources.am
+
+include stem_sources.am
+stem_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBSTEMMER_CFLAGS)
+stem_la_LIBADD = $(LIBS) $(LIBSTEMMER_LIBS)
+stem_la_LDFLAGS = $(AM_LDFLAGS) $(LIBSTEMMER_LDFLAGS)
diff --git a/storage/mroonga/vendor/groonga/plugins/token_filters/stem.c b/storage/mroonga/vendor/groonga/plugins/token_filters/stem.c
new file mode 100644
index 00000000000..010b8c91867
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/plugins/token_filters/stem.c
@@ -0,0 +1,275 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <grn_str.h>
+
+#include <groonga.h>
+#include <groonga/token_filter.h>
+
+#include <ctype.h>
+#include <string.h>
+
+#include <libstemmer.h>
+
+typedef struct {
+ struct sb_stemmer *stemmer;
+ grn_tokenizer_token token;
+ grn_obj buffer;
+} grn_stem_token_filter;
+
+static void *
+stem_init(grn_ctx *ctx, grn_obj *table, grn_token_mode mode)
+{
+ grn_stem_token_filter *token_filter;
+
+ token_filter = GRN_PLUGIN_MALLOC(ctx, sizeof(grn_stem_token_filter));
+ if (!token_filter) {
+ GRN_PLUGIN_ERROR(ctx, GRN_NO_MEMORY_AVAILABLE,
+ "[token-filter][stem] "
+ "failed to allocate grn_stem_token_filter");
+ return NULL;
+ }
+
+ {
+ /* TODO: Support other languages. */
+ const char *algorithm = "english";
+ const char *encoding = "UTF_8";
+ token_filter->stemmer = sb_stemmer_new(algorithm, encoding);
+ if (!token_filter->stemmer) {
+ GRN_PLUGIN_FREE(ctx, token_filter);
+ GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
+ "[token-filter][stem] "
+ "failed to create stemmer: "
+ "algorithm=<%s>, encoding=<%s>",
+ algorithm, encoding);
+ return NULL;
+ }
+ }
+ grn_tokenizer_token_init(ctx, &(token_filter->token));
+ GRN_TEXT_INIT(&(token_filter->buffer), 0);
+
+ return token_filter;
+}
+
+static grn_bool
+is_stemmable(grn_obj *data, grn_bool *is_all_upper)
+{
+ const char *current, *end;
+ grn_bool have_lower = GRN_FALSE;
+ grn_bool have_upper = GRN_FALSE;
+
+ *is_all_upper = GRN_FALSE;
+
+ switch (data->header.domain) {
+ case GRN_DB_SHORT_TEXT :
+ case GRN_DB_TEXT :
+ case GRN_DB_LONG_TEXT :
+ break;
+ default :
+ return GRN_FALSE;
+ }
+
+ current = GRN_TEXT_VALUE(data);
+ end = current + GRN_TEXT_LEN(data);
+
+ for (; current < end; current++) {
+ if (islower(*current)) {
+ have_lower = GRN_TRUE;
+ continue;
+ }
+ if (isupper(*current)) {
+ have_upper = GRN_TRUE;
+ continue;
+ }
+ if (isdigit(*current)) {
+ continue;
+ }
+ switch (*current) {
+ case '-' :
+ case '\'' :
+ break;
+ default :
+ return GRN_FALSE;
+ }
+ }
+
+ if (!have_lower && have_upper) {
+ *is_all_upper = GRN_TRUE;
+ }
+
+ return GRN_TRUE;
+}
+
+static void
+normalize(grn_ctx *ctx,
+ const char *string, unsigned int length,
+ grn_obj *normalized)
+{
+ const char *current, *end;
+ const char *unwritten;
+
+ current = unwritten = string;
+ end = current + length;
+
+ for (; current < end; current++) {
+ if (isupper(*current)) {
+ if (current > unwritten) {
+ GRN_TEXT_PUT(ctx, normalized, unwritten, current - unwritten);
+ }
+ GRN_TEXT_PUTC(ctx, normalized, tolower(*current));
+ unwritten = current + 1;
+ }
+ }
+
+ if (current != unwritten) {
+ GRN_TEXT_PUT(ctx, normalized, unwritten, current - unwritten);
+ }
+}
+
+static void
+unnormalize(grn_ctx *ctx,
+ const char *string, unsigned int length,
+ grn_obj *normalized)
+{
+ const char *current, *end;
+ const char *unwritten;
+
+ current = unwritten = string;
+ end = current + length;
+
+ for (; current < end; current++) {
+ if (islower(*current)) {
+ if (current > unwritten) {
+ GRN_TEXT_PUT(ctx, normalized, unwritten, current - unwritten);
+ }
+ GRN_TEXT_PUTC(ctx, normalized, toupper(*current));
+ unwritten = current + 1;
+ }
+ }
+
+ if (current != unwritten) {
+ GRN_TEXT_PUT(ctx, normalized, unwritten, current - unwritten);
+ }
+}
+
+static void
+stem_filter(grn_ctx *ctx,
+ grn_token *current_token,
+ grn_token *next_token,
+ void *user_data)
+{
+ grn_stem_token_filter *token_filter = user_data;
+ grn_obj *data;
+ grn_bool is_all_upper = GRN_FALSE;
+
+ if (GRN_CTX_GET_ENCODING(ctx) != GRN_ENC_UTF8) {
+ return;
+ }
+
+ data = grn_token_get_data(ctx, current_token);
+ if (!is_stemmable(data, &is_all_upper)) {
+ return;
+ }
+
+ {
+ const sb_symbol *stemmed;
+
+ if (is_all_upper) {
+ grn_obj *buffer;
+ buffer = &(token_filter->buffer);
+ GRN_BULK_REWIND(buffer);
+ normalize(ctx,
+ GRN_TEXT_VALUE(data),
+ GRN_TEXT_LEN(data),
+ buffer);
+ stemmed = sb_stemmer_stem(token_filter->stemmer,
+ GRN_TEXT_VALUE(buffer), GRN_TEXT_LEN(buffer));
+ if (stemmed) {
+ GRN_BULK_REWIND(buffer);
+ unnormalize(ctx,
+ stemmed,
+ sb_stemmer_length(token_filter->stemmer),
+ buffer);
+ grn_token_set_data(ctx, next_token,
+ GRN_TEXT_VALUE(buffer), GRN_TEXT_LEN(buffer));
+ } else {
+ GRN_PLUGIN_ERROR(ctx, GRN_NO_MEMORY_AVAILABLE,
+ "[token-filter][stem] "
+ "failed to allocate memory for stemmed word: <%.*s> "
+ "(normalized: <%.*s>)",
+ (int)GRN_TEXT_LEN(data), GRN_TEXT_VALUE(data),
+ (int)GRN_TEXT_LEN(buffer), GRN_TEXT_VALUE(buffer));
+ }
+ } else {
+ stemmed = sb_stemmer_stem(token_filter->stemmer,
+ GRN_TEXT_VALUE(data), GRN_TEXT_LEN(data));
+ if (stemmed) {
+ grn_token_set_data(ctx, next_token,
+ stemmed,
+ sb_stemmer_length(token_filter->stemmer));
+ } else {
+ GRN_PLUGIN_ERROR(ctx, GRN_NO_MEMORY_AVAILABLE,
+ "[token-filter][stem] "
+ "failed to allocate memory for stemmed word: <%.*s>",
+ (int)GRN_TEXT_LEN(data), GRN_TEXT_VALUE(data));
+ }
+ }
+ }
+}
+
+static void
+stem_fin(grn_ctx *ctx, void *user_data)
+{
+ grn_stem_token_filter *token_filter = user_data;
+ if (!token_filter) {
+ return;
+ }
+
+ grn_tokenizer_token_fin(ctx, &(token_filter->token));
+ if (token_filter->stemmer) {
+ sb_stemmer_delete(token_filter->stemmer);
+ }
+ GRN_OBJ_FIN(ctx, &(token_filter->buffer));
+ GRN_PLUGIN_FREE(ctx, token_filter);
+}
+
+grn_rc
+GRN_PLUGIN_INIT(grn_ctx *ctx)
+{
+ return ctx->rc;
+}
+
+grn_rc
+GRN_PLUGIN_REGISTER(grn_ctx *ctx)
+{
+ grn_rc rc;
+
+ rc = grn_token_filter_register(ctx,
+ "TokenFilterStem", -1,
+ stem_init,
+ stem_filter,
+ stem_fin);
+
+ return rc;
+}
+
+grn_rc
+GRN_PLUGIN_FIN(grn_ctx *ctx)
+{
+ return GRN_SUCCESS;
+}
diff --git a/storage/mroonga/vendor/groonga/plugins/token_filters/stem_sources.am b/storage/mroonga/vendor/groonga/plugins/token_filters/stem_sources.am
new file mode 100644
index 00000000000..d02a39526e2
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/plugins/token_filters/stem_sources.am
@@ -0,0 +1,2 @@
+stem_la_SOURCES = \
+ stem.c
diff --git a/storage/mroonga/vendor/groonga/plugins/token_filters/stop_word.c b/storage/mroonga/vendor/groonga/plugins/token_filters/stop_word.c
index 21451f00b25..9b8cc68200a 100644
--- a/storage/mroonga/vendor/groonga/plugins/token_filters/stop_word.c
+++ b/storage/mroonga/vendor/groonga/plugins/token_filters/stop_word.c
@@ -16,7 +16,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include <str.h>
+#include <grn_str.h>
#include <groonga.h>
#include <groonga/token_filter.h>
@@ -102,7 +102,7 @@ stop_word_filter(grn_ctx *ctx,
if (GRN_BOOL_VALUE(&(token_filter->value))) {
grn_tokenizer_status status;
status = grn_token_get_status(ctx, current_token);
- status |= GRN_TOKENIZER_TOKEN_SKIP;
+ status |= GRN_TOKEN_SKIP;
grn_token_set_status(ctx, next_token, status);
}
}
diff --git a/storage/mroonga/vendor/groonga/plugins/tokenizers/CMakeLists.txt b/storage/mroonga/vendor/groonga/plugins/tokenizers/CMakeLists.txt
index e044c1fbb93..5871e982211 100644
--- a/storage/mroonga/vendor/groonga/plugins/tokenizers/CMakeLists.txt
+++ b/storage/mroonga/vendor/groonga/plugins/tokenizers/CMakeLists.txt
@@ -30,9 +30,7 @@ if(GRN_WITH_MECAB)
PREFIX ""
OUTPUT_NAME "mecab")
target_link_libraries(mecab_tokenizer libgroonga ${MECAB_LIBRARIES})
- if(NOT MRN_GROONGA_BUNDLED)
- install(TARGETS mecab_tokenizer DESTINATION "${TOKENIZERS_DIR}")
- endif()
+ install(TARGETS mecab_tokenizer DESTINATION "${TOKENIZERS_DIR}")
endif()
if(GRN_WITH_KYTEA)
@@ -47,7 +45,5 @@ if(GRN_WITH_KYTEA)
PREFIX ""
OUTPUT_NAME "kytea")
target_link_libraries(kytea_tokenizer libgroonga ${KYTEA_LIBRARIES})
- if(NOT MRN_GROONGA_BUNDLED)
- install(TARGETS kytea_tokenizer DESTINATION "${TOKENIZERS_DIR}")
- endif()
+ install(TARGETS kytea_tokenizer DESTINATION "${TOKENIZERS_DIR}")
endif()
diff --git a/storage/mroonga/vendor/groonga/plugins/tokenizers/mecab.c b/storage/mroonga/vendor/groonga/plugins/tokenizers/mecab.c
index 4ac99f9a9e8..49e4b5c877e 100644
--- a/storage/mroonga/vendor/groonga/plugins/tokenizers/mecab.c
+++ b/storage/mroonga/vendor/groonga/plugins/tokenizers/mecab.c
@@ -1,5 +1,5 @@
/* -*- c-basic-offset: 2 -*- */
-/* Copyright(C) 2009-2012 Brazil
+/* Copyright(C) 2009-2015 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -15,13 +15,14 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include <str.h>
+#include <grn_str.h>
#include <groonga.h>
#include <groonga/tokenizer.h>
#include <mecab.h>
+#include <stdlib.h>
#include <string.h>
#include <ctype.h>
@@ -38,6 +39,21 @@ typedef struct {
grn_tokenizer_token token;
} grn_mecab_tokenizer;
+static const char *
+mecab_global_error_message(void)
+{
+ double version;
+
+ version = atof(mecab_version());
+ /* MeCab <= 0.993 doesn't support mecab_strerror(NULL). */
+ if (version <= 0.993) {
+ return "Unknown";
+ }
+
+ return mecab_strerror(NULL);
+}
+
+
static grn_encoding
translate_mecab_charset_to_grn_encoding(const char *charset)
{
@@ -96,7 +112,7 @@ mecab_init(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
GRN_PLUGIN_ERROR(ctx, GRN_TOKENIZER_ERROR,
"[tokenizer][mecab] "
"mecab_new2() failed on mecab_init(): %s",
- mecab_strerror(NULL));
+ mecab_global_error_message());
} else {
sole_mecab_encoding = get_mecab_encoding(sole_mecab);
}
@@ -273,7 +289,7 @@ check_mecab_dictionary_encoding(grn_ctx *ctx)
GRN_PLUGIN_ERROR(ctx, GRN_TOKENIZER_ERROR,
"[tokenizer][mecab] "
"mecab_new2 failed in check_mecab_dictionary_encoding: %s",
- mecab_strerror(NULL));
+ mecab_global_error_message());
}
#endif
}
diff --git a/storage/mroonga/vendor/groonga/src/CMakeLists.txt b/storage/mroonga/vendor/groonga/src/CMakeLists.txt
index 4d02109dae5..258d1866c2b 100644
--- a/storage/mroonga/vendor/groonga/src/CMakeLists.txt
+++ b/storage/mroonga/vendor/groonga/src/CMakeLists.txt
@@ -25,9 +25,7 @@ set_source_files_properties(${GROONGA_SOURCES}
PROPERTIES
COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}")
target_link_libraries(groonga libgroonga)
-if(NOT MRN_GROONGA_BUNDLED)
- install(TARGETS groonga DESTINATION ${BIN_DIR})
-endif()
+install(TARGETS groonga DESTINATION ${BIN_DIR})
if(NOT WIN32)
read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/grnslap_sources.am GRNSLAP_SOURCES)
@@ -36,9 +34,7 @@ if(NOT WIN32)
PROPERTIES
COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}")
target_link_libraries(grnslap libgroonga)
- if(NOT MRN_GROONGA_BUNDLED)
- install(TARGETS grnslap DESTINATION ${BIN_DIR})
- endif()
+ install(TARGETS grnslap DESTINATION ${BIN_DIR})
endif()
read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/groonga_benchmark_sources.am
@@ -48,7 +44,5 @@ set_source_files_properties(${GROONGA_BENCHMARK_SOURCES}
PROPERTIES
COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}")
target_link_libraries(groonga-benchmark libgroonga)
-if(NOT MRN_GROONGA_BUNDLED)
- install(TARGETS groonga-benchmark DESTINATION ${BIN_DIR})
-endif()
+install(TARGETS groonga-benchmark DESTINATION ${BIN_DIR})
diff --git a/storage/mroonga/vendor/groonga/src/Makefile.am b/storage/mroonga/vendor/groonga/src/Makefile.am
index b125db54c3d..a4d57e85c44 100644
--- a/storage/mroonga/vendor/groonga/src/Makefile.am
+++ b/storage/mroonga/vendor/groonga/src/Makefile.am
@@ -6,6 +6,10 @@ NONEXISTENT_CXX_SOURCE = nonexistent.cpp
bin_PROGRAMS = groonga groonga-benchmark
noinst_PROGRAMS = grnslap
+if WITH_MRUBY
+bin_PROGRAMS += grndb
+noinst_PROGRAMS += groonga-mruby
+endif
EXTRA_DIST = \
CMakeLists.txt
@@ -22,9 +26,8 @@ AM_LDFLAGS = -no-undefined
DEFAULT_INCLUDES = \
-I$(top_builddir) \
- -I$(srcdir) \
- -I$(top_srcdir) \
-I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib \
$(GROONGA_INCLUDEDIR)
include groonga_sources.am
@@ -46,3 +49,15 @@ nodist_EXTRA_groonga_benchmark_SOURCES = $(NONEXISTENT_CXX_SOURCE)
groonga_benchmark_LDADD = \
$(top_builddir)/lib/libgroonga.la \
$(MESSAGE_PACK_LIBS)
+
+include grndb_sources.am
+nodist_EXTRA_grndb_SOURCES = $(NONEXISTENT_CXX_SOURCE)
+grndb_LDADD = \
+ $(top_builddir)/lib/libgroonga.la \
+ $(MESSAGE_PACK_LIBS)
+
+include groonga_mruby_sources.am
+nodist_EXTRA_groonga_mruby_SOURCES = $(NONEXISTENT_CXX_SOURCE)
+groonga_mruby_LDADD = \
+ $(top_builddir)/lib/libgroonga.la \
+ $(MESSAGE_PACK_LIBS)
diff --git a/storage/mroonga/vendor/groonga/src/grndb.c b/storage/mroonga/vendor/groonga/src/grndb.c
new file mode 100644
index 00000000000..d493338f57e
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/src/grndb.c
@@ -0,0 +1,137 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifdef WIN32
+# define GROONGA_MAIN
+#endif /* WIN32 */
+
+#include <grn_mrb.h>
+#include <grn_ctx_impl.h>
+
+#include <mruby/variable.h>
+#include <mruby/array.h>
+
+static int
+run_command(grn_ctx *ctx, int argc, char **argv)
+{
+ int exit_code = EXIT_SUCCESS;
+ grn_mrb_data *data = &(ctx->impl->mrb);
+ mrb_state *mrb = data->state;
+ mrb_value mrb_command_line_module;
+ mrb_value mrb_grndb_class;
+
+ mrb_command_line_module = mrb_const_get(mrb,
+ mrb_obj_value(data->module),
+ mrb_intern_cstr(mrb, "CommandLine"));
+ if (mrb->exc) {
+ goto exit;
+ }
+
+ mrb_grndb_class = mrb_const_get(mrb,
+ mrb_command_line_module,
+ mrb_intern_cstr(mrb, "Grndb"));
+ if (mrb->exc) {
+ goto exit;
+ }
+
+ {
+ int i;
+ mrb_value mrb_argv;
+ mrb_value mrb_grndb;
+ mrb_value mrb_result;
+
+ mrb_argv = mrb_ary_new_capa(mrb, argc);
+ for (i = 0; i < argc; i++) {
+ mrb_ary_push(mrb, mrb_argv, mrb_str_new_cstr(mrb, argv[i]));
+ }
+ mrb_grndb = mrb_funcall(mrb, mrb_grndb_class, "new", 1, mrb_argv);
+ if (mrb->exc) {
+ goto exit;
+ }
+
+ mrb_result = mrb_funcall(mrb, mrb_grndb, "run", 0);
+ if (mrb->exc) {
+ goto exit;
+ }
+
+ if (!mrb_bool(mrb_result)) {
+ exit_code = EXIT_FAILURE;
+ }
+ }
+
+exit :
+ if (mrb->exc) {
+ mrb_print_error(mrb);
+ exit_code = EXIT_FAILURE;
+ }
+
+ return exit_code;
+}
+
+static int
+run(grn_ctx *ctx, int argc, char **argv)
+{
+ int exit_code = EXIT_SUCCESS;
+ const char *grndb_rb = "command_line/grndb.rb";
+ grn_mrb_data *data = &(ctx->impl->mrb);
+ mrb_state *mrb = data->state;
+
+ mrb_gv_set(mrb, mrb_intern_lit(mrb, "$0"), mrb_str_new_cstr(mrb, argv[0]));
+
+ grn_mrb_load(ctx, grndb_rb);
+ if (ctx->rc != GRN_SUCCESS) {
+ fprintf(stderr, "Failed to load Ruby script: <%s>: %s",
+ grndb_rb, ctx->errbuf);
+ goto exit;
+ }
+
+ {
+ int arena_index;
+
+ arena_index = mrb_gc_arena_save(mrb);
+ exit_code = run_command(ctx, argc, argv);
+ mrb_gc_arena_restore(mrb, arena_index);
+ }
+
+exit :
+ if (ctx->rc != GRN_SUCCESS) {
+ exit_code = EXIT_FAILURE;
+ }
+ return exit_code;
+}
+
+int
+main(int argc, char **argv)
+{
+ int exit_code = EXIT_SUCCESS;
+
+ if (grn_init() != GRN_SUCCESS) {
+ return EXIT_FAILURE;
+ }
+
+ {
+ grn_ctx ctx;
+ grn_ctx_init(&ctx, 0);
+ exit_code = run(&ctx, argc, argv);
+ grn_ctx_fin(&ctx);
+ }
+
+ grn_fin();
+
+ return exit_code;
+}
diff --git a/storage/mroonga/vendor/groonga/src/grndb_sources.am b/storage/mroonga/vendor/groonga/src/grndb_sources.am
new file mode 100644
index 00000000000..ce2e2bb3466
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/src/grndb_sources.am
@@ -0,0 +1,2 @@
+grndb_SOURCES = \
+ grndb.c
diff --git a/storage/mroonga/vendor/groonga/src/grnslap.c b/storage/mroonga/vendor/groonga/src/grnslap.c
index 5400fbb23e0..be2f181f3e7 100644
--- a/storage/mroonga/vendor/groonga/src/grnslap.c
+++ b/storage/mroonga/vendor/groonga/src/grnslap.c
@@ -16,8 +16,8 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "lib/com.h"
-#include "lib/ctx_impl.h"
+#include <grn_com.h>
+#include <grn_ctx_impl.h>
#include <string.h>
#include <stdio.h>
#ifdef HAVE_SYS_WAIT_H
@@ -196,7 +196,7 @@ msg_handler(grn_ctx *ctx, grn_obj *msg)
grn_msg_close(ctx, msg);
}
-static void * CALLBACK
+static grn_thread_func_result CALLBACK
receiver(void *arg)
{
grn_ctx ctx_, *ctx = &ctx_;
@@ -213,7 +213,7 @@ receiver(void *arg)
*/
}
grn_ctx_fin(ctx);
- return NULL;
+ return GRN_THREAD_FUNC_RETURN_VALUE;
}
static int
diff --git a/storage/mroonga/vendor/groonga/src/groonga.c b/storage/mroonga/vendor/groonga/src/groonga.c
index 9d1009d72da..b03e70e0258 100644
--- a/storage/mroonga/vendor/groonga/src/groonga.c
+++ b/storage/mroonga/vendor/groonga/src/groonga.c
@@ -1,6 +1,6 @@
/* -*- c-basic-offset: 2 -*- */
/*
- Copyright(C) 2009-2014 Brazil
+ Copyright(C) 2009-2015 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -16,20 +16,22 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifdef WIN32
-# define GROONGA_MAIN
-#endif /* WIN32 */
-#include "lib/groonga_in.h"
-
-#include "lib/com.h"
-#include "lib/ctx_impl.h"
-#include "lib/proc.h"
-#include "lib/db.h"
-#include "lib/util.h"
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>
+
+#ifdef WIN32
+# define GROONGA_MAIN
+#endif /* WIN32 */
+#include <grn.h>
+
+#include <grn_com.h>
+#include <grn_ctx_impl.h>
+#include <grn_proc.h>
+#include <grn_db.h>
+#include <grn_util.h>
+
#ifdef HAVE_SYS_WAIT_H
# include <sys/wait.h>
#endif /* HAVE_SYS_WAIT_H */
@@ -48,7 +50,14 @@
# include <sys/sysctl.h>
#endif /* HAVE_SYS_SYSCTL_H */
+#ifdef HAVE_IO_H
+# include <io.h>
+#endif /* HAVE_IO_H */
+
#ifdef HAVE__STRNICMP
+# ifdef strncasecmp
+# undef strncasecmp
+# endif /* strcasecmp */
# define strncasecmp(s1,s2,n) _strnicmp(s1,s2,n)
#endif /* HAVE__STRNICMP */
@@ -210,6 +219,7 @@ read_next_line(grn_ctx *ctx, grn_obj *buf)
rc = line_editor_fgets(ctx, buf);
#else
fprintf(stderr, "> ");
+ fflush(stderr);
rc = grn_text_fgets(ctx, buf, stdin);
#endif
} else {
@@ -271,31 +281,73 @@ output_envelope(grn_ctx *ctx, grn_rc rc, grn_obj *head, grn_obj *body, grn_obj *
}
static void
-s_output(grn_ctx *ctx, int flags, void *arg)
+s_output_raw(grn_ctx *ctx, int flags, FILE *stream)
+{
+ char *chunk = NULL;
+ unsigned int chunk_size = 0;
+ int recv_flags;
+
+ grn_ctx_recv(ctx, &chunk, &chunk_size, &recv_flags);
+ if (chunk_size > 0) {
+ fwrite(chunk, 1, chunk_size, stream);
+ }
+
+ if (flags & GRN_CTX_TAIL) {
+ grn_obj *command;
+
+ fflush(stream);
+
+ command = GRN_CTX_USER_DATA(ctx)->ptr;
+ GRN_BULK_REWIND(command);
+ }
+}
+
+static void
+s_output_typed(grn_ctx *ctx, int flags, FILE *stream)
{
if (ctx && ctx->impl && (flags & GRN_CTX_TAIL)) {
- grn_obj *buf = ctx->impl->outbuf;
+ char *chunk = NULL;
+ unsigned int chunk_size = 0;
+ int recv_flags;
+ grn_obj body;
grn_obj *command;
- if (GRN_TEXT_LEN(buf) || ctx->rc) {
- FILE * stream = (FILE *) arg;
+
+ GRN_TEXT_INIT(&body, 0);
+ grn_ctx_recv(ctx, &chunk, &chunk_size, &recv_flags);
+ GRN_TEXT_SET(ctx, &body, chunk, chunk_size);
+
+ if (GRN_TEXT_LEN(&body) || ctx->rc) {
grn_obj head, foot;
GRN_TEXT_INIT(&head, 0);
GRN_TEXT_INIT(&foot, 0);
- output_envelope(ctx, ctx->rc, &head, buf, &foot);
+ output_envelope(ctx, ctx->rc, &head, &body, &foot);
fwrite(GRN_TEXT_VALUE(&head), 1, GRN_TEXT_LEN(&head), stream);
- fwrite(GRN_TEXT_VALUE(buf), 1, GRN_TEXT_LEN(buf), stream);
+ fwrite(GRN_TEXT_VALUE(&body), 1, GRN_TEXT_LEN(&body), stream);
fwrite(GRN_TEXT_VALUE(&foot), 1, GRN_TEXT_LEN(&foot), stream);
fputc('\n', stream);
fflush(stream);
- GRN_BULK_REWIND(buf);
GRN_OBJ_FIN(ctx, &head);
GRN_OBJ_FIN(ctx, &foot);
}
+ GRN_OBJ_FIN(ctx, &body);
+
command = GRN_CTX_USER_DATA(ctx)->ptr;
GRN_BULK_REWIND(command);
}
}
+static void
+s_output(grn_ctx *ctx, int flags, void *arg)
+{
+ FILE *stream = (FILE *)arg;
+
+ if (grn_ctx_get_output_type(ctx) == GRN_CONTENT_NONE) {
+ s_output_raw(ctx, flags, stream);
+ } else {
+ s_output_typed(ctx, flags, stream);
+ }
+}
+
static int
do_alone(int argc, char **argv)
{
@@ -584,7 +636,7 @@ run_server(grn_ctx *ctx, grn_obj *db, grn_com_event *ev,
struct hostent *he;
if (!(he = gethostbyname(hostname))) {
send_ready_notify();
- SERR("gethostbyname");
+ SOERR("gethostbyname");
} else {
ev->opaque = db;
grn_edges_init(ctx, dispatcher);
@@ -643,94 +695,255 @@ start_service(grn_ctx *ctx, const char *db_path,
typedef struct {
grn_msg *msg;
+ grn_bool in_body;
+ grn_bool is_chunked;
} ht_context;
static void
-h_output(grn_ctx *ctx, int flags, void *arg)
+h_output_set_header(grn_ctx *ctx, grn_obj *header,
+ grn_rc rc, long long int content_length)
{
- grn_rc expr_rc = ctx->rc;
- ht_context *hc = (ht_context *)arg;
- grn_sock fd = hc->msg->u.fd;
- grn_obj header, head, foot, *outbuf = ctx->impl->outbuf;
- if (!(flags & GRN_CTX_TAIL)) { return; }
- GRN_TEXT_INIT(&header, 0);
- GRN_TEXT_INIT(&head, 0);
- GRN_TEXT_INIT(&foot, 0);
- output_envelope(ctx, expr_rc, &head, outbuf, &foot);
- switch (expr_rc) {
+ switch (rc) {
case GRN_SUCCESS :
- GRN_TEXT_SETS(ctx, &header, "HTTP/1.1 200 OK\r\n");
+ GRN_TEXT_SETS(ctx, header, "HTTP/1.1 200 OK\r\n");
break;
case GRN_INVALID_ARGUMENT :
case GRN_SYNTAX_ERROR :
- GRN_TEXT_SETS(ctx, &header, "HTTP/1.1 400 Bad Request\r\n");
+ GRN_TEXT_SETS(ctx, header, "HTTP/1.1 400 Bad Request\r\n");
break;
case GRN_NO_SUCH_FILE_OR_DIRECTORY :
- GRN_TEXT_SETS(ctx, &header, "HTTP/1.1 404 Not Found\r\n");
+ GRN_TEXT_SETS(ctx, header, "HTTP/1.1 404 Not Found\r\n");
break;
default :
- GRN_TEXT_SETS(ctx, &header, "HTTP/1.1 500 Internal Server Error\r\n");
+ GRN_TEXT_SETS(ctx, header, "HTTP/1.1 500 Internal Server Error\r\n");
break;
}
- GRN_TEXT_PUTS(ctx, &header, "Connection: close\r\n");
- GRN_TEXT_PUTS(ctx, &header, "Content-Type: ");
- GRN_TEXT_PUTS(ctx, &header, grn_ctx_get_mime_type(ctx));
- GRN_TEXT_PUTS(ctx, &header, "\r\nContent-Length: ");
- grn_text_lltoa(ctx, &header,
- GRN_TEXT_LEN(&head) + GRN_TEXT_LEN(outbuf) + GRN_TEXT_LEN(&foot));
- GRN_TEXT_PUTS(ctx, &header, "\r\n\r\n");
- {
- ssize_t ret, len;
+ GRN_TEXT_PUTS(ctx, header, "Content-Type: ");
+ GRN_TEXT_PUTS(ctx, header, grn_ctx_get_mime_type(ctx));
+ GRN_TEXT_PUTS(ctx, header, "\r\n");
+ if (content_length >= 0) {
+ GRN_TEXT_PUTS(ctx, header, "Connection: close\r\n");
+ GRN_TEXT_PUTS(ctx, header, "Content-Length: ");
+ grn_text_lltoa(ctx, header, content_length);
+ GRN_TEXT_PUTS(ctx, header, "\r\n");
+ } else {
+ GRN_TEXT_PUTS(ctx, header, "Transfer-Encoding: chunked\r\n");
+ }
+ GRN_TEXT_PUTS(ctx, header, "\r\n");
+}
+
+static void
+h_output_send(grn_ctx *ctx, grn_sock fd,
+ grn_obj *header, grn_obj *head, grn_obj *body, grn_obj *foot)
+{
+ ssize_t ret;
+ ssize_t len = 0;
#ifdef WIN32
- WSABUF wsabufs[4];
- wsabufs[0].buf = GRN_TEXT_VALUE(&header);
- wsabufs[0].len = GRN_TEXT_LEN(&header);
- wsabufs[1].buf = GRN_TEXT_VALUE(&head);
- wsabufs[1].len = GRN_TEXT_LEN(&head);
- wsabufs[2].buf = GRN_TEXT_VALUE(outbuf);
- wsabufs[2].len = GRN_TEXT_LEN(outbuf);
- wsabufs[3].buf = GRN_TEXT_VALUE(&foot);
- wsabufs[3].len = GRN_TEXT_LEN(&foot);
- if (WSASend(fd, wsabufs, 4, &ret, 0, NULL, NULL) == SOCKET_ERROR) {
- SERR("WSASend");
+ int n_buffers = 0;
+ WSABUF wsabufs[4];
+ if (header) {
+ wsabufs[n_buffers].buf = GRN_TEXT_VALUE(header);
+ wsabufs[n_buffers].len = GRN_TEXT_LEN(header);
+ len += GRN_TEXT_LEN(header);
+ n_buffers++;
+ }
+ if (head) {
+ wsabufs[n_buffers].buf = GRN_TEXT_VALUE(head);
+ wsabufs[n_buffers].len = GRN_TEXT_LEN(head);
+ len += GRN_TEXT_LEN(head);
+ n_buffers++;
+ }
+ if (body) {
+ wsabufs[n_buffers].buf = GRN_TEXT_VALUE(body);
+ wsabufs[n_buffers].len = GRN_TEXT_LEN(body);
+ len += GRN_TEXT_LEN(body);
+ n_buffers++;
+ }
+ if (foot) {
+ wsabufs[n_buffers].buf = GRN_TEXT_VALUE(foot);
+ wsabufs[n_buffers].len = GRN_TEXT_LEN(foot);
+ len += GRN_TEXT_LEN(foot);
+ n_buffers++;
+ }
+ {
+ DWORD sent;
+ if (WSASend(fd, wsabufs, n_buffers, &sent, 0, NULL, NULL) == SOCKET_ERROR) {
+ SOERR("WSASend");
}
+ ret = sent;
+ }
#else /* WIN32 */
- struct iovec msg_iov[4];
- struct msghdr msg;
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_iov = msg_iov;
- msg.msg_iovlen = 4;
- msg.msg_control = NULL;
- msg.msg_controllen = 0;
- msg.msg_flags = 0;
- msg_iov[0].iov_base = GRN_TEXT_VALUE(&header);
- msg_iov[0].iov_len = GRN_TEXT_LEN(&header);
- msg_iov[1].iov_base = GRN_TEXT_VALUE(&head);
- msg_iov[1].iov_len = GRN_TEXT_LEN(&head);
- msg_iov[2].iov_base = GRN_TEXT_VALUE(outbuf);
- msg_iov[2].iov_len = GRN_TEXT_LEN(outbuf);
- msg_iov[3].iov_base = GRN_TEXT_VALUE(&foot);
- msg_iov[3].iov_len = GRN_TEXT_LEN(&foot);
- if ((ret = sendmsg(fd, &msg, MSG_NOSIGNAL)) == -1) {
- SERR("sendmsg");
- }
+ struct iovec msg_iov[4];
+ struct msghdr msg;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = msg_iov;
+ msg.msg_iovlen = 0;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ msg.msg_flags = 0;
+
+ if (header) {
+ msg_iov[msg.msg_iovlen].iov_base = GRN_TEXT_VALUE(header);
+ msg_iov[msg.msg_iovlen].iov_len = GRN_TEXT_LEN(header);
+ len += GRN_TEXT_LEN(header);
+ msg.msg_iovlen++;
+ }
+ if (head) {
+ msg_iov[msg.msg_iovlen].iov_base = GRN_TEXT_VALUE(head);
+ msg_iov[msg.msg_iovlen].iov_len = GRN_TEXT_LEN(head);
+ len += GRN_TEXT_LEN(head);
+ msg.msg_iovlen++;
+ }
+ if (body) {
+ msg_iov[msg.msg_iovlen].iov_base = GRN_TEXT_VALUE(body);
+ msg_iov[msg.msg_iovlen].iov_len = GRN_TEXT_LEN(body);
+ len += GRN_TEXT_LEN(body);
+ msg.msg_iovlen++;
+ }
+ if (foot) {
+ msg_iov[msg.msg_iovlen].iov_base = GRN_TEXT_VALUE(foot);
+ msg_iov[msg.msg_iovlen].iov_len = GRN_TEXT_LEN(foot);
+ len += GRN_TEXT_LEN(foot);
+ msg.msg_iovlen++;
+ }
+ if ((ret = sendmsg(fd, &msg, MSG_NOSIGNAL)) == -1) {
+ SOERR("sendmsg");
+ }
#endif /* WIN32 */
- len = GRN_TEXT_LEN(&header) + GRN_TEXT_LEN(&head) +
- GRN_TEXT_LEN(outbuf) + GRN_TEXT_LEN(&foot);
- if (ret != len) {
- GRN_LOG(&grn_gctx, GRN_LOG_NOTICE,
- "couldn't send all data (%" GRN_FMT_LLD "/%" GRN_FMT_LLD ")",
- (long long int)ret, (long long int)len);
+ if (ret != len) {
+ GRN_LOG(&grn_gctx, GRN_LOG_NOTICE,
+ "couldn't send all data (%" GRN_FMT_LLD "/%" GRN_FMT_LLD ")",
+ (long long int)ret, (long long int)len);
+ }
+}
+
+static void
+h_output_raw(grn_ctx *ctx, int flags, ht_context *hc)
+{
+ grn_rc expr_rc = ctx->rc;
+ grn_sock fd = hc->msg->u.fd;
+ grn_obj header_;
+ grn_obj head_;
+ grn_obj body_;
+ grn_obj foot_;
+ grn_obj *header = NULL;
+ grn_obj *head = NULL;
+ grn_obj *body = NULL;
+ grn_obj *foot = NULL;
+ char *chunk = NULL;
+ unsigned int chunk_size = 0;
+ int recv_flags;
+ grn_bool is_last_message = (flags & GRN_CTX_TAIL);
+
+ GRN_TEXT_INIT(&header_, 0);
+ GRN_TEXT_INIT(&head_, 0);
+ GRN_TEXT_INIT(&body_, GRN_OBJ_DO_SHALLOW_COPY);
+ GRN_TEXT_INIT(&foot_, 0);
+
+ grn_ctx_recv(ctx, &chunk, &chunk_size, &recv_flags);
+ GRN_TEXT_SET(ctx, &body_, chunk, chunk_size);
+
+ if (!hc->in_body) {
+ if (is_last_message) {
+ h_output_set_header(ctx, &header_, expr_rc, GRN_TEXT_LEN(&body_));
+ hc->is_chunked = GRN_FALSE;
+ } else {
+ h_output_set_header(ctx, &header_, expr_rc, -1);
+ hc->is_chunked = GRN_TRUE;
+ }
+ header = &header_;
+ hc->in_body = GRN_TRUE;
+ }
+
+ if (GRN_TEXT_LEN(&body_) > 0) {
+ if (hc->is_chunked) {
+ grn_text_printf(ctx, &head_,
+ "%x\r\n", (unsigned int)GRN_TEXT_LEN(&body_));
+ head = &head_;
+ GRN_TEXT_PUTS(ctx, &foot_, "\r\n");
+ foot = &foot_;
}
+ body = &body_;
+ }
+
+ if (is_last_message) {
+ if (hc->is_chunked) {
+ GRN_TEXT_PUTS(ctx, &foot_, "0\r\n");
+ GRN_TEXT_PUTS(ctx, &foot_, "Connection: close\r\n");
+ GRN_TEXT_PUTS(ctx, &foot_, "\r\n");
+ foot = &foot_;
+ }
+ }
+
+ h_output_send(ctx, fd, header, head, body, foot);
+
+ GRN_OBJ_FIN(ctx, &foot_);
+ GRN_OBJ_FIN(ctx, &body_);
+ GRN_OBJ_FIN(ctx, &head_);
+ GRN_OBJ_FIN(ctx, &header_);
+}
+
+static void
+h_output_typed(grn_ctx *ctx, int flags, ht_context *hc)
+{
+ grn_rc expr_rc = ctx->rc;
+ grn_sock fd = hc->msg->u.fd;
+ grn_obj header, head, body, foot;
+ char *chunk = NULL;
+ unsigned int chunk_size = 0;
+ int recv_flags;
+ grn_bool should_return_body;
+
+ if (!(flags & GRN_CTX_TAIL)) { return; }
+
+ switch (hc->msg->header.qtype) {
+ case 'G' :
+ case 'P' :
+ should_return_body = GRN_TRUE;
+ break;
+ default :
+ should_return_body = GRN_FALSE;
+ break;
+ }
+
+ GRN_TEXT_INIT(&header, 0);
+ GRN_TEXT_INIT(&head, 0);
+ GRN_TEXT_INIT(&body, 0);
+ GRN_TEXT_INIT(&foot, 0);
+
+ grn_ctx_recv(ctx, &chunk, &chunk_size, &recv_flags);
+ GRN_TEXT_SET(ctx, &body, chunk, chunk_size);
+
+ output_envelope(ctx, expr_rc, &head, &body, &foot);
+ h_output_set_header(ctx, &header, expr_rc,
+ GRN_TEXT_LEN(&head) +
+ GRN_TEXT_LEN(&body) +
+ GRN_TEXT_LEN(&foot));
+ if (should_return_body) {
+ h_output_send(ctx, fd, &header, &head, &body, &foot);
+ } else {
+ h_output_send(ctx, fd, &header, NULL, NULL, NULL);
}
- GRN_BULK_REWIND(outbuf);
GRN_OBJ_FIN(ctx, &foot);
+ GRN_OBJ_FIN(ctx, &body);
GRN_OBJ_FIN(ctx, &head);
GRN_OBJ_FIN(ctx, &header);
}
static void
+h_output(grn_ctx *ctx, int flags, void *arg)
+{
+ ht_context *hc = (ht_context *)arg;
+
+ if (grn_ctx_get_output_type(ctx) == GRN_CONTENT_NONE) {
+ h_output_raw(ctx, flags, hc);
+ } else {
+ h_output_typed(ctx, flags, hc);
+ }
+}
+
+static void
do_htreq_get(grn_ctx *ctx, grn_msg *msg)
{
char *path = NULL;
@@ -923,10 +1136,6 @@ do_htreq_post_parse_header(grn_ctx *ctx,
return GRN_FALSE;
}
- if (!header->have_100_continue && current == end) {
- return GRN_FALSE;
- }
-
if (current == end) {
header->body_start = NULL;
} else {
@@ -961,6 +1170,8 @@ do_htreq_post(grn_ctx *ctx, grn_msg *msg)
if (ctx->rc != GRN_SUCCESS) {
ht_context context;
context.msg = msg;
+ context.in_body = GRN_FALSE;
+ context.is_chunked = GRN_FALSE;
h_output(ctx, GRN_CTX_TAIL, &context);
return;
}
@@ -971,7 +1182,7 @@ do_htreq_post(grn_ctx *ctx, grn_msg *msg)
int send_flags = MSG_NOSIGNAL;
send_size = send(fd, continue_message, strlen(continue_message), send_flags);
if (send_size == -1) {
- SERR("send");
+ SOERR("send");
return;
}
}
@@ -999,7 +1210,7 @@ do_htreq_post(grn_ctx *ctx, grn_msg *msg)
break;
}
if (recv_length == -1) {
- SERR("recv");
+ SOERR("recv");
break;
}
buffer_start = buffer;
@@ -1052,15 +1263,13 @@ do_htreq(grn_ctx *ctx, grn_msg *msg)
grn_com_header *header = &msg->header;
switch (header->qtype) {
case 'G' : /* GET */
+ case 'H' : /* HEAD */
do_htreq_get(ctx, msg);
break;
case 'P' : /* POST */
do_htreq_post(ctx, msg);
break;
}
- /* TODO: support "Connection: keep-alive" */
- ctx->stat = GRN_CTX_QUIT;
- /* TODO: support a command in multi requests. e.g.: load command */
grn_ctx_set_next_expr(ctx, NULL);
/* if (ctx->rc != GRN_OPERATION_WOULD_BLOCK) {...} */
grn_msg_close(ctx, (grn_obj *)msg);
@@ -1653,7 +1862,7 @@ check_rlimit_nofile(grn_ctx *ctx)
#endif /* WIN32 */
}
-static void * CALLBACK
+static grn_thread_func_result CALLBACK
h_worker(void *arg)
{
ht_context hc;
@@ -1676,6 +1885,8 @@ h_worker(void *arg)
nfthreads--;
MUTEX_UNLOCK(q_mutex);
hc.msg = (grn_msg *)msg;
+ hc.in_body = GRN_FALSE;
+ hc.is_chunked = GRN_FALSE;
do_htreq(ctx, (grn_msg *)msg);
MUTEX_LOCK(q_mutex);
} while (nfthreads < max_nfthreads && grn_gctx.stat != GRN_CTX_QUIT);
@@ -1684,7 +1895,7 @@ exit :
MUTEX_UNLOCK(q_mutex);
GRN_LOG(&grn_gctx, GRN_LOG_NOTICE, "thread end (%d/%d)", nfthreads, nthreads);
grn_ctx_fin(ctx);
- return NULL;
+ return GRN_THREAD_FUNC_RETURN_VALUE;
}
static void
@@ -1729,7 +1940,7 @@ h_server(char *path)
return exit_code;
}
-static void * CALLBACK
+static grn_thread_func_result CALLBACK
g_worker(void *arg)
{
GRN_LOG(&grn_gctx, GRN_LOG_NOTICE, "thread start (%d/%d)", nfthreads, nthreads + 1);
@@ -1790,7 +2001,7 @@ exit :
nthreads--;
MUTEX_UNLOCK(q_mutex);
GRN_LOG(&grn_gctx, GRN_LOG_NOTICE, "thread end (%d/%d)", nfthreads, nthreads);
- return NULL;
+ return GRN_THREAD_FUNC_RETURN_VALUE;
}
static void
@@ -1891,18 +2102,18 @@ g_server(char *path)
}
enum {
- mode_alone = 0,
- mode_client,
- mode_daemon,
- mode_server,
- mode_usage,
- mode_version,
- mode_config,
- mode_error
+ ACTION_USAGE = 1,
+ ACTION_VERSION,
+ ACTION_SHOW_CONFIG,
+ ACTION_ERROR
};
-#define MODE_MASK 0x007f
-#define MODE_NEW_DB 0x0100
+#define ACTION_MASK (0x0f)
+#define FLAG_MODE_ALONE (1 << 4)
+#define FLAG_MODE_CLIENT (1 << 5)
+#define FLAG_MODE_DAEMON (1 << 6)
+#define FLAG_MODE_SERVER (1 << 7)
+#define FLAG_NEW_DB (1 << 8)
static uint32_t
get_core_number(void)
@@ -2123,7 +2334,6 @@ static const int default_http_port = DEFAULT_HTTP_PORT;
static const int default_gqtp_port = DEFAULT_GQTP_PORT;
static grn_encoding default_encoding = GRN_ENC_DEFAULT;
static uint32_t default_max_num_threads = DEFAULT_MAX_NFTHREADS;
-static const int default_mode = mode_alone;
static const int default_log_level = GRN_LOG_DEFAULT_LEVEL;
static const char * const default_protocol = "gqtp";
static const char *default_hostname = "localhost";
@@ -2277,8 +2487,8 @@ show_version(void)
#ifdef GRN_WITH_ZLIB
printf(",zlib");
#endif
-#ifdef GRN_WITH_LZO
- printf(",lzo");
+#ifdef GRN_WITH_LZ4
+ printf(",lz4");
#endif
#ifdef USE_KQUEUE
printf(",kqueue");
@@ -2397,26 +2607,27 @@ main(int argc, char **argv)
*working_directory_arg = NULL;
const char *config_path = NULL;
int exit_code = EXIT_SUCCESS;
- int i, mode = mode_alone;
+ int i;
+ int flags = 0;
uint32_t cache_limit = 0;
static grn_str_getopt_opt opts[] = {
{'p', "port", NULL, 0, GETOPT_OP_NONE},
{'e', "encoding", NULL, 0, GETOPT_OP_NONE},
{'t', "max-threads", NULL, 0, GETOPT_OP_NONE},
- {'h', "help", NULL, mode_usage, GETOPT_OP_UPDATE},
- {'c', NULL, NULL, mode_client, GETOPT_OP_UPDATE},
- {'d', NULL, NULL, mode_daemon, GETOPT_OP_UPDATE},
- {'s', NULL, NULL, mode_server, GETOPT_OP_UPDATE},
+ {'h', "help", NULL, ACTION_USAGE, GETOPT_OP_UPDATE},
+ {'c', NULL, NULL, FLAG_MODE_CLIENT, GETOPT_OP_ON},
+ {'d', NULL, NULL, FLAG_MODE_DAEMON, GETOPT_OP_ON},
+ {'s', NULL, NULL, FLAG_MODE_SERVER, GETOPT_OP_ON},
{'l', "log-level", NULL, 0, GETOPT_OP_NONE},
{'i', "server-id", NULL, 0, GETOPT_OP_NONE},
- {'n', NULL, NULL, MODE_NEW_DB, GETOPT_OP_ON},
+ {'n', NULL, NULL, FLAG_NEW_DB, GETOPT_OP_ON},
{'\0', "protocol", NULL, 0, GETOPT_OP_NONE},
- {'\0', "version", NULL, mode_version, GETOPT_OP_UPDATE},
+ {'\0', "version", NULL, ACTION_VERSION, GETOPT_OP_UPDATE},
{'\0', "log-path", NULL, 0, GETOPT_OP_NONE},
{'\0', "query-log-path", NULL, 0, GETOPT_OP_NONE},
{'\0', "pid-path", NULL, 0, GETOPT_OP_NONE},
{'\0', "config-path", NULL, 0, GETOPT_OP_NONE},
- {'\0', "show-config", NULL, mode_config, GETOPT_OP_UPDATE},
+ {'\0', "show-config", NULL, ACTION_SHOW_CONFIG, GETOPT_OP_UPDATE},
{'\0', "cache-limit", NULL, 0, GETOPT_OP_NONE},
{'\0', "file", NULL, 0, GETOPT_OP_NONE},
{'\0', "document-root", NULL, 0, GETOPT_OP_NONE},
@@ -2453,14 +2664,14 @@ main(int argc, char **argv)
init_default_settings();
/* only for parsing --config-path. */
- i = grn_str_getopt(argc, argv, opts, &mode);
+ i = grn_str_getopt(argc, argv, opts, &flags);
if (i < 0) {
show_usage(stderr);
return EXIT_FAILURE;
}
if (config_path) {
- const config_file_status status = config_file_load(config_path, opts, &mode);
+ const config_file_status status = config_file_load(config_path, opts, &flags);
if (status == CONFIG_FILE_FOPEN_ERROR) {
fprintf(stderr, "%s: can't open config file: %s (%s)\n",
argv[0], config_path, strerror(errno));
@@ -2473,7 +2684,7 @@ main(int argc, char **argv)
}
} else if (*default_config_path) {
const config_file_status status =
- config_file_load(default_config_path, opts, &mode);
+ config_file_load(default_config_path, opts, &flags);
if (status != CONFIG_FILE_SUCCESS && status != CONFIG_FILE_FOPEN_ERROR) {
fprintf(stderr, "%s: failed to parse config file: %s (%s)\n",
argv[0], default_config_path,
@@ -2491,22 +2702,21 @@ main(int argc, char **argv)
}
/* ignore mode option in config file */
- mode = (mode == mode_error) ? default_mode :
- ((mode & ~MODE_MASK) | default_mode);
+ flags = (flags == ACTION_ERROR) ? 0 : (flags & ~ACTION_MASK);
- i = grn_str_getopt(argc, argv, opts, &mode);
- if (i < 0) { mode = mode_error; }
- switch (mode & MODE_MASK) {
- case mode_version :
+ i = grn_str_getopt(argc, argv, opts, &flags);
+ if (i < 0) { flags = ACTION_ERROR; }
+ switch (flags & ACTION_MASK) {
+ case ACTION_VERSION :
show_version();
return EXIT_SUCCESS;
- case mode_usage :
+ case ACTION_USAGE :
show_usage(output);
return EXIT_SUCCESS;
- case mode_config :
- show_config(output, opts, mode & ~MODE_MASK);
+ case ACTION_SHOW_CONFIG :
+ show_config(output, opts, flags & ~ACTION_MASK);
return EXIT_SUCCESS;
- case mode_error :
+ case ACTION_ERROR :
show_usage(stderr);
return EXIT_FAILURE;
}
@@ -2787,23 +2997,14 @@ main(int argc, char **argv)
grn_cache_set_max_n_entries(&grn_gctx, cache, cache_limit);
}
- newdb = (mode & MODE_NEW_DB);
- switch (mode & MODE_MASK) {
- case mode_alone :
- exit_code = do_alone(argc - i, argv + i);
- break;
- case mode_client :
+ newdb = (flags & FLAG_NEW_DB);
+ is_daemon_mode = (flags & FLAG_MODE_DAEMON);
+ if (flags & FLAG_MODE_CLIENT) {
exit_code = do_client(argc - i, argv + i);
- break;
- case mode_daemon :
- is_daemon_mode = GRN_TRUE;
- /* fallthru */
- case mode_server :
+ } else if (is_daemon_mode || (flags & FLAG_MODE_SERVER)) {
exit_code = do_server(argc > i ? argv[i] : NULL);
- break;
- default:
- exit_code = EXIT_FAILURE;
- break;
+ } else {
+ exit_code = do_alone(argc - i, argv + i);
}
#ifdef GRN_WITH_LIBEDIT
diff --git a/storage/mroonga/vendor/groonga/src/groonga_benchmark.c b/storage/mroonga/vendor/groonga/src/groonga_benchmark.c
index 61575174950..e7e426e748f 100644
--- a/storage/mroonga/vendor/groonga/src/groonga_benchmark.c
+++ b/storage/mroonga/vendor/groonga/src/groonga_benchmark.c
@@ -1,6 +1,6 @@
/* -*- c-basic-offset: 2 -*- */
/*
- Copyright(C) 2010-2012 Brazil
+ Copyright(C) 2010-2014 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -17,7 +17,7 @@
*/
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <stdio.h>
@@ -37,9 +37,9 @@
#include <netinet/in.h>
#endif /* HAVE_NETINET_IN_H */
-#include "lib/str.h"
-#include "lib/com.h"
-#include "lib/db.h"
+#include <grn_str.h>
+#include <grn_com.h>
+#include <grn_db.h>
#ifdef WIN32
#include <windows.h>
@@ -598,7 +598,7 @@ command_send_http(grn_ctx *ctx, const char *command, int type, int task_id)
fprintf(stderr, "failed to connect to groonga at %s:%d via HTTP: ",
grntest_serverhost, grntest_serverport);
#ifdef WIN32
- fprintf(stderr, "%d\n", GetLastError());
+ fprintf(stderr, "%lu\n", GetLastError());
#else
fprintf(stderr, "%s\n", strerror(errno));
#endif
@@ -1149,7 +1149,7 @@ typedef struct _grntest_worker {
} grntest_worker;
#ifdef WIN32
-static int
+static unsigned int
__stdcall
worker(void *val)
{
@@ -1252,7 +1252,6 @@ get_sysinfo(const char *path, char *result, int olen)
char tmpbuf[256];
#ifdef WIN32
- int cinfo[4];
ULARGE_INTEGER dinfo;
char cpustring[64];
SYSTEM_INFO sinfo;
@@ -1279,12 +1278,15 @@ get_sysinfo(const char *path, char *result, int olen)
memset(cpustring, 0, 64);
#ifndef __GNUC__
- __cpuid(cinfo, 0x80000002);
- memcpy(cpustring, cinfo, 16);
- __cpuid(cinfo, 0x80000003);
- memcpy(cpustring+16, cinfo, 16);
- __cpuid(cinfo, 0x80000004);
- memcpy(cpustring+32, cinfo, 16);
+ {
+ int cinfo[4];
+ __cpuid(cinfo, 0x80000002);
+ memcpy(cpustring, cinfo, 16);
+ __cpuid(cinfo, 0x80000003);
+ memcpy(cpustring+16, cinfo, 16);
+ __cpuid(cinfo, 0x80000004);
+ memcpy(cpustring+32, cinfo, 16);
+ }
#endif
if (grntest_outtype == OUT_TSV) {
@@ -1313,9 +1315,9 @@ get_sysinfo(const char *path, char *result, int olen)
GetSystemInfo(&sinfo);
if (grntest_outtype == OUT_TSV) {
- sprintf(tmpbuf, "CORE\t%d\n", sinfo.dwNumberOfProcessors);
+ sprintf(tmpbuf, "CORE\t%lu\n", sinfo.dwNumberOfProcessors);
} else {
- sprintf(tmpbuf, " \"CORE\": %d,\n", sinfo.dwNumberOfProcessors);
+ sprintf(tmpbuf, " \"CORE\": %lu,\n", sinfo.dwNumberOfProcessors);
}
strcat(result, tmpbuf);
@@ -1338,9 +1340,10 @@ get_sysinfo(const char *path, char *result, int olen)
osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osinfo);
if (grntest_outtype == OUT_TSV) {
- sprintf(tmpbuf, "Windows %d.%d\n", osinfo.dwMajorVersion, osinfo.dwMinorVersion);
+ sprintf(tmpbuf, "Windows %ld.%ld\n",
+ osinfo.dwMajorVersion, osinfo.dwMinorVersion);
} else {
- sprintf(tmpbuf, " \"OS\": \"Windows %d.%d\",\n", osinfo.dwMajorVersion,
+ sprintf(tmpbuf, " \"OS\": \"Windows %lu.%lu\",\n", osinfo.dwMajorVersion,
osinfo.dwMinorVersion);
}
strcat(result, tmpbuf);
@@ -1561,7 +1564,7 @@ start_server(const char *dbpath, int r)
0, NULL, NULL, &si, &grntest_pi);
if (ret == 0) {
- fprintf(stderr, "Cannot start groonga server: <%s>: error=%d\n",
+ fprintf(stderr, "Cannot start groonga server: <%s>: error=%lu\n",
groonga_path, GetLastError());
exit(1);
}
diff --git a/storage/mroonga/vendor/groonga/src/groonga_mruby.c b/storage/mroonga/vendor/groonga/src/groonga_mruby.c
new file mode 100644
index 00000000000..9978a002f18
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/src/groonga_mruby.c
@@ -0,0 +1,84 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+ Copyright(C) 2014 Brazil
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License version 2.1 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <grn_mrb.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static int
+run(grn_ctx *ctx, const char *db_path, const char *ruby_script_path)
+{
+ grn_obj *db;
+
+ db = grn_db_open(ctx, db_path);
+ if (!db) {
+ if (ctx->rc == GRN_NO_SUCH_FILE_OR_DIRECTORY) {
+ db = grn_db_create(ctx, db_path, NULL);
+ if (!db) {
+ fprintf(stderr, "Failed to create database: <%s>: %s",
+ db_path, ctx->errbuf);
+ return EXIT_FAILURE;
+ }
+ } else {
+ fprintf(stderr, "Failed to open database: <%s>: %s",
+ db_path, ctx->errbuf);
+ return EXIT_FAILURE;
+ }
+ }
+
+ grn_mrb_load(ctx, ruby_script_path);
+ if (ctx->rc != GRN_SUCCESS) {
+ fprintf(stderr, "Failed to load Ruby script: <%s>: %s",
+ ruby_script_path, ctx->errbuf);
+ }
+
+ grn_obj_close(ctx, db);
+
+ if (ctx->rc == GRN_SUCCESS) {
+ return EXIT_SUCCESS;
+ } else {
+ return EXIT_FAILURE;
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ int exit_code = EXIT_SUCCESS;
+
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s DB_PATH RUBY_SCRIPT_PATH\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ if (grn_init() != GRN_SUCCESS) {
+ return EXIT_FAILURE;
+ }
+
+ {
+ grn_ctx ctx;
+ grn_ctx_init(&ctx, 0);
+ exit_code = run(&ctx, argv[1], argv[2]);
+ grn_ctx_fin(&ctx);
+ }
+
+ grn_fin();
+
+ return exit_code;
+}
diff --git a/storage/mroonga/vendor/groonga/src/groonga_mruby_sources.am b/storage/mroonga/vendor/groonga/src/groonga_mruby_sources.am
new file mode 100644
index 00000000000..c9006755c97
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/src/groonga_mruby_sources.am
@@ -0,0 +1,2 @@
+groonga_mruby_SOURCES = \
+ groonga_mruby.c
diff --git a/storage/mroonga/vendor/groonga/src/httpd/nginx-module/ngx_http_groonga_module.c b/storage/mroonga/vendor/groonga/src/httpd/nginx-module/ngx_http_groonga_module.c
index 26be6be7d0a..115de1338a4 100644
--- a/storage/mroonga/vendor/groonga/src/httpd/nginx-module/ngx_http_groonga_module.c
+++ b/storage/mroonga/vendor/groonga/src/httpd/nginx-module/ngx_http_groonga_module.c
@@ -1,6 +1,6 @@
/* -*- c-basic-offset: 2 -*- */
/*
- Copyright(C) 2012-2014 Brazil
+ Copyright(C) 2012-2015 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -16,9 +16,9 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
+#ifndef WIN32
+# define NGX_GRN_SUPPORT_STOP_BY_COMMAND
+#endif
#include <ngx_config.h>
#include <ngx_core.h>
@@ -26,6 +26,13 @@
#include <groonga.h>
+#include <sys/stat.h>
+
+#ifdef NGX_GRN_SUPPORT_STOP_BY_COMMAND
+# include <sys/types.h>
+# include <unistd.h>
+#endif
+
#define GRN_NO_FLAGS 0
typedef struct {
@@ -56,9 +63,19 @@ typedef struct {
typedef struct {
grn_bool initialized;
grn_ctx context;
- grn_obj head;
- grn_obj body;
- grn_obj foot;
+ struct {
+ grn_bool processed;
+ grn_bool header_sent;
+ ngx_http_request_t *r;
+ ngx_int_t rc;
+ ngx_chain_t *free_chain;
+ ngx_chain_t *busy_chain;
+ } raw;
+ struct {
+ grn_obj head;
+ grn_obj body;
+ grn_obj foot;
+ } typed;
} ngx_http_groonga_handler_data_t;
typedef struct {
@@ -126,18 +143,54 @@ ngx_http_groonga_logger_log(grn_ctx *ctx, grn_log_level level,
const char level_marks[] = " EACewnid-";
u_char buffer[NGX_MAX_ERROR_STR];
u_char *last;
-
+ size_t prefix_size;
+ size_t message_size;
+ size_t location_size;
+ size_t postfix_size;
+ size_t log_message_size;
+
+#define LOG_PREFIX_FORMAT "%s|%c|%s "
+ prefix_size =
+ strlen(timestamp) +
+ 1 /* | */ +
+ 1 /* %c */ +
+ 1 /* | */ +
+ strlen(title) +
+ 1 /* a space */;
+ message_size = strlen(message);
if (location && *location) {
- last = ngx_slprintf(buffer, buffer + NGX_MAX_ERROR_STR,
- "%s|%c|%s %s %s\n",
- timestamp, *(level_marks + level), title, message,
- location);
+ location_size = 1 /* a space */ + strlen(location);
} else {
+ location_size = 0;
+ }
+ postfix_size = 1 /* \n */;
+ log_message_size = prefix_size + message_size + location_size + postfix_size;
+
+ if (log_message_size > NGX_MAX_ERROR_STR) {
last = ngx_slprintf(buffer, buffer + NGX_MAX_ERROR_STR,
- "%s|%c|%s %s\n",
- timestamp, *(level_marks + level), title, message);
+ LOG_PREFIX_FORMAT,
+ timestamp, *(level_marks + level), title);
+ ngx_write_fd(logger_data->file->fd, buffer, last - buffer);
+ ngx_write_fd(logger_data->file->fd, (void *)message, message_size);
+ if (location_size > 0) {
+ ngx_write_fd(logger_data->file->fd, " ", 1);
+ ngx_write_fd(logger_data->file->fd, (void *)location, location_size);
+ }
+ ngx_write_fd(logger_data->file->fd, "\n", 1);
+ } else {
+ if (location && *location) {
+ last = ngx_slprintf(buffer, buffer + NGX_MAX_ERROR_STR,
+ LOG_PREFIX_FORMAT " %s %s\n",
+ timestamp, *(level_marks + level), title, message,
+ location);
+ } else {
+ last = ngx_slprintf(buffer, buffer + NGX_MAX_ERROR_STR,
+ LOG_PREFIX_FORMAT " %s\n",
+ timestamp, *(level_marks + level), title, message);
+ }
+ ngx_write_fd(logger_data->file->fd, buffer, last - buffer);
}
- ngx_write_fd(logger_data->file->fd, buffer, last - buffer);
+#undef LOG_PREFIX_FORMAT
}
static void
@@ -336,6 +389,7 @@ ngx_http_groonga_grn_obj_to_ngx_buf(ngx_pool_t *pool, grn_obj *object)
buffer->pos = (u_char *)GRN_TEXT_VALUE(object);
buffer->last = (u_char *)GRN_TEXT_VALUE(object) + GRN_TEXT_LEN(object);
buffer->memory = 1; /* this buffer is in memory */
+ buffer->in_file = 0;
return buffer;
}
@@ -351,20 +405,109 @@ ngx_http_groonga_handler_cleanup(void *user_data)
}
context = &(data->context);
- GRN_OBJ_FIN(context, &(data->head));
- GRN_OBJ_FIN(context, &(data->body));
- GRN_OBJ_FIN(context, &(data->foot));
+ GRN_OBJ_FIN(context, &(data->typed.head));
+ GRN_OBJ_FIN(context, &(data->typed.body));
+ GRN_OBJ_FIN(context, &(data->typed.foot));
grn_logger_set(context, NULL);
grn_query_logger_set(context, NULL);
grn_ctx_fin(context);
}
static void
-ngx_http_groonga_context_receive_handler(grn_ctx *context,
- int flags,
- void *callback_data)
+ngx_http_groonga_handler_set_content_type(ngx_http_request_t *r,
+ const char *content_type)
+{
+ r->headers_out.content_type.len = strlen(content_type);
+ r->headers_out.content_type.data = (u_char *)content_type;
+ r->headers_out.content_type_len = r->headers_out.content_type.len;
+}
+
+static void
+ngx_http_groonga_context_receive_handler_raw(grn_ctx *context,
+ int flags,
+ ngx_http_groonga_handler_data_t *data)
+{
+ char *chunk = NULL;
+ unsigned int chunk_size = 0;
+ int recv_flags;
+ ngx_http_request_t *r;
+ ngx_log_t *log;
+ grn_bool is_last_chunk;
+
+ grn_ctx_recv(context, &chunk, &chunk_size, &recv_flags);
+ data->raw.processed = GRN_TRUE;
+
+ if (data->raw.rc != NGX_OK) {
+ return;
+ }
+
+ r = data->raw.r;
+ log = r->connection->log;
+ is_last_chunk = (flags & GRN_CTX_TAIL);
+
+ if (!data->raw.header_sent) {
+ ngx_http_groonga_handler_set_content_type(r, grn_ctx_get_mime_type(context));
+ r->headers_out.status = NGX_HTTP_OK;
+ if (is_last_chunk) {
+ r->headers_out.content_length_n = chunk_size;
+ if (chunk_size == 0) {
+ r->header_only = 1;
+ }
+ } else {
+ r->headers_out.content_length_n = -1;
+ }
+ data->raw.rc = ngx_http_send_header(r);
+ data->raw.header_sent = GRN_TRUE;
+
+ if (data->raw.rc != NGX_OK) {
+ return;
+ }
+ }
+
+ if (chunk_size > 0 || is_last_chunk) {
+ ngx_chain_t *chain;
+
+ chain = ngx_chain_get_free_buf(r->pool, &(data->raw.free_chain));
+ if (!chain) {
+ ngx_log_error(NGX_LOG_ERR, log, 0,
+ "http_groonga: failed to allocate memory for chunked body");
+ data->raw.rc = NGX_ERROR;
+ return;
+ }
+ if (chunk_size == 0) {
+ chain->buf->pos = NULL;
+ chain->buf->last = NULL;
+ chain->buf->memory = 0;
+ } else {
+ chain->buf->pos = (u_char *)chunk;
+ chain->buf->last = (u_char *)chunk + chunk_size;
+ chain->buf->memory = 1;
+ }
+ chain->buf->tag = (ngx_buf_tag_t)&ngx_http_groonga_module;
+ chain->buf->flush = 1;
+ chain->buf->temporary = 0;
+ chain->buf->in_file = 0;
+ if (is_last_chunk) {
+ chain->buf->last_buf = 1;
+ } else {
+ chain->buf->last_buf = 0;
+ }
+ chain->next = NULL;
+
+ data->raw.rc = ngx_http_output_filter(r, chain);
+ ngx_chain_update_chains(r->pool,
+ &(data->raw.free_chain),
+ &(data->raw.busy_chain),
+ &chain,
+ (ngx_buf_tag_t)&ngx_http_groonga_module);
+ }
+}
+
+static void
+ngx_http_groonga_context_receive_handler_typed(grn_ctx *context,
+ int flags,
+ ngx_http_groonga_handler_data_t *data)
{
- ngx_http_groonga_handler_data_t *data = callback_data;
char *result = NULL;
unsigned int result_size = 0;
int recv_flags;
@@ -375,6 +518,7 @@ ngx_http_groonga_context_receive_handler(grn_ctx *context,
grn_ctx_recv(context, &result, &result_size, &recv_flags);
+#ifdef NGX_GRN_SUPPORT_STOP_BY_COMMAND
if (recv_flags == GRN_CTX_QUIT) {
ngx_int_t ngx_rc;
ngx_int_t ngx_pid;
@@ -394,28 +538,43 @@ ngx_http_groonga_context_receive_handler(grn_ctx *context,
context->stat |= GRN_CTX_QUIT;
} else {
context->rc = GRN_OPERATION_NOT_PERMITTED;
- GRN_TEXT_PUTS(context, &(data->body), "false");
+ GRN_TEXT_PUTS(context, &(data->typed.body), "false");
context->stat &= ~GRN_CTX_QUIT;
}
}
+#endif
if (result_size > 0 ||
- GRN_TEXT_LEN(&(data->body)) > 0 ||
+ GRN_TEXT_LEN(&(data->typed.body)) > 0 ||
context->rc != GRN_SUCCESS) {
if (result_size > 0) {
- GRN_TEXT_PUT(context, &(data->body), result, result_size);
+ GRN_TEXT_PUT(context, &(data->typed.body), result, result_size);
}
grn_output_envelope(context,
context->rc,
- &(data->head),
- &(data->body),
- &(data->foot),
+ &(data->typed.head),
+ &(data->typed.body),
+ &(data->typed.foot),
NULL,
0);
}
}
+static void
+ngx_http_groonga_context_receive_handler(grn_ctx *context,
+ int flags,
+ void *callback_data)
+{
+ ngx_http_groonga_handler_data_t *data = callback_data;
+
+ if (grn_ctx_get_output_type(context) == GRN_CONTENT_NONE) {
+ ngx_http_groonga_context_receive_handler_raw(context, flags, data);
+ } else {
+ ngx_http_groonga_context_receive_handler_typed(context, flags, data);
+ }
+}
+
static ngx_int_t
ngx_http_groonga_extract_command_path(ngx_http_request_t *r,
ngx_str_t *command_path)
@@ -461,15 +620,6 @@ ngx_http_groonga_extract_command_path(ngx_http_request_t *r,
return NGX_OK;
}
-static void
-ngx_http_groonga_handler_set_content_type(ngx_http_request_t *r,
- const char *content_type)
-{
- r->headers_out.content_type.len = strlen(content_type);
- r->headers_out.content_type.data = (u_char *)content_type;
- r->headers_out.content_type_len = r->headers_out.content_type.len;
-}
-
static ngx_int_t
ngx_http_groonga_handler_create_data(ngx_http_request_t *r,
ngx_http_groonga_handler_data_t **data_return)
@@ -496,10 +646,20 @@ ngx_http_groonga_handler_create_data(ngx_http_request_t *r,
if (rc != NGX_OK) {
return rc;
}
+
data->initialized = GRN_TRUE;
- GRN_TEXT_INIT(&(data->head), GRN_NO_FLAGS);
- GRN_TEXT_INIT(&(data->body), GRN_NO_FLAGS);
- GRN_TEXT_INIT(&(data->foot), GRN_NO_FLAGS);
+
+ data->raw.processed = GRN_FALSE;
+ data->raw.header_sent = GRN_FALSE;
+ data->raw.r = r;
+ data->raw.rc = NGX_OK;
+ data->raw.free_chain = NULL;
+ data->raw.busy_chain = NULL;
+
+ GRN_TEXT_INIT(&(data->typed.head), GRN_NO_FLAGS);
+ GRN_TEXT_INIT(&(data->typed.body), GRN_NO_FLAGS);
+ GRN_TEXT_INIT(&(data->typed.foot), GRN_NO_FLAGS);
+
grn_ctx_use(context, grn_ctx_db(&(location_conf->context)));
rc = ngx_http_groonga_context_check_error(r->connection->log, context);
if (rc != NGX_OK) {
@@ -553,9 +713,10 @@ ngx_http_groonga_handler_validate_post_command(ngx_http_request_t *r,
context = &(data->context);
ngx_http_groonga_handler_set_content_type(r, "text/plain");
- GRN_TEXT_PUTS(context, &(data->body), "command for POST must be <load>: <");
- GRN_TEXT_PUT(context, &(data->body), command.data, command.len);
- GRN_TEXT_PUTS(context, &(data->body), ">");
+ GRN_TEXT_PUTS(context, &(data->typed.body),
+ "command for POST must be <load>: <");
+ GRN_TEXT_PUT(context, &(data->typed.body), command.data, command.len);
+ GRN_TEXT_PUTS(context, &(data->typed.body), ">");
return NGX_HTTP_BAD_REQUEST;
}
@@ -665,7 +826,7 @@ ngx_http_groonga_handler_process_body(ngx_http_request_t *r,
body = r->request_body->bufs->buf;
if (!body) {
ngx_http_groonga_handler_set_content_type(r, "text/plain");
- GRN_TEXT_PUTS(context, &(data->body), "must send load data as body");
+ GRN_TEXT_PUTS(context, &(data->typed.body), "must send load data as body");
return NGX_HTTP_BAD_REQUEST;
}
@@ -744,6 +905,10 @@ ngx_http_groonga_handler_send_response(ngx_http_request_t *r,
ngx_chain_t head_chain, body_chain, foot_chain;
ngx_chain_t *output_chain = NULL;
+ if (data->raw.processed) {
+ return data->raw.rc;
+ }
+
context = &(data->context);
/* set the 'Content-type' header */
@@ -753,17 +918,17 @@ ngx_http_groonga_handler_send_response(ngx_http_request_t *r,
}
/* allocate buffers for a response body */
- head_buf = ngx_http_groonga_grn_obj_to_ngx_buf(r->pool, &(data->head));
+ head_buf = ngx_http_groonga_grn_obj_to_ngx_buf(r->pool, &(data->typed.head));
if (!head_buf) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
- body_buf = ngx_http_groonga_grn_obj_to_ngx_buf(r->pool, &(data->body));
+ body_buf = ngx_http_groonga_grn_obj_to_ngx_buf(r->pool, &(data->typed.body));
if (!body_buf) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
- foot_buf = ngx_http_groonga_grn_obj_to_ngx_buf(r->pool, &(data->foot));
+ foot_buf = ngx_http_groonga_grn_obj_to_ngx_buf(r->pool, &(data->typed.foot));
if (!foot_buf) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
@@ -778,9 +943,9 @@ ngx_http_groonga_handler_send_response(ngx_http_request_t *r,
/* set the status line */
r->headers_out.status = NGX_HTTP_OK;
- r->headers_out.content_length_n = GRN_TEXT_LEN(&(data->head)) +
- GRN_TEXT_LEN(&(data->body)) +
- GRN_TEXT_LEN(&(data->foot));
+ r->headers_out.content_length_n = GRN_TEXT_LEN(&(data->typed.head)) +
+ GRN_TEXT_LEN(&(data->typed.body)) +
+ GRN_TEXT_LEN(&(data->typed.foot));
if (r->headers_out.content_length_n == 0) {
r->header_only = 1;
}
@@ -1072,7 +1237,7 @@ ngx_http_groonga_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
GRN_CACHE_DEFAULT_MAX_N_ENTRIES);
#ifdef NGX_HTTP_GROONGA_LOG_PATH
- {
+ if (!conf->log_file) {
ngx_str_t default_log_path;
default_log_path.data = (u_char *)NGX_HTTP_GROONGA_LOG_PATH;
default_log_path.len = strlen(NGX_HTTP_GROONGA_LOG_PATH);
@@ -1085,8 +1250,6 @@ ngx_http_groonga_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
return NGX_CONF_ERROR;
}
}
-#else
- conf->log_file = NULL;
#endif
ngx_conf_merge_str_value(conf->query_log_path, prev->query_log_path,
diff --git a/storage/mroonga/vendor/groonga/src/suggest/CMakeLists.txt b/storage/mroonga/vendor/groonga/src/suggest/CMakeLists.txt
index 0773026a618..c0c7a9c9964 100644
--- a/storage/mroonga/vendor/groonga/src/suggest/CMakeLists.txt
+++ b/storage/mroonga/vendor/groonga/src/suggest/CMakeLists.txt
@@ -25,11 +25,9 @@ set_source_files_properties(${GROONGA_SUGGEST_CREATE_DATASET_SOURCES}
PROPERTIES
COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}")
target_link_libraries(groonga-suggest-create-dataset libgroonga)
-if(NOT MRN_GROONGA_BUNDLED)
- install(
- TARGETS groonga-suggest-create-dataset
- DESTINATION ${BIN_DIR})
-endif()
+install(
+ TARGETS groonga-suggest-create-dataset
+ DESTINATION ${BIN_DIR})
if(GRN_WITH_LIBEVENT AND GRN_WITH_ZEROMQ AND GRN_WITH_MESSAGE_PACK)
set(GRN_WITH_SUGGEST_LEARNER TRUE)
@@ -82,9 +80,7 @@ if(GRN_WITH_SUGGEST_LEARNER)
${ZEROMQ_LIBRARIES}
${MESSAGE_PACK_LIBRARIES})
- if(NOT MRN_GROONGA_BUNDLED)
- install(
- TARGETS groonga-suggest-learner groonga-suggest-httpd
- DESTINATION ${BIN_DIR})
- endif()
+ install(
+ TARGETS groonga-suggest-learner groonga-suggest-httpd
+ DESTINATION ${BIN_DIR})
endif()
diff --git a/storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_create_dataset.c b/storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_create_dataset.c
index 35f2cd09fc0..d566d24b96a 100644
--- a/storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_create_dataset.c
+++ b/storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_create_dataset.c
@@ -21,7 +21,7 @@
#include <groonga.h>
/* For grn_str_getopt() */
-#include <str.h>
+#include <grn_str.h>
typedef enum {
MODE_NONE,
diff --git a/storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_httpd.c b/storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_httpd.c
index 6d94be87a8a..98ae0958908 100644
--- a/storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_httpd.c
+++ b/storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_httpd.c
@@ -16,7 +16,7 @@
*/
/* groonga origin headers */
-#include <str.h>
+#include <grn_str.h>
#include <stdio.h>
#include <signal.h>
diff --git a/storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_learner.c b/storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_learner.c
index 060d238565a..18b91d438e2 100644
--- a/storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_learner.c
+++ b/storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_learner.c
@@ -16,7 +16,7 @@
*/
/* for grn_str_getopt() */
-#include <str.h>
+#include <grn_str.h>
#include "zmq_compatible.h"
#include <stdio.h>
diff --git a/storage/mroonga/vendor/groonga/tools/travis-before-script.sh b/storage/mroonga/vendor/groonga/tools/travis-before-script.sh
index 943f41b0013..71d5a816b87 100755
--- a/storage/mroonga/vendor/groonga/tools/travis-before-script.sh
+++ b/storage/mroonga/vendor/groonga/tools/travis-before-script.sh
@@ -4,30 +4,46 @@ set -e
git submodule update --init --depth 1
+prefix=/tmp/local
+
case "${BUILD_TOOL}" in
- autotools)
- ./autogen.sh
-
- configure_args=""
- #if [ "$CC" = "clang" ]; then
- configure_args="${configure_args} --enable-debug"
- #fi
- if [ "$ENABLE_MRUBY" = "yes" ]; then
- configure_args="${configure_args} --with-ruby --enable-mruby"
- fi
-
- ./configure --with-ruby ${configure_args}
- ;;
- cmake)
- cmake_args=""
- cmake_args="${cmake_args} -DGRN_WITH_DEBUG=yes"
- if [ "$ENABLE_MRUBY" = "yes" ]; then
- cmake_args="${cmake_args} -DGRN_WITH_MRUBY=yes"
- fi
-
- cmake . ${cmake_args}
- ;;
+ autotools)
+ ./autogen.sh
+
+ configure_args=""
+ #if [ "$CC" = "clang" ]; then
+ configure_args="${configure_args} --enable-debug"
+ #fi
+ if [ "$ENABLE_MRUBY" = "yes" ]; then
+ configure_args="${configure_args} --with-ruby --enable-mruby"
+ fi
+ if [ "$ENABLE_JEMALLOC" = "yes" ]; then
+ configure_args="${configure_args} --with-jemalloc"
+ fi
+
+ ./configure --prefix=${prefix} --with-ruby ${configure_args}
+ ;;
+ cmake)
+ cmake_args=""
+ cmake_args="${cmake_args} -DGRN_WITH_DEBUG=yes"
+ if [ "$ENABLE_MRUBY" = "yes" ]; then
+ cmake_args="${cmake_args} -DGRN_WITH_MRUBY=yes"
+ fi
+
+ cmake . ${cmake_args}
+ ;;
+esac
+
+case "$(uname)" in
+ Linux)
+ n_processors="$(grep '^processor' /proc/cpuinfo | wc -l)"
+ ;;
+ Darwin)
+ n_processors="$(/usr/sbin/sysctl -n hw.ncpu)"
+ ;;
+ *)
+ n_processors="1"
+ ;;
esac
-n_processors="$(grep '^processor' /proc/cpuinfo | wc -l)"
make -j${n_processors} > /dev/null
diff --git a/storage/mroonga/vendor/groonga/tools/travis-install.sh b/storage/mroonga/vendor/groonga/tools/travis-install.sh
new file mode 100755
index 00000000000..e64e17b9872
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/tools/travis-install.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+set -e
+
+case "${TRAVIS_OS_NAME}" in
+ linux)
+ curl --silent --location https://raw.github.com/clear-code/cutter/master/data/travis/setup.sh | sh
+ sudo apt-get install -qq -y \
+ autotools-dev \
+ zlib1g-dev \
+ libmsgpack-dev \
+ libevent-dev \
+ libmecab-dev \
+ mecab-naist-jdic \
+ cmake
+ if [ "${ENABLE_JEMALLOC}" = "yes" ]; then
+ sudo apt-get install -qq -y libjemalloc-dev
+ fi
+ ;;
+ osx)
+ brew install \
+ msgpack \
+ libevent \
+ mecab \
+ mecab-ipadic
+ ;;
+esac
+
+if [ "${ENABLE_MRUBY}" = "yes" ]; then
+ gem install pkg-config groonga-client
+fi
diff --git a/storage/mroonga/vendor/groonga/tools/travis-script.sh b/storage/mroonga/vendor/groonga/tools/travis-script.sh
index 7931903d419..35bf0bd1c9e 100755
--- a/storage/mroonga/vendor/groonga/tools/travis-script.sh
+++ b/storage/mroonga/vendor/groonga/tools/travis-script.sh
@@ -2,14 +2,20 @@
set -e
+prefix=/tmp/local
+
case "${BUILD_TOOL}" in
- autotools)
- test/unit/run-test.sh
- test/command/run-test.sh
- # test/command/run-test.sh --interface http
- # test/command/run-test.sh --interface http --testee groonga-httpd
- ;;
- cmake)
- test/command/run-test.sh
- ;;
+ autotools)
+ test/unit/run-test.sh
+ test/command/run-test.sh
+ if [ "${ENABLE_MRUBY}" = "yes" ]; then
+ test/query_optimizer/run-test.rb
+ fi
+ test/command/run-test.sh --interface http
+ mkdir -p ${prefix}/var/log/groonga/httpd
+ test/command/run-test.sh --testee groonga-httpd
+ ;;
+ cmake)
+ test/command/run-test.sh
+ ;;
esac
diff --git a/storage/mroonga/vendor/groonga/vendor/Makefile.am b/storage/mroonga/vendor/groonga/vendor/Makefile.am
index 334b6fd8917..0b766191a08 100644
--- a/storage/mroonga/vendor/groonga/vendor/Makefile.am
+++ b/storage/mroonga/vendor/groonga/vendor/Makefile.am
@@ -11,6 +11,7 @@ EXTRA_DIST = \
mruby/CMakeLists.txt
dist-hook:
+ rm -rf $(distdir)/$(NGINX_DIR)/objs/
GIT_DIR=$(srcdir)/mruby-source/.git git archive --format=tar HEAD | \
tar xf - -C $(distdir)/mruby-source
$(MKDIR_P) $(distdir)/onigmo-source
diff --git a/storage/mroonga/vendor/groonga/vendor/mruby/CMakeLists.txt b/storage/mroonga/vendor/groonga/vendor/mruby/CMakeLists.txt
index 9f4aad4c32b..994ad5e0e6c 100644
--- a/storage/mroonga/vendor/groonga/vendor/mruby/CMakeLists.txt
+++ b/storage/mroonga/vendor/groonga/vendor/mruby/CMakeLists.txt
@@ -24,6 +24,8 @@ include_directories(
if(GRN_WITH_MRUBY)
read_file_list("${CMAKE_CURRENT_SOURCE_DIR}/sources.am" MRUBY_SOURCES)
+ string(REGEX REPLACE "\\.\\./" "${CMAKE_CURRENT_SOURCE_DIR}/../"
+ MRUBY_SOURCES "${MRUBY_SOURCES}")
add_library(mruby OBJECT ${MRUBY_SOURCES})
set_source_files_properties(${MRUBY_SOURCES}
PROPERTIES
diff --git a/storage/mroonga/vendor/groonga/vendor/mruby/Makefile.am b/storage/mroonga/vendor/groonga/vendor/mruby/Makefile.am
index 41385bcd589..dff8a235b49 100644
--- a/storage/mroonga/vendor/groonga/vendor/mruby/Makefile.am
+++ b/storage/mroonga/vendor/groonga/vendor/mruby/Makefile.am
@@ -1,9 +1,12 @@
EXTRA_DIST = \
- build_config.rb
+ build_config.rb \
+ mruby-build.timestamp
DEFAULT_INCLUDES = \
-I$(srcdir)/../mruby-source/include \
- -I$(srcdir)/../mruby-source/src
+ -I$(srcdir)/../mruby-source/src \
+ -Imruby-io/include \
+ -I$(srcdir)/mruby-io/include
if WITH_MRUBY
noinst_LTLIBRARIES = libmruby.la
@@ -22,18 +25,31 @@ include sources.am
BUILT_SOURCES = \
parse.c \
mrblib.c \
- mrbgems_init.c \
- mruby_onig_regexp.c
+ mrbgems_init.c
+BUILT_SOURCES += \
+ mruby-onig-regexp/src/mruby_onig_regexp.c
+BUILT_SOURCES += \
+ mruby-io/include/mruby/ext/io.h \
+ mruby-io/src/file.c \
+ mruby-io/src/file_test.c \
+ mruby-io/src/io.c \
+ mruby-io/src/mruby_io_gem.c
libmruby_la_SOURCES += $(BUILT_SOURCES)
parse.c: mruby-build.timestamp
mrblib.c: mruby-build.timestamp
mrbgems_init.c: mruby-build.timestamp
-mruby_onig_regexp.c: mruby-build.timestamp
+mruby-onig-regexp/src/mruby_onig_regexp.c: mruby-build.timestamp
+mruby-io/include/mruby/ext/io.h: mruby-build.timestamp
+mruby-io/src/file.c: mruby-build.timestamp
+mruby-io/src/file_test.c: mruby-build.timestamp
+mruby-io/src/io.c: mruby-build.timestamp
+mruby-io/src/mruby_io_gem.c: mruby-build.timestamp
MRUBY_CONFIG = $(abs_srcdir)/build_config.rb
MRUBY_BUILD_DIR = $(abs_top_builddir)/vendor/mruby-build
MRUBY_ONIG_REGEXP_DIR = $(MRUBY_BUILD_DIR)/mrbgems/mruby-onig-regexp
+MRUBY_IO_DIR = $(MRUBY_BUILD_DIR)/mrbgems/mruby-io
mruby-build.timestamp: build_config.rb
rm -rf $(MRUBY_BUILD_DIR)
cd $(srcdir)/../mruby-source && \
@@ -47,7 +63,11 @@ mruby-build.timestamp: build_config.rb
cat $(MRUBY_BUILD_DIR)/host/mrbgems/gem_init.c; \
cat $(MRUBY_BUILD_DIR)/host/mrbgems/*/gem_init.c; \
) > mrbgems_init.c
- cp $(MRUBY_ONIG_REGEXP_DIR)/src/mruby_onig_regexp.c ./
+ $(MKDIR_P) mruby-onig-regexp/
+ cp -r $(MRUBY_ONIG_REGEXP_DIR)/src/ mruby-onig-regexp/
+ $(MKDIR_P) mruby-io/
+ cp -r $(MRUBY_IO_DIR)/include/ mruby-io/
+ cp -r $(MRUBY_IO_DIR)/src/ mruby-io/
EXTRA_DIST += \
mruby-build.timestamp
diff --git a/storage/mroonga/vendor/groonga/vendor/mruby/build_config.rb b/storage/mroonga/vendor/groonga/vendor/mruby/build_config.rb
index 2380c04789d..65992c20340 100644
--- a/storage/mroonga/vendor/groonga/vendor/mruby/build_config.rb
+++ b/storage/mroonga/vendor/groonga/vendor/mruby/build_config.rb
@@ -30,4 +30,7 @@ MRuby::Build.new do |conf|
conf.gem :core => "mruby-kernel-ext"
conf.gem :github => "mattn/mruby-onig-regexp"
+ conf.gem :github => "iij/mruby-io"
+ conf.gem :github => "kou/mruby-pp"
+ conf.gem :github => "kou/mruby-slop"
end
diff --git a/storage/mroonga/vendor/groonga/vendor/onigmo/Makefile.am b/storage/mroonga/vendor/groonga/vendor/onigmo/Makefile.am
index 772bfb420c6..9219783bbd7 100644
--- a/storage/mroonga/vendor/groonga/vendor/onigmo/Makefile.am
+++ b/storage/mroonga/vendor/groonga/vendor/onigmo/Makefile.am
@@ -4,16 +4,13 @@ EXTRA_DIST = \
CONFIGURE_DEPENDENCIES = \
configure
-ALL_DEPEND_TARGETS =
-INSTALL_DEPEND_TARGETS =
-CLEAN_DEPEND_TARGETS =
-if WITH_MRUBY
-ALL_DEPEND_TARGETS += onigmo-all
+ALL_DEPEND_TARGETS = onigmo-all
+CLEAN_DEPEND_TARGETS = onigmo-clean
+
+INSTALL_DEPEND_TARGETS = onigmo-all
if WITH_SHARED_ONIGMO
INSTALL_DEPEND_TARGETS += onigmo-install
endif
-CLEAN_DEPEND_TARGETS += onigmo-clean
-endif
onigmo-all:
cd ../onigmo-source && $(MAKE) all
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/AUTHORS b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/AUTHORS
deleted file mode 100644
index 95053dbcb47..00000000000
--- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/AUTHORS
+++ /dev/null
@@ -1 +0,0 @@
-See README.md.
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/CMakeLists.txt b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/CMakeLists.txt
index 484a7d63bfd..3577572a9f1 100644
--- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/CMakeLists.txt
+++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright(C) 2013 Kouhei Sutou <kou@clear-code.com>
+# Copyright(C) 2013-2015 Kouhei Sutou <kou@clear-code.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
@@ -18,6 +18,16 @@
cmake_minimum_required(VERSION 2.6)
project(groonga-normalizer-mysql)
+if(DEFINED GROONGA_NORMALIZER_MYSQL_EMBED)
+ set(GROONGA_NORMALIZER_MYSQL_EMBED_DEFAULT
+ ${GROONGA_NORMALIZER_MYSQL_EMBED})
+else()
+ set(GROONGA_NORMALIZER_MYSQL_EMBED_DEFAULT OFF)
+endif()
+option(GROONGA_NORMALIZER_MYSQL_EMBED
+ "Build as a static library to embed into an application"
+ ${GROONGA_NORMALIZER_MYSQL_EMBED_DEFAULT})
+
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/version" VERSION)
if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
@@ -53,12 +63,11 @@ link_directories(
add_subdirectory(normalizers)
-configure_file(
- groonga-normalizer-mysql.pc.in
- "${CMAKE_CURRENT_BINARY_DIR}/groonga-normalizer-mysql.pc"
- @ONLY)
-
-if(NOT GROONGA_NORMALIZER_MYSQL_FOUND)
+if(NOT GROONGA_NORMALIZER_MYSQL_EMBED)
+ configure_file(
+ groonga-normalizer-mysql.pc.in
+ "${CMAKE_CURRENT_BINARY_DIR}/groonga-normalizer-mysql.pc"
+ @ONLY)
install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/groonga-normalizer-mysql.pc"
DESTINATION "lib/pkgconfig/")
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/ChangeLog b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/ChangeLog
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/ChangeLog
+++ /dev/null
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/INSTALL b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/INSTALL
deleted file mode 100644
index 95053dbcb47..00000000000
--- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/INSTALL
+++ /dev/null
@@ -1 +0,0 @@
-See README.md.
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/NEWS b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/NEWS
deleted file mode 100644
index a4685347e88..00000000000
--- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/NEWS
+++ /dev/null
@@ -1 +0,0 @@
-See doc/text/news.md.
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/README b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/README
deleted file mode 100644
index 95053dbcb47..00000000000
--- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/README
+++ /dev/null
@@ -1 +0,0 @@
-See README.md.
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/README.md b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/README.md
index 866aba84d40..a2fcf4c9f84 100644
--- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/README.md
+++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/README.md
@@ -6,8 +6,8 @@ groonga-normalizer-mysql
## Description
-Groonga-normalizer-mysql is a groonga plugin. It provides MySQL
-compatible normalizers and a custom normalizer to groonga.
+Groonga-normalizer-mysql is a Groonga plugin. It provides MySQL
+compatible normalizers and a custom normalizer to Groonga.
MySQL compatible normalizers are `NormalizerMySQLGeneralCI` and
`NormalizerMySQLUnicodeCI`. `NormalizerMySQLGeneralCI` corresponds to
@@ -62,14 +62,14 @@ doesn't identify them.
### Debian GNU/Linux
-[Add apt-line for the groonga deb package repository](http://groonga.org/docs/install/debian.html)
+[Add apt-line for the Groonga deb package repository](http://groonga.org/docs/install/debian.html)
and install `groonga-normalizer-mysql` package:
% sudo aptitude -V -D -y install groonga-normalizer-mysql
### Ubuntu
-[Add apt-line for the groonga deb package repository](http://groonga.org/docs/install/ubuntu.html)
+[Add apt-line for the Groonga deb package repository](http://groonga.org/docs/install/ubuntu.html)
and install `groonga-normalizer-mysql` package:
% sudo aptitude -V -D -y install groonga-normalizer-mysql
@@ -114,16 +114,16 @@ Install the following build tools:
* [Microsoft Visual Studio 2010 Express](http://www.microsoft.com/japan/msdn/vstudio/express/): 2012 isn't tested yet.
* [CMake](http://www.cmake.org/)
-#### Build groonga
+#### Build Groonga
-Download the latest groonga source from [packages.groonga.org](http://packages.groonga.org/source/groonga/). Source file name is formatted as `groonga-X.Y.Z.zip`.
+Download the latest Groonga source from [packages.groonga.org](http://packages.groonga.org/source/groonga/). Source file name is formatted as `groonga-X.Y.Z.zip`.
Extract the source and move to the source folder:
> cd ...\groonga-X.Y.Z
groonga-X.Y.Z>
-Run CMake. Here is a command line to install groonga to `C:\groonga` folder:
+Run CMake. Here is a command line to install Groonga to `C:\groonga` folder:
groonga-X.Y.Z> cmake . -G "Visual Studio 10 Win64" -DCMAKE_INSTALL_PREFIX=C:\groonga
@@ -148,7 +148,7 @@ IMPORTANT!!!: Set `PKG_CONFIG_PATH` environment variable:
groonga-normalizer-mysql-X.Y.Z> set PKG_CONFIG_PATH=C:\groongalocal\lib\pkgconfig
-Run CMake. Here is a command line to install groonga to `C:\groonga` folder:
+Run CMake. Here is a command line to install Groonga to `C:\groonga` folder:
groonga-normalizer-mysql-X.Y.Z> cmake . -G "Visual Studio 10 Win64" -DCMAKE_INSTALL_PREFIX=C:\groonga
@@ -173,7 +173,7 @@ Then, you can use `NormalizerMySQLGeneralCI` and
## Dependencies
-* groonga >= 3.0.3
+* Groonga >= 3.0.3
## Mailing list
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/configure.ac b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/configure.ac
index effb5884f93..1ef007bb6df 100644
--- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/configure.ac
+++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/configure.ac
@@ -1,4 +1,4 @@
-# Copyright (C) 2013 Kouhei Sutou <kou@clear-code.com>
+# Copyright (C) 2013-2015 Kouhei Sutou <kou@clear-code.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
@@ -24,7 +24,7 @@ AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR([normalizers/mysql.c])
AM_CONFIG_HEADER([config.h])
-AM_INIT_AUTOMAKE([1.9 tar-pax])
+AM_INIT_AUTOMAKE([1.9 foreign tar-pax])
AC_PROG_LIBTOOL
@@ -49,11 +49,23 @@ AC_SUBST(GROONGA)
normalizers_pluginsdir="\${GROONGA_PLUGINS_DIR}/normalizers"
AC_SUBST(normalizers_pluginsdir)
+AC_ARG_ENABLE([embed],
+ AS_HELP_STRING([--enable-embed],
+ [Build as a static library to embed into an application (default: no)]),
+ [GROONGA_NORMALIZER_MYSQL_EMBED="$enableval"],
+ [GROONGA_NORMALIZER_MYSQL_EMBED="no"])
+
+if test "x$GROONGA_NORMALIZER_MYSQL_EMBED" = "xyes"; then
+ AC_DEFINE_UNQUOTED(GROONGA_NORMALIZER_MYSQL_EMBED,
+ [1],
+ [Define to 1 if groonga-normalizer-mysql is built for embedding.])
+fi
+
# check Ruby for test
ac_cv_ruby_available="no"
-AC_ARG_WITH([ruby19],
- AS_HELP_STRING([--with-ruby19=PATH],
- [Ruby 1.9 interpreter path (default: auto)]),
+AC_ARG_WITH([ruby],
+ AS_HELP_STRING([--with-ruby=PATH],
+ [Ruby interpreter path (default: auto)]),
[RUBY="$withval"],
[RUBY="auto"])
@@ -61,17 +73,19 @@ if test "x$RUBY" = "xno"; then
RUBY=
else
if test "x$RUBY" = "xauto"; then
- AC_PATH_PROGS(RUBY, [ruby1.9 ruby19 ruby1.9.1 ruby], ruby19-not-found)
- if test "$RUBY" != "ruby19-not-found"; then
+ AC_PATH_PROGS(RUBY,
+ [ruby2.1 ruby21 ruby2.0 ruby20 ruby1.9 ruby19 ruby1.9.1 ruby],
+ ruby-not-found)
+ if test "$RUBY" != "ruby-not-found"; then
ruby_version="`$RUBY --version`"
- if echo "$ruby_version" | grep -q -- 'ruby 1\.9'; then
+ if echo "$ruby_version" | grep -q -- 'ruby \(1\.9\|2\.\)'; then
ac_cv_ruby_available="yes"
else
- AC_MSG_WARN([$RUBY isn't Ruby 1.9 ($ruby_version)])
+ AC_MSG_WARN([$RUBY isn't Ruby 1.9 or later ($ruby_version)])
fi
fi
else
- ruby_not_found_warning_message="$RUBY is not found. Disable HTTP test."
+ ruby_not_found_warning_message="$RUBY is not found. Disable test."
case "$RUBY" in
/*)
AC_CHECK_FILE([$RUBY],
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/doc/text/Makefile.am b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/doc/text/Makefile.am
index 52dbe4a8f0d..6adf4f103e9 100644
--- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/doc/text/Makefile.am
+++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/doc/text/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (C) 2013 Kouhei Sutou <kou@clear-code.com>
+# Copyright (C) 2013-2015 Kouhei Sutou <kou@clear-code.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
@@ -16,4 +16,5 @@
docdir = $(datadir)/doc/$(PACKAGE)
dist_doc_DATA = \
- lgpl-2.0.txt
+ lgpl-2.0.txt \
+ news.md
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/doc/text/news.md b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/doc/text/news.md
new file mode 100644
index 00000000000..9f367a56671
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/doc/text/news.md
@@ -0,0 +1,12 @@
+# News
+
+## 1.0.8: 2015-02-10
+
+### Fixes
+
+ * Fix registering error when you build with configure.
+ [GitHub#3][Reported by Kazuhiko]
+
+### Thanks
+
+ * Kazuhiko
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/normalizers/CMakeLists.txt b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/normalizers/CMakeLists.txt
index ae290b66347..db8ffedb082 100644
--- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/normalizers/CMakeLists.txt
+++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/normalizers/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright(C) 2013 Kouhei Sutou <kou@clear-code.com>
+# Copyright(C) 2013-2015 Kouhei Sutou <kou@clear-code.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
@@ -17,11 +17,15 @@
set(NORMALIZERS_DIR "${GROONGA_PLUGINS_DIR}/normalizers")
read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/mysql_sources.am MYSQL_SOURCES)
-add_library(mysql_normalizer MODULE ${MYSQL_SOURCES})
-set_target_properties(mysql_normalizer PROPERTIES
- PREFIX ""
- OUTPUT_NAME "mysql")
-target_link_libraries(mysql_normalizer ${GROONGA_LIBRARIES})
-if(NOT MRN_GROONGA_BUNDLED)
+if(GROONGA_NORMALIZER_MYSQL_EMBED)
+ add_convenience_library(mysql_normalizer ${MYSQL_SOURCES})
+ set_property(TARGET mysql_normalizer APPEND PROPERTY
+ COMPILE_DEFINITIONS "GROONGA_NORMALIZER_MYSQL_EMBED")
+else()
+ add_library(mysql_normalizer MODULE ${MYSQL_SOURCES})
+ set_target_properties(mysql_normalizer PROPERTIES
+ PREFIX ""
+ OUTPUT_NAME "mysql")
install(TARGETS mysql_normalizer DESTINATION "${NORMALIZERS_DIR}")
endif()
+target_link_libraries(mysql_normalizer ${GROONGA_LIBRARIES})
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/normalizers/mysql.c b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/normalizers/mysql.c
index 94acfb16389..d9e8de4d4a0 100644
--- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/normalizers/mysql.c
+++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/normalizers/mysql.c
@@ -1,6 +1,6 @@
/* -*- c-basic-offset: 2 -*- */
/*
- Copyright(C) 2013-2014 Kouhei Sutou <kou@clear-code.com>
+ Copyright(C) 2013-2015 Kouhei Sutou <kou@clear-code.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -18,6 +18,14 @@
MA 02110-1301, USA
*/
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef GROONGA_NORMALIZER_MYSQL_EMBED
+# define GRN_PLUGIN_FUNCTION_TAG normalizers_mysql
+#endif
+
#include <groonga/normalizer.h>
#include <groonga/nfkc.h>
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/apt/Vagrantfile b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/apt/Vagrantfile
index 97ba2496071..a7e11791feb 100644
--- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/apt/Vagrantfile
+++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/apt/Vagrantfile
@@ -8,12 +8,11 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
vms = [
{
:id => "debian-wheezy-i386",
- :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_debian-7.6-i386_chef-provisionerless.box
-",
+ :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_debian-7.8-i386_chef-provisionerless.box",
},
{
:id => "debian-wheezy-amd64",
- :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_debian-7.6_chef-provisionerless.box",
+ :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_debian-7.8_chef-provisionerless.box",
},
]
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/apt/build-deb.sh b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/apt/build-deb.sh
index fdfc8f52f03..21bf8af6b35 100755
--- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/apt/build-deb.sh
+++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/apt/build-deb.sh
@@ -54,4 +54,4 @@ run cd -
package_initial=$(echo "${PACKAGE}" | sed -e 's/\(.\).*/\1/')
pool_dir="/vagrant/repositories/${distribution}/pool/${code_name}/${component}/${package_initial}/${PACKAGE}"
run mkdir -p "${pool_dir}/"
-run cp *.tar.gz *.dsc *.deb "${pool_dir}/"
+run cp *.tar.gz *.diff.gz *.dsc *.deb "${pool_dir}/"
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/changelog b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/changelog
index 245c138a35a..a02be693955 100644
--- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/changelog
+++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/changelog
@@ -1,3 +1,15 @@
+groonga-normalizer-mysql (1.0.8-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Kouhei Sutou <kou@clear-code.com> Tue, 10 Feb 2015 00:00:00 +0900
+
+groonga-normalizer-mysql (1.0.7-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- <hayashi@clear-code.com> Mon, 09 Feb 2015 00:00:00 +0900
+
groonga-normalizer-mysql (1.0.6-1) unstable; urgency=low
* New upstream release.
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/control b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/control
index 20c456b0a76..37a3805d966 100644
--- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/control
+++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/control
@@ -1,25 +1,31 @@
Source: groonga-normalizer-mysql
Section: libs
Priority: optional
-Maintainer: Kouhei Sutou <kou@clear-code.com>
+Maintainer: Groonga Project <packages@groonga.org>
Build-Depends:
debhelper (>= 9),
autotools-dev,
pkg-config,
libgroonga-dev (>= 3.0.0)
Standards-Version: 3.9.3
-Homepage: http://groonga.org/
+Homepage: https://github.com/groonga/groonga-normalizer-mysql
Package: groonga-normalizer-mysql
-Section: libs
Architecture: any
Depends:
${misc:Depends},
${shlibs:Depends},
libgroonga0
-Description: MySQL derived normalizer for groonga.
+Description: MySQL derived normalizer for Groonga
Groonga is an open-source fulltext search engine and column store.
- It lets you write high-performance applications that requires fulltext search.
+ It lets you write high-performance applications that requires fulltext
+ search.
.
- This package provides a normalizer which normalizes text as same as MySQL does.
-
+ This package provides a normalizer which normalizes text as same as
+ MySQL does.
+ .
+ Groonga has its own normalizers by default, but that behavior is a bit
+ defferent from MySQL does, so as a result, it affects search results.
+ These normalizers are useful if you regards it important for keeping
+ normalizer compatibility with MySQL in Mroonga which uses Groonga as
+ storage engine.
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/copyright b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/copyright
index cd3295a134c..79b0d9c4e1f 100644
--- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/copyright
+++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/copyright
@@ -1,29 +1,85 @@
-This package was debianized by Kouhei Sutou <kou@clear-code.com> on
-Tue, 29 Jan 2013 14:52:04 +0000.
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Contact: Kouhei Sutou <kou at clear-code.com>
+Source: http://packages.groonga.org/source/groonga-normalizer-mysql/
-It was downloaded from <http://groonga.org/>
+Files: *
+Copyright: 2013 Kouhei Sutou <kou@clear-code.com>
+License: LGPL-2
-Upstream Author(s):
+Files: debian/*
+Copyright: 2013 Kouhei Sutou <kou@clear-code.com>
+ 2013 HAYASHI Kentaro <hayashi@clear-code.com>
+License: LGPL-2
- Kouhei Sutou <kou at clear-code.com>
+Files: test/run-test.sh
+Copyright: 2013 Kouhei Sutou <kou@clear-code.com>
+License: LGPL-2+
-Copyright:
+Files: normalizers/mysql_general_ci_table.h
+Copyright: 2013 Kouhei Sutou <kou@clear-code.com>
+ 2000, 2012, Oracle and/or its affiliates
+License: LGPL-2
- Copyright(C) 2013 Brazil
+Files: normalizers/mysql_unicode_ci_*.h
+Copyright: 2013 Kouhei Sutou <kou@clear-code.com>
+ 2004, 2011, Oracle and/or its affiliates
+License: LGPL-2
-License:
+Files: ltmain.sh
+Copyright: 1996, Gordon Matzigkeit <gord@gnu.ai.mit.edu>
+ 1996-2011, Free Software Foundation, Inc.
+License: GPL-2+ with Libtool exception
+ GNU Libtool is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ .
+ As a special exception to the GNU General Public License,
+ if you distribute this file as part of a program or library that
+ is built using GNU Libtool, you may include this file under the
+ same distribution terms that you use for the rest of that program.
+ .
+ GNU Libtool is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+ .
+ You should have received a copy of the GNU General Public License
+ along with GNU Libtool; see the file COPYING. If not, a copy
+ can be downloaded from http://www.gnu.org/licenses/gpl.html,
+ or obtained by writing to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- This library is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 2 of the License.
+License: LGPL-2
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, version 2 of the License.
+ .
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+ .
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ .
+ The Debian packaging is (C) 2013, Kouhei Sutou <kou@clear-code.com> and
+ is licensed under the LGPL-2, see `/usr/share/common-licenses/LGPL-2'.
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-The Debian packaging is (C) 2013, Kouhei Sutou <kou@clear-code.com> and
-is licensed under the LGPL-2, see `/usr/share/common-licenses/LGPL-2'.
+License: LGPL-2+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+ .
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+ .
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ .
+ On Debian systems, the full text of the GNU Library General Public
+ License version 2 can be found in the file `/usr/share/common-licenses/LGPL-2'.
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/rules b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/rules
index 811e09274c0..753d4484cf8 100755
--- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/rules
+++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/rules
@@ -13,3 +13,5 @@ export DH_OPTIONS
override_dh_auto_test:
override_dh_install:
+ find $(CURDIR) -name '*.la' -delete
+ find $(CURDIR) -name 'lgpl-2.0.txt' -delete
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/watch b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/watch
new file mode 100644
index 00000000000..ab451e4c004
--- /dev/null
+++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/watch
@@ -0,0 +1,2 @@
+version=3
+http://packages.groonga.org/source/groonga-normalizer-mysql/groonga-normalizer-mysql-(.+).tar.gz
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/rpm/centos/groonga-normalizer-mysql.spec.in b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/rpm/centos/groonga-normalizer-mysql.spec.in
index e51bae6990d..b4751c43762 100644
--- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/rpm/centos/groonga-normalizer-mysql.spec.in
+++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/rpm/centos/groonga-normalizer-mysql.spec.in
@@ -42,7 +42,6 @@ make install DESTDIR=$RPM_BUILD_ROOT INSTALL="install -p"
rm $RPM_BUILD_ROOT%{_libdir}/groonga/plugins/*/*.la
%files
-%doc README AUTHORS COPYING
%dir %{_libdir}/groonga
%dir %{_libdir}/groonga/plugins
%dir %{_libdir}/groonga/plugins/normalizers
@@ -53,6 +52,12 @@ rm $RPM_BUILD_ROOT%{_libdir}/groonga/plugins/*/*.la
%{_libdir}/pkgconfig/groonga-normalizer-mysql.pc
%changelog
+* Tue Feb 10 2015 Kouhei Sutou <kou@clear-code.com> - 1.0.8-1
+- new upstream release.
+
+* Mon Feb 09 2015 HAYASHI Kentaro <hayashi@clear-code.com> - 1.0.7-1
+- new upstream release.
+
* Sun Feb 09 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 1.0.6-1
- new upstream release.
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/rpm/fedora/groonga-normalizer-mysql.spec.in b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/rpm/fedora/groonga-normalizer-mysql.spec.in
index 3be5e0797db..fbde53c117f 100644
--- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/rpm/fedora/groonga-normalizer-mysql.spec.in
+++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/rpm/fedora/groonga-normalizer-mysql.spec.in
@@ -41,7 +41,6 @@ make install DESTDIR=$RPM_BUILD_ROOT INSTALL="install -p"
rm $RPM_BUILD_ROOT%{_libdir}/groonga/plugins/*/*.la
%files
-%doc README AUTHORS COPYING
%dir %{_libdir}/groonga
%dir %{_libdir}/groonga/plugins
%dir %{_libdir}/groonga/plugins/normalizers
@@ -52,6 +51,12 @@ rm $RPM_BUILD_ROOT%{_libdir}/groonga/plugins/*/*.la
%{_libdir}/pkgconfig/groonga-normalizer-mysql.pc
%changelog
+* Tue Feb 10 2015 Kouhei Sutou <kou@clear-code.com> - 1.0.8-1
+- new upstream release.
+
+* Mon Feb 09 2015 <hayashi@clear-code.com> - 1.0.7-1
+- new upstream release.
+
* Sun Feb 09 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 1.0.6-1
- new upstream release.
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/ubuntu/Makefile.am b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/ubuntu/Makefile.am
index 3b616910900..4afc4a982f0 100644
--- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/ubuntu/Makefile.am
+++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/ubuntu/Makefile.am
@@ -1,4 +1,4 @@
-CODE_NAMES = precise,trusty
+CODE_NAMES = precise,trusty,utopic
SOURCE = ../$(PACKAGE)-$(VERSION).tar.gz
all:
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/yum/Makefile.am b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/yum/Makefile.am
index ea62f6e427e..edd546fbae1 100644
--- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/yum/Makefile.am
+++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/yum/Makefile.am
@@ -1,7 +1,6 @@
REPOSITORIES_PATH = repositories
DISTRIBUTIONS = centos
ARCHITECTURES = i386 x86_64
-HAVE_DEVELOPMENT_BRANCH = no
release: download build sign-packages update-repository upload
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/yum/Vagrantfile b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/yum/Vagrantfile
index 4238d678721..87866a3a0ac 100644
--- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/yum/Vagrantfile
+++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/yum/Vagrantfile
@@ -8,19 +8,19 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
vms = [
{
:id => "centos-5-i386",
- :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-5.10-i386_chef-provisionerless.box",
+ :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-5.11-i386_chef-provisionerless.box",
},
{
:id => "centos-5-x86_64",
- :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-5.10_chef-provisionerless.box",
+ :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-5.11_chef-provisionerless.box",
},
{
:id => "centos-6-i386",
- :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.5-i386_chef-provisionerless.box",
+ :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.6-i386_chef-provisionerless.box",
},
{
:id => "centos-6-x86_64",
- :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.5_chef-provisionerless.box",
+ :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.6_chef-provisionerless.box",
},
{
:id => "centos-7-x86_64",
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/version b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/version
index ece61c60124..337a6a8f189 100644
--- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/version
+++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/version
@@ -1 +1 @@
-1.0.6 \ No newline at end of file
+1.0.8 \ No newline at end of file
diff --git a/storage/mroonga/version b/storage/mroonga/version
index b0372476047..2defa1a3bb8 100644
--- a/storage/mroonga/version
+++ b/storage/mroonga/version
@@ -1 +1 @@
-4.06 \ No newline at end of file
+5.00 \ No newline at end of file
diff --git a/storage/mroonga/version_in_hex b/storage/mroonga/version_in_hex
index 6f503be55dd..960c1688afd 100644
--- a/storage/mroonga/version_in_hex
+++ b/storage/mroonga/version_in_hex
@@ -1 +1 @@
-0x0406 \ No newline at end of file
+0x0500 \ No newline at end of file
diff --git a/storage/mroonga/version_major b/storage/mroonga/version_major
index bf0d87ab1b2..7813681f5b4 100644
--- a/storage/mroonga/version_major
+++ b/storage/mroonga/version_major
@@ -1 +1 @@
-4 \ No newline at end of file
+5 \ No newline at end of file
diff --git a/storage/mroonga/version_micro b/storage/mroonga/version_micro
index 62f9457511f..c227083464f 100644
--- a/storage/mroonga/version_micro
+++ b/storage/mroonga/version_micro
@@ -1 +1 @@
-6 \ No newline at end of file
+0 \ No newline at end of file
diff --git a/storage/spider/CMakeLists.txt b/storage/spider/CMakeLists.txt
index cdb2de45ee6..33786e2b85a 100644
--- a/storage/spider/CMakeLists.txt
+++ b/storage/spider/CMakeLists.txt
@@ -1,6 +1,11 @@
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_HANDLERSOCKET")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DHAVE_HANDLERSOCKET")
+IF(HAVE_WVLA)
+ SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wno-vla")
+ SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wno-vla")
+ENDIF()
+
SET(SPIDER_SOURCES
spd_param.cc spd_sys_table.cc spd_trx.cc spd_db_conn.cc spd_conn.cc
spd_table.cc spd_direct_sql.cc spd_udf.cc spd_ping_table.cc
diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc
index 2944e750b88..40d5c0e8450 100644
--- a/storage/spider/ha_spider.cc
+++ b/storage/spider/ha_spider.cc
@@ -18,7 +18,6 @@
#endif
#define MYSQL_SERVER 1
-#include <my_global.h>
#include "mysql_version.h"
#if MYSQL_VERSION_ID < 50500
#include "mysql_priv.h"
@@ -28,6 +27,9 @@
#include "probes_mysql.h"
#include "sql_class.h"
#include "key.h"
+#ifdef HANDLER_HAS_DIRECT_AGGREGATE
+#include "sql_select.h"
+#endif
#endif
#include "ha_partition.h"
#include "spd_param.h"
@@ -92,7 +94,7 @@ ha_spider::ha_spider(
mrr_key_buff = NULL;
#endif
append_tblnm_alias = NULL;
- has_clone_for_merge = FALSE;
+ use_index_merge = FALSE;
is_clone = FALSE;
clone_bitmap_init = FALSE;
pt_clone_source_handler = NULL;
@@ -162,6 +164,7 @@ ha_spider::ha_spider(
result_list.direct_distinct = FALSE;
result_list.casual_read = NULL;
result_list.use_both_key = FALSE;
+ result_list.in_cmp_ref = FALSE;
DBUG_VOID_RETURN;
}
@@ -199,7 +202,7 @@ ha_spider::ha_spider(
mrr_key_buff = NULL;
#endif
append_tblnm_alias = NULL;
- has_clone_for_merge = FALSE;
+ use_index_merge = FALSE;
is_clone = FALSE;
clone_bitmap_init = FALSE;
pt_clone_source_handler = NULL;
@@ -269,6 +272,7 @@ ha_spider::ha_spider(
result_list.direct_distinct = FALSE;
result_list.casual_read = NULL;
result_list.use_both_key = FALSE;
+ result_list.in_cmp_ref = FALSE;
ref_length = sizeof(SPIDER_POSITION);
DBUG_VOID_RETURN;
}
@@ -300,7 +304,7 @@ handler *ha_spider::clone(
HA_OPEN_IGNORE_IF_LOCKED))
DBUG_RETURN(NULL);
spider->sync_from_clone_source_base(this);
- has_clone_for_merge = TRUE;
+ use_index_merge = TRUE;
DBUG_RETURN((handler *) spider);
}
@@ -1735,7 +1739,8 @@ int ha_spider::reset()
result_list.use_both_key = FALSE;
pt_clone_last_searcher = NULL;
conn_kinds = SPIDER_CONN_KIND_MYSQL;
- has_clone_for_merge = FALSE;
+ use_index_merge = FALSE;
+ init_rnd_handler = FALSE;
while (condition)
{
tmp_cond = condition->next;
@@ -1854,6 +1859,35 @@ int ha_spider::extra(
DBUG_RETURN(error_num);
break;
#endif
+#ifdef HA_EXTRA_HAS_HA_EXTRA_USE_CMP_REF
+ case HA_EXTRA_USE_CMP_REF:
+ DBUG_PRINT("info",("spider HA_EXTRA_USE_CMP_REF"));
+ if (table_share->primary_key != MAX_KEY)
+ {
+ DBUG_PRINT("info",("spider need primary key columns"));
+ KEY *key_info = &table->key_info[table->s->primary_key];
+ KEY_PART_INFO *key_part;
+ uint part_num;
+ for (
+ key_part = key_info->key_part, part_num = 0;
+ part_num < spider_user_defined_key_parts(key_info);
+ key_part++, part_num++
+ ) {
+ spider_set_bit(searched_bitmap, key_part->field->field_index);
+ }
+ } else {
+ DBUG_PRINT("info",("spider need all columns"));
+ Field **field;
+ for (
+ field = table->field;
+ *field;
+ field++
+ ) {
+ spider_set_bit(searched_bitmap, (*field)->field_index);
+ }
+ }
+ break;
+#endif
default:
break;
}
@@ -4437,6 +4471,7 @@ int ha_spider::read_multi_range_first_internal(
result_list.keyread = TRUE;
else
result_list.keyread = FALSE;
+ mrr_with_cnt = FALSE;
if (
(error_num = spider_db_append_select(this)) ||
(error_num = spider_db_append_select_columns(this))
@@ -7649,6 +7684,7 @@ int ha_spider::cmp_ref(
DBUG_PRINT("info",("spider this=%p", this));
DBUG_PRINT("info",("spider ref1=%p", ref1));
DBUG_PRINT("info",("spider ref2=%p", ref2));
+ result_list.in_cmp_ref = TRUE;
if (table_share->primary_key < MAX_KEY)
{
uchar table_key[MAX_KEY_LENGTH];
@@ -7680,6 +7716,7 @@ int ha_spider::cmp_ref(
}
}
}
+ result_list.in_cmp_ref = FALSE;
DBUG_PRINT("info",("spider ret=%d", ret));
DBUG_RETURN(ret);
}
@@ -8685,7 +8722,7 @@ ha_rows ha_spider::records_in_range(
key_part_map end_key_part_map;
key_part_map tgt_key_part_map;
KEY_PART_INFO *key_part;
- Field *field;
+ Field *field = NULL;
double rows = (double) share->records;
double weight, rate;
DBUG_PRINT("info",("spider rows1=%f", rows));
@@ -10967,7 +11004,11 @@ bool ha_spider::is_crashed() const
DBUG_RETURN(FALSE);
}
+#ifdef SPIDER_HANDLER_AUTO_REPAIR_HAS_ERROR
+bool ha_spider::auto_repair(int error) const
+#else
bool ha_spider::auto_repair() const
+#endif
{
DBUG_ENTER("ha_spider::auto_repair");
DBUG_PRINT("info",("spider this=%p", this));
@@ -11452,6 +11493,16 @@ TABLE *ha_spider::get_table()
DBUG_RETURN(table);
}
+TABLE *ha_spider::get_top_table()
+{
+ DBUG_ENTER("ha_spider::get_top_table");
+#ifdef HANDLER_HAS_TOP_TABLE_FIELDS
+ if (set_top_table_fields)
+ DBUG_RETURN(top_table);
+#endif
+ DBUG_RETURN(table);
+}
+
void ha_spider::set_ft_discard_bitmap()
{
DBUG_ENTER("ha_spider::set_ft_discard_bitmap");
@@ -13819,6 +13870,18 @@ int ha_spider::append_key_order_for_merge_with_alias_sql_part(
uint roop_count, dbton_id;
spider_db_handler *dbton_hdl;
DBUG_ENTER("ha_spider::append_key_order_for_merge_with_alias_sql_part");
+#ifdef HANDLER_HAS_DIRECT_AGGREGATE
+ if (result_list.direct_aggregate)
+ {
+ st_select_lex *select_lex = spider_get_select_lex(this);
+ ORDER *group = (ORDER *) select_lex->group_list.first;
+ if (!group && *(select_lex->join->sum_funcs))
+ {
+ DBUG_PRINT("info",("spider skip order by"));
+ DBUG_RETURN(0);
+ }
+ }
+#endif
for (roop_count = 0; roop_count < share->use_sql_dbton_count; roop_count++)
{
dbton_id = share->use_sql_dbton_ids[roop_count];
@@ -13868,6 +13931,18 @@ int ha_spider::append_key_order_with_alias_sql_part(
uint roop_count, dbton_id;
spider_db_handler *dbton_hdl;
DBUG_ENTER("ha_spider::append_key_order_with_alias_sql_part");
+#ifdef HANDLER_HAS_DIRECT_AGGREGATE
+ if (result_list.direct_aggregate)
+ {
+ st_select_lex *select_lex = spider_get_select_lex(this);
+ ORDER *group = (ORDER *) select_lex->group_list.first;
+ if (!group && *(select_lex->join->sum_funcs))
+ {
+ DBUG_PRINT("info",("spider skip order by"));
+ DBUG_RETURN(0);
+ }
+ }
+#endif
for (roop_count = 0; roop_count < share->use_sql_dbton_count; roop_count++)
{
dbton_id = share->use_sql_dbton_ids[roop_count];
diff --git a/storage/spider/ha_spider.h b/storage/spider/ha_spider.h
index fc880831912..0c81bef1773 100644
--- a/storage/spider/ha_spider.h
+++ b/storage/spider/ha_spider.h
@@ -125,7 +125,7 @@ public:
bool clone_bitmap_init;
ha_spider *pt_clone_source_handler;
ha_spider *pt_clone_last_searcher;
- bool has_clone_for_merge;
+ bool use_index_merge;
bool init_index_handler;
bool init_rnd_handler;
@@ -682,7 +682,11 @@ public:
const char *name
);
bool is_crashed() const;
+#ifdef SPIDER_HANDLER_AUTO_REPAIR_HAS_ERROR
+ bool auto_repair(int error) const;
+#else
bool auto_repair() const;
+#endif
int disable_indexes(
uint mode
);
@@ -730,6 +734,7 @@ public:
void return_record_by_parent();
#endif
TABLE *get_table();
+ TABLE *get_top_table();
void set_ft_discard_bitmap();
void set_searched_bitmap();
void set_clone_searched_bitmap();
diff --git a/storage/spider/spd_conn.cc b/storage/spider/spd_conn.cc
index ce786a7b697..e19222c99f6 100644
--- a/storage/spider/spd_conn.cc
+++ b/storage/spider/spd_conn.cc
@@ -14,7 +14,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define MYSQL_SERVER 1
-#include <my_global.h>
#include "mysql_version.h"
#if MYSQL_VERSION_ID < 50500
#include "mysql_priv.h"
diff --git a/storage/spider/spd_copy_tables.cc b/storage/spider/spd_copy_tables.cc
index dae0d94d7aa..10fed696134 100644
--- a/storage/spider/spd_copy_tables.cc
+++ b/storage/spider/spd_copy_tables.cc
@@ -14,7 +14,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define MYSQL_SERVER 1
-#include <my_global.h>
#include "mysql_version.h"
#if MYSQL_VERSION_ID < 50500
#include "mysql_priv.h"
diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc
index 81b6fae841f..30ad38eceb0 100644
--- a/storage/spider/spd_db_conn.cc
+++ b/storage/spider/spd_db_conn.cc
@@ -14,7 +14,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define MYSQL_SERVER 1
-#include <my_global.h>
#include "mysql_version.h"
#if MYSQL_VERSION_ID < 50500
#include "mysql_priv.h"
@@ -515,6 +514,7 @@ int spider_db_before_query(
int *need_mon
) {
int error_num;
+ bool tmp_mta_conn_mutex_lock_already;
DBUG_ENTER("spider_db_before_query");
DBUG_ASSERT(need_mon);
#ifndef WITHOUT_SPIDER_BG_SEARCH
@@ -529,11 +529,15 @@ int spider_db_before_query(
conn->need_mon = need_mon;
}
DBUG_ASSERT(conn->mta_conn_mutex_file_pos.file_name);
+ tmp_mta_conn_mutex_lock_already = conn->mta_conn_mutex_lock_already;
+ conn->mta_conn_mutex_lock_already = TRUE;
if ((error_num = spider_db_conn_queue_action(conn)))
{
conn->in_before_query = FALSE;
+ conn->mta_conn_mutex_lock_already = tmp_mta_conn_mutex_lock_already;
DBUG_RETURN(error_num);
}
+ conn->mta_conn_mutex_lock_already = tmp_mta_conn_mutex_lock_already;
if (conn->server_lost)
{
conn->in_before_query = FALSE;
@@ -2564,7 +2568,11 @@ int spider_db_fetch_for_item_sum_func(
{
Item *free_list = thd->free_list;
spider->direct_aggregate_item_current->item =
+#ifdef SPIDER_ITEM_STRING_WITHOUT_SET_STR_WITH_COPY
+ new Item_string("", 0, share->access_charset);
+#else
new Item_string(share->access_charset);
+#endif
if (!spider->direct_aggregate_item_current->item)
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
thd->free_list = free_list;
@@ -2575,7 +2583,12 @@ int spider_db_fetch_for_item_sum_func(
(Item_string *) spider->direct_aggregate_item_current->item;
if (row->is_null())
{
+#ifdef SPIDER_ITEM_STRING_WITHOUT_SET_STR_WITH_COPY
+ item->val_str(NULL)->length(0);
+ item->append(NULL, 0);
+#else
item->set_str_with_copy(NULL, 0);
+#endif
item->null_value = TRUE;
} else {
char buf[MAX_FIELD_WIDTH];
@@ -2584,7 +2597,12 @@ int spider_db_fetch_for_item_sum_func(
tmp_str.length(0);
if ((error_num = row->append_to_str(&tmp_str)))
DBUG_RETURN(error_num);
+#ifdef SPIDER_ITEM_STRING_WITHOUT_SET_STR_WITH_COPY
+ item->val_str(NULL)->length(0);
+ item->append((char *) tmp_str.ptr(), tmp_str.length());
+#else
item->set_str_with_copy(tmp_str.ptr(), tmp_str.length());
+#endif
item->null_value = FALSE;
}
item_hybrid->direct_add(item);
@@ -3279,8 +3297,11 @@ void spider_db_free_one_result(
if (result->result)
{
result->result->free_result();
- delete result->result;
- result->result = NULL;
+ if (!result->tmp_tbl_use_position)
+ {
+ delete result->result;
+ result->result = NULL;
+ }
}
if (!result->tmp_tbl_use_position)
{
@@ -4964,11 +4985,14 @@ int spider_db_seek_tmp_table(
DBUG_PRINT("info", ("spider row=%p", row));
#ifdef HANDLER_HAS_DIRECT_AGGREGATE
- DBUG_PRINT("info", ("spider direct_aggregate=%s",
- pos->direct_aggregate ? "TRUE" : "FALSE"));
- spider->result_list.snap_mrr_with_cnt = pos->mrr_with_cnt;
- spider->result_list.snap_direct_aggregate = pos->direct_aggregate;
- spider->result_list.snap_row = row;
+ if (!spider->result_list.in_cmp_ref)
+ {
+ DBUG_PRINT("info", ("spider direct_aggregate=%s",
+ pos->direct_aggregate ? "TRUE" : "FALSE"));
+ spider->result_list.snap_mrr_with_cnt = pos->mrr_with_cnt;
+ spider->result_list.snap_direct_aggregate = pos->direct_aggregate;
+ spider->result_list.snap_row = row;
+ }
#endif
/* for mrr */
@@ -5052,11 +5076,14 @@ int spider_db_seek_tmp_key(
DBUG_PRINT("info", ("spider row=%p", row));
#ifdef HANDLER_HAS_DIRECT_AGGREGATE
- DBUG_PRINT("info", ("spider direct_aggregate=%s",
- pos->direct_aggregate ? "TRUE" : "FALSE"));
- spider->result_list.snap_mrr_with_cnt = pos->mrr_with_cnt;
- spider->result_list.snap_direct_aggregate = pos->direct_aggregate;
- spider->result_list.snap_row = row;
+ if (!spider->result_list.in_cmp_ref)
+ {
+ DBUG_PRINT("info", ("spider direct_aggregate=%s",
+ pos->direct_aggregate ? "TRUE" : "FALSE"));
+ spider->result_list.snap_mrr_with_cnt = pos->mrr_with_cnt;
+ spider->result_list.snap_direct_aggregate = pos->direct_aggregate;
+ spider->result_list.snap_row = row;
+ }
#endif
/* for mrr */
@@ -5133,11 +5160,14 @@ int spider_db_seek_tmp_minimum_columns(
DBUG_PRINT("info", ("spider row=%p", row));
#ifdef HANDLER_HAS_DIRECT_AGGREGATE
- DBUG_PRINT("info", ("spider direct_aggregate=%s",
- pos->direct_aggregate ? "TRUE" : "FALSE"));
- spider->result_list.snap_mrr_with_cnt = pos->mrr_with_cnt;
- spider->result_list.snap_direct_aggregate = pos->direct_aggregate;
- spider->result_list.snap_row = row;
+ if (!spider->result_list.in_cmp_ref)
+ {
+ DBUG_PRINT("info", ("spider direct_aggregate=%s",
+ pos->direct_aggregate ? "TRUE" : "FALSE"));
+ spider->result_list.snap_mrr_with_cnt = pos->mrr_with_cnt;
+ spider->result_list.snap_direct_aggregate = pos->direct_aggregate;
+ spider->result_list.snap_row = row;
+ }
#endif
/* for mrr */
@@ -8088,19 +8118,24 @@ int spider_db_open_item_string(
spider_string tmp_str(tmp_buf, MAX_FIELD_WIDTH, str->charset());
String *tmp_str2;
tmp_str.init_calc_mem(126);
- if (
- !(tmp_str2 = item->val_str(tmp_str.get_str())) ||
- str->reserve(SPIDER_SQL_VALUE_QUOTE_LEN * 2 + tmp_str2->length() * 2)
- )
- DBUG_RETURN(HA_ERR_OUT_OF_MEM);
- tmp_str.mem_calc();
- str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN);
- if (
- str->append_for_single_quote(tmp_str2) ||
- str->reserve(SPIDER_SQL_VALUE_QUOTE_LEN)
- )
- DBUG_RETURN(HA_ERR_OUT_OF_MEM);
- str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN);
+ if (!(tmp_str2 = item->val_str(tmp_str.get_str())))
+ {
+ if (str->reserve(SPIDER_SQL_NULL_LEN))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ str->q_append(SPIDER_SQL_NULL_STR, SPIDER_SQL_NULL_LEN);
+ } else {
+ if (str->reserve(SPIDER_SQL_VALUE_QUOTE_LEN * 2 +
+ tmp_str2->length() * 2))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ tmp_str.mem_calc();
+ str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN);
+ if (
+ str->append_for_single_quote(tmp_str2) ||
+ str->reserve(SPIDER_SQL_VALUE_QUOTE_LEN)
+ )
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN);
+ }
}
DBUG_RETURN(0);
}
diff --git a/storage/spider/spd_db_handlersocket.cc b/storage/spider/spd_db_handlersocket.cc
index d1eb68679b2..9d0b05855d5 100644
--- a/storage/spider/spd_db_handlersocket.cc
+++ b/storage/spider/spd_db_handlersocket.cc
@@ -14,7 +14,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define MYSQL_SERVER 1
-#include <my_global.h>
#include "mysql_version.h"
#if MYSQL_VERSION_ID < 50500
#include "mysql_priv.h"
@@ -5543,7 +5542,7 @@ void spider_handlersocket_handler::minimum_select_bitmap_create()
DBUG_ENTER("spider_handlersocket_handler::minimum_select_bitmap_create");
memset(minimum_select_bitmap, 0, no_bytes_in_map(table->read_set));
if (
- spider->has_clone_for_merge ||
+ spider->use_index_merge ||
#ifdef HA_CAN_BULK_ACCESS
(spider->is_clone && !spider->is_bulk_access_clone)
#else
diff --git a/storage/spider/spd_db_include.h b/storage/spider/spd_db_include.h
index 371257a955b..c70995ec007 100644
--- a/storage/spider/spd_db_include.h
+++ b/storage/spider/spd_db_include.h
@@ -24,6 +24,9 @@
#define SPIDER_HAS_DISCOVER_TABLE_STRUCTURE
#define SPIDER_HAS_APPEND_FOR_SINGLE_QUOTE
#define SPIDER_HAS_SHOW_SIMPLE_FUNC
+#define SPIDER_HAS_JT_HASH_INDEX_MERGE
+#else
+#define SPIDER_NEED_CHECK_CONDITION_AT_CHECKING_DIRECT_ORDER_LIMIT
#endif
#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100007
@@ -36,8 +39,13 @@
#define SPIDER_HAS_DECIMAL_OPERATION_RESULTS_VALUE_TYPE
#endif
+#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100014
+#define SPIDER_ITEM_STRING_WITHOUT_SET_STR_WITH_COPY
+#endif
+
#if defined(MARIADB_BASE_VERSION)
#define SPIDER_ITEM_GEOFUNC_NAME_HAS_MBR
+#define SPIDER_HANDLER_AUTO_REPAIR_HAS_ERROR
#endif
class spider_db_conn;
@@ -1649,6 +1657,7 @@ typedef struct st_spider_result_list
bool snap_direct_aggregate;
SPIDER_DB_ROW *snap_row;
#endif
+ bool in_cmp_ref;
bool set_split_read;
bool insert_dup_update_pushdown;
longlong split_read_base;
diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc
index f60220ee38b..e4d9d150bcd 100644
--- a/storage/spider/spd_db_mysql.cc
+++ b/storage/spider/spd_db_mysql.cc
@@ -14,7 +14,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define MYSQL_SERVER 1
-#include <my_global.h>
#include "mysql_version.h"
#if MYSQL_VERSION_ID < 50500
#include "mysql_priv.h"
@@ -7269,11 +7268,16 @@ int spider_mysql_handler::append_update_where(
Field **field;
SPIDER_SHARE *share = spider->share;
DBUG_ENTER("spider_mysql_handler::append_update_where");
+ DBUG_PRINT("info", ("spider table->s->primary_key=%s",
+ table->s->primary_key != MAX_KEY ? "TRUE" : "FALSE"));
if (str->reserve(SPIDER_SQL_WHERE_LEN))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
str->q_append(SPIDER_SQL_WHERE_STR, SPIDER_SQL_WHERE_LEN);
for (field = table->field; *field; field++)
{
+ DBUG_PRINT("info", ("spider bitmap=%s",
+ bitmap_is_set(table->read_set, (*field)->field_index) ?
+ "TRUE" : "FALSE"));
if (
table->s->primary_key == MAX_KEY ||
bitmap_is_set(table->read_set, (*field)->field_index)
@@ -11444,7 +11448,7 @@ void spider_mysql_handler::minimum_select_bitmap_create()
DBUG_PRINT("info",("spider this=%p", this));
memset(minimum_select_bitmap, 0, no_bytes_in_map(table->read_set));
if (
- spider->has_clone_for_merge ||
+ spider->use_index_merge ||
#ifdef HA_CAN_BULK_ACCESS
(spider->is_clone && !spider->is_bulk_access_clone)
#else
diff --git a/storage/spider/spd_db_oracle.cc b/storage/spider/spd_db_oracle.cc
index 0464d2b576d..d536020e513 100644
--- a/storage/spider/spd_db_oracle.cc
+++ b/storage/spider/spd_db_oracle.cc
@@ -14,7 +14,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define MYSQL_SERVER 1
-#include <my_global.h>
#include "mysql_version.h"
#if MYSQL_VERSION_ID < 50500
#include "mysql_priv.h"
@@ -11647,7 +11646,7 @@ void spider_oracle_handler::minimum_select_bitmap_create()
DBUG_ENTER("spider_oracle_handler::minimum_select_bitmap_create");
memset(minimum_select_bitmap, 0, no_bytes_in_map(table->read_set));
if (
- spider->has_clone_for_merge ||
+ spider->use_index_merge ||
#ifdef HA_CAN_BULK_ACCESS
(spider->is_clone && !spider->is_bulk_access_clone)
#else
diff --git a/storage/spider/spd_direct_sql.cc b/storage/spider/spd_direct_sql.cc
index 7149502d8f6..27041790d63 100644
--- a/storage/spider/spd_direct_sql.cc
+++ b/storage/spider/spd_direct_sql.cc
@@ -14,7 +14,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define MYSQL_SERVER 1
-#include <my_global.h>
#include "mysql_version.h"
#if MYSQL_VERSION_ID < 50500
#include "mysql_priv.h"
diff --git a/storage/spider/spd_i_s.cc b/storage/spider/spd_i_s.cc
index 025878b6253..49824693984 100644
--- a/storage/spider/spd_i_s.cc
+++ b/storage/spider/spd_i_s.cc
@@ -14,7 +14,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define MYSQL_SERVER 1
-#include <my_global.h>
#include "mysql_version.h"
#if MYSQL_VERSION_ID < 50500
#include "mysql_priv.h"
diff --git a/storage/spider/spd_include.h b/storage/spider/spd_include.h
index f6952e5398e..9c7eebb65c8 100644
--- a/storage/spider/spd_include.h
+++ b/storage/spider/spd_include.h
@@ -13,7 +13,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#define SPIDER_DETAIL_VERSION "3.2.11"
+#define SPIDER_DETAIL_VERSION "3.2.18"
#define SPIDER_HEX_VERSION 0x0302
#if MYSQL_VERSION_ID < 50500
@@ -70,6 +70,7 @@
#define spider_stmt_da_message(A) thd_get_error_message(A)
#define spider_stmt_da_sql_errno(A) thd_get_error_number(A)
#define spider_user_defined_key_parts(A) (A)->user_defined_key_parts
+#define spider_join_table_count(A) (A)->table_count
#define SPIDER_CAN_BG_UPDATE (1LL << 39)
#define SPIDER_ALTER_ADD_PARTITION Alter_info::ALTER_ADD_PARTITION
#define SPIDER_ALTER_DROP_PARTITION Alter_info::ALTER_DROP_PARTITION
@@ -94,6 +95,7 @@
#endif
#endif
#define spider_user_defined_key_parts(A) (A)->key_parts
+#define spider_join_table_count(A) (A)->tables
#define SPIDER_ALTER_ADD_PARTITION ALTER_ADD_PARTITION
#define SPIDER_ALTER_DROP_PARTITION ALTER_DROP_PARTITION
#define SPIDER_ALTER_COALESCE_PARTITION ALTER_COALESCE_PARTITION
@@ -105,6 +107,10 @@
#define SPIDER_THD_KILL_CONNECTION THD::KILL_CONNECTION
#endif
+#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100005
+#define SPIDER_HAS_EXPLAIN_QUERY
+#endif
+
#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100009
#define SPIDER_TEST(A) MY_TEST(A)
#else
diff --git a/storage/spider/spd_malloc.cc b/storage/spider/spd_malloc.cc
index 56fb3c9ccd2..4a033c1e7cf 100644
--- a/storage/spider/spd_malloc.cc
+++ b/storage/spider/spd_malloc.cc
@@ -14,7 +14,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define MYSQL_SERVER 1
-#include <my_global.h>
#include "mysql_version.h"
#if MYSQL_VERSION_ID < 50500
#include "mysql_priv.h"
diff --git a/storage/spider/spd_param.cc b/storage/spider/spd_param.cc
index 387d17134e5..2b1e87313d1 100644
--- a/storage/spider/spd_param.cc
+++ b/storage/spider/spd_param.cc
@@ -14,7 +14,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define MYSQL_SERVER 1
-#include <my_global.h>
#include "mysql_version.h"
#if MYSQL_VERSION_ID < 50500
#include "mysql_priv.h"
diff --git a/storage/spider/spd_ping_table.cc b/storage/spider/spd_ping_table.cc
index 8c55b0fc683..d32dbec2421 100644
--- a/storage/spider/spd_ping_table.cc
+++ b/storage/spider/spd_ping_table.cc
@@ -14,7 +14,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define MYSQL_SERVER 1
-#include <my_global.h>
#include "mysql_version.h"
#if MYSQL_VERSION_ID < 50500
#include "mysql_priv.h"
diff --git a/storage/spider/spd_sys_table.cc b/storage/spider/spd_sys_table.cc
index 7b46889a135..1ff3496d83e 100644
--- a/storage/spider/spd_sys_table.cc
+++ b/storage/spider/spd_sys_table.cc
@@ -14,7 +14,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define MYSQL_SERVER 1
-#include <my_global.h>
#include "mysql_version.h"
#if MYSQL_VERSION_ID < 50500
#include "mysql_priv.h"
diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc
index ba845426d49..36768ae85c1 100644
--- a/storage/spider/spd_table.cc
+++ b/storage/spider/spd_table.cc
@@ -14,7 +14,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define MYSQL_SERVER 1
-#include <my_global.h>
#include "mysql_version.h"
#if MYSQL_VERSION_ID < 50500
#include "mysql_priv.h"
@@ -7730,6 +7729,7 @@ longlong spider_split_read_param(
DBUG_RETURN(result_list->semi_split_read_base);
}
spider_get_select_limit(spider, &select_lex, &select_limit, &offset_limit);
+ DBUG_PRINT("info",("spider result_list->set_split_read=%s", result_list->set_split_read ? "TRUE" : "FALSE"));
if (!result_list->set_split_read)
{
int bulk_update_mode = spider_param_bulk_update_mode(thd,
@@ -7803,6 +7803,7 @@ longlong spider_split_read_param(
result_list->set_split_read = TRUE;
DBUG_RETURN(9223372036854775807LL);
}
+#ifdef SPIDER_HAS_EXPLAIN_QUERY
Explain_query *explain = thd->lex->explain;
bool filesort = FALSE;
if (explain)
@@ -7827,18 +7828,23 @@ longlong spider_split_read_param(
}
}
}
+#endif
result_list->split_read_base =
spider_param_split_read(thd, share->split_read);
+#ifdef SPIDER_HAS_EXPLAIN_QUERY
if (filesort)
{
result_list->semi_split_read = 0;
result_list->semi_split_read_limit = 9223372036854775807LL;
} else {
+#endif
result_list->semi_split_read =
spider_param_semi_split_read(thd, share->semi_split_read);
result_list->semi_split_read_limit =
spider_param_semi_split_read_limit(thd, share->semi_split_read_limit);
+#ifdef SPIDER_HAS_EXPLAIN_QUERY
}
+#endif
result_list->first_read =
spider_param_first_read(thd, share->first_read);
result_list->second_read =
@@ -7846,6 +7852,11 @@ longlong spider_split_read_param(
result_list->semi_split_read_base = 0;
result_list->set_split_read = TRUE;
}
+ DBUG_PRINT("info",("spider result_list->semi_split_read=%f", result_list->semi_split_read));
+ DBUG_PRINT("info",("spider select_lex->explicit_limit=%d", select_lex ? select_lex->explicit_limit : 0));
+ DBUG_PRINT("info",("spider OPTION_FOUND_ROWS=%s", select_lex && (select_lex->options & OPTION_FOUND_ROWS) ? "TRUE" : "FALSE"));
+ DBUG_PRINT("info",("spider select_lex->group_list.elements=%u", select_lex ? select_lex->group_list.elements : 0));
+ DBUG_PRINT("info",("spider select_lex->with_sum_func=%s", select_lex && select_lex->with_sum_func ? "TRUE" : "FALSE"));
if (
result_list->semi_split_read > 0 &&
select_lex && select_lex->explicit_limit &&
@@ -7932,12 +7943,18 @@ bool spider_check_direct_order_limit(
longlong select_limit;
longlong offset_limit;
DBUG_ENTER("spider_check_direct_order_limit");
+ if (spider_check_index_merge(spider->get_top_table(),
+ spider_get_select_lex(spider)))
+ {
+ DBUG_PRINT("info",("spider set use_index_merge"));
+ spider->use_index_merge = TRUE;
+ }
DBUG_PRINT("info",("spider SQLCOM_HA_READ=%s",
(spider->sql_command == SQLCOM_HA_READ) ? "TRUE" : "FALSE"));
DBUG_PRINT("info",("spider sql_kinds with SPIDER_SQL_KIND_HANDLER=%s",
(spider->sql_kinds & SPIDER_SQL_KIND_HANDLER) ? "TRUE" : "FALSE"));
- DBUG_PRINT("info",("spider has_clone_for_merge=%s",
- spider->has_clone_for_merge ? "TRUE" : "FALSE"));
+ DBUG_PRINT("info",("spider use_index_merge=%s",
+ spider->use_index_merge ? "TRUE" : "FALSE"));
DBUG_PRINT("info",("spider is_clone=%s",
spider->is_clone ? "TRUE" : "FALSE"));
#ifdef HA_CAN_BULK_ACCESS
@@ -7946,7 +7963,7 @@ bool spider_check_direct_order_limit(
#endif
if (
spider->sql_command != SQLCOM_HA_READ &&
- !spider->has_clone_for_merge &&
+ !spider->use_index_merge &&
#ifdef HA_CAN_BULK_ACCESS
(!spider->is_clone || spider->is_bulk_access_clone)
#else
@@ -7958,10 +7975,10 @@ bool spider_check_direct_order_limit(
DBUG_PRINT("info",("spider select_lex=%p", select_lex));
#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100000
DBUG_PRINT("info",("spider leaf_tables.elements=%u",
- select_lex->leaf_tables.elements));
+ select_lex ? select_lex->leaf_tables.elements : 0));
#endif
- if (select_lex->options & SELECT_DISTINCT)
+ if (select_lex && (select_lex->options & SELECT_DISTINCT))
{
DBUG_PRINT("info",("spider with distinct"));
spider->result_list.direct_distinct = TRUE;
@@ -7972,6 +7989,9 @@ bool spider_check_direct_order_limit(
DBUG_PRINT("info",("spider select_limit=%lld", select_limit));
DBUG_PRINT("info",("spider offset_limit=%lld", offset_limit));
if (
+#ifdef SPIDER_NEED_CHECK_CONDITION_AT_CHECKING_DIRECT_ORDER_LIMIT
+ !spider->condition ||
+#endif
!select_lex ||
#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100000
select_lex->leaf_tables.elements != 1 ||
@@ -8038,19 +8058,19 @@ bool spider_check_direct_order_limit(
DBUG_PRINT("info",("spider first_check=%s",
first_check ? "TRUE" : "FALSE"));
DBUG_PRINT("info",("spider (select_lex->options & OPTION_FOUND_ROWS)=%s",
- (select_lex->options & OPTION_FOUND_ROWS) ? "TRUE" : "FALSE"));
+ select_lex && (select_lex->options & OPTION_FOUND_ROWS) ? "TRUE" : "FALSE"));
#ifdef HANDLER_HAS_DIRECT_AGGREGATE
DBUG_PRINT("info",("spider direct_aggregate=%s",
spider->result_list.direct_aggregate ? "TRUE" : "FALSE"));
#endif
DBUG_PRINT("info",("spider select_lex->group_list.elements=%u",
- select_lex->group_list.elements));
+ select_lex ? select_lex->group_list.elements : 0));
DBUG_PRINT("info",("spider select_lex->with_sum_func=%s",
- select_lex->with_sum_func ? "TRUE" : "FALSE"));
+ select_lex && select_lex->with_sum_func ? "TRUE" : "FALSE"));
DBUG_PRINT("info",("spider select_lex->having=%s",
- select_lex->having ? "TRUE" : "FALSE"));
+ select_lex && select_lex->having ? "TRUE" : "FALSE"));
DBUG_PRINT("info",("spider select_lex->order_list.elements=%u",
- select_lex->order_list.elements));
+ select_lex ? select_lex->order_list.elements : 0));
if (
!first_check ||
!select_lex->explicit_limit ||
@@ -8092,6 +8112,63 @@ bool spider_check_direct_order_limit(
DBUG_RETURN(FALSE);
}
+bool spider_check_index_merge(
+ TABLE *table,
+ st_select_lex *select_lex
+) {
+ uint roop_count;
+ JOIN *join;
+ DBUG_ENTER("spider_check_index_merge");
+ if (!select_lex)
+ {
+ DBUG_PRINT("info",("spider select_lex is null"));
+ DBUG_RETURN(FALSE);
+ }
+ join = select_lex->join;
+ if (!join)
+ {
+ DBUG_PRINT("info",("spider join is null"));
+ DBUG_RETURN(FALSE);
+ }
+ for (roop_count = 0; roop_count < spider_join_table_count(join); ++roop_count)
+ {
+ JOIN_TAB *join_tab = &join->join_tab[roop_count];
+ if (join_tab && join_tab->table == table)
+ {
+ DBUG_PRINT("info",("spider join_tab->type=%u", join_tab->type));
+ if (
+#ifdef SPIDER_HAS_JT_HASH_INDEX_MERGE
+ join_tab->type == JT_HASH_INDEX_MERGE ||
+#endif
+ join_tab->type == JT_INDEX_MERGE
+ ) {
+ DBUG_RETURN(TRUE);
+ }
+/*
+ DBUG_PRINT("info",("spider join_tab->quick->get_type()=%u",
+ join_tab->quick ? join_tab->quick->get_type() : 0));
+ if (
+ join_tab->quick &&
+ join_tab->quick->get_type() == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE
+ ) {
+ DBUG_RETURN(TRUE);
+ }
+*/
+ DBUG_PRINT("info",("spider join_tab->select->quick->get_type()=%u",
+ join_tab->select && join_tab->select->quick ? join_tab->select->quick->get_type() : 0));
+ if (
+ join_tab->select &&
+ join_tab->select->quick &&
+ join_tab->select->quick->get_type() == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE
+ ) {
+ DBUG_RETURN(TRUE);
+ }
+ break;
+ }
+ }
+ DBUG_RETURN(FALSE);
+}
+
int spider_compare_for_sort(
SPIDER_SORT *a,
SPIDER_SORT *b
diff --git a/storage/spider/spd_table.h b/storage/spider/spd_table.h
index 858421444b1..e9d1d5c61c2 100644
--- a/storage/spider/spd_table.h
+++ b/storage/spider/spd_table.h
@@ -414,6 +414,11 @@ bool spider_check_direct_order_limit(
ha_spider *spider
);
+bool spider_check_index_merge(
+ TABLE *table,
+ st_select_lex *select_lex
+);
+
int spider_compare_for_sort(
SPIDER_SORT *a,
SPIDER_SORT *b
diff --git a/storage/spider/spd_trx.cc b/storage/spider/spd_trx.cc
index dd0cc1d3101..a66fa5a7f5d 100644
--- a/storage/spider/spd_trx.cc
+++ b/storage/spider/spd_trx.cc
@@ -14,7 +14,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define MYSQL_SERVER 1
-#include <my_global.h>
#include "mysql_version.h"
#if MYSQL_VERSION_ID < 50500
#include "mysql_priv.h"
diff --git a/storage/tokudb/CMakeLists.txt b/storage/tokudb/CMakeLists.txt
index 24d4ffc12de..efb5d7e7da3 100644
--- a/storage/tokudb/CMakeLists.txt
+++ b/storage/tokudb/CMakeLists.txt
@@ -25,7 +25,7 @@ IF (HAVE_WVLA)
ENDIF()
############################################
-SET(TOKUDB_VERSION "tokudb-7.5.4")
+SET(TOKUDB_VERSION "tokudb-7.5.5")
SET(TOKUDB_DEB_FILES "usr/lib/mysql/plugin/ha_tokudb.so\netc/mysql/conf.d/tokudb.cnf\nusr/bin/tokuftdump\nusr/share/doc/mariadb-server-10.1/README-TOKUDB\nusr/share/doc/mariadb-server-10.1/README.md" PARENT_SCOPE)
SET(USE_BDB OFF CACHE BOOL "")
MARK_AS_ADVANCED(BUILDNAME)
diff --git a/storage/tokudb/doc2/sysbench.update.ma10.tokudb754.loglog.png b/storage/tokudb/doc2/sysbench.update.ma10.tokudb754.loglog.png
index 99b15ff642f..7b2c1c5c66d 100644
--- a/storage/tokudb/doc2/sysbench.update.ma10.tokudb754.loglog.png
+++ b/storage/tokudb/doc2/sysbench.update.ma10.tokudb754.loglog.png
Binary files differ
diff --git a/storage/tokudb/doc2/sysbench.update.ma10.tokudb754.png b/storage/tokudb/doc2/sysbench.update.ma10.tokudb754.png
index 7297013b51f..d46c053c0af 100644
--- a/storage/tokudb/doc2/sysbench.update.ma10.tokudb754.png
+++ b/storage/tokudb/doc2/sysbench.update.ma10.tokudb754.png
Binary files differ
diff --git a/storage/tokudb/ha_tokudb.cc b/storage/tokudb/ha_tokudb.cc
index 532ce7004e7..c875af1488b 100644
--- a/storage/tokudb/ha_tokudb.cc
+++ b/storage/tokudb/ha_tokudb.cc
@@ -172,6 +172,31 @@ static inline uint32_t get_len_of_offsets(KEY_AND_COL_INFO* kc_info, TABLE_SHARE
}
+static int get_thread_query_string(my_thread_id id, String &qs) {
+ mysql_mutex_lock(&LOCK_thread_count);
+ I_List_iterator<THD> it(threads);
+ THD* tmp;
+ while ((tmp= it++))
+ {
+ /* ID */
+ if (tmp->thread_id == id)
+ {
+ /* Lock THD mutex that protects its data when looking at it. */
+ mysql_mutex_lock(&tmp->LOCK_thd_data);
+
+ /* INFO */
+ if (tmp->query())
+ {
+ qs = String(tmp->query(), tmp->query_length(), system_charset_info);
+ }
+ mysql_mutex_unlock(&tmp->LOCK_thd_data);
+ break;
+ }
+ }
+ mysql_mutex_unlock(&LOCK_thread_count);
+ return 0;
+}
+
static int allocate_key_and_col_info ( TABLE_SHARE* table_share, KEY_AND_COL_INFO* kc_info) {
int error;
//
@@ -3557,8 +3582,12 @@ static void maybe_do_unique_checks_delay(THD *thd) {
}
}
+static bool need_read_only(THD *thd) {
+ return opt_readonly || !THDVAR(thd, rpl_check_readonly);
+}
+
static bool do_unique_checks(THD *thd, bool do_rpl_event) {
- if (do_rpl_event && thd->slave_thread && opt_readonly && !THDVAR(thd, rpl_unique_checks))
+ if (do_rpl_event && thd->slave_thread && need_read_only(thd) && !THDVAR(thd, rpl_unique_checks))
return false;
else
return !thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS);
@@ -5375,9 +5404,12 @@ int ha_tokudb::get_next(uchar* buf, int direction, DBT* key_to_compare, bool do_
}
if (!error) {
- tokudb_trx_data* trx = (tokudb_trx_data *) thd_get_ha_data(ha_thd(), tokudb_hton);
+ THD *thd = ha_thd();
+ tokudb_trx_data* trx = (tokudb_trx_data *) thd_get_ha_data(thd, tokudb_hton);
trx->stmt_progress.queried++;
- track_progress(ha_thd());
+ track_progress(thd);
+ if (thd_killed(thd))
+ error = ER_ABORTING_CONNECTION;
}
cleanup:
return error;
@@ -7257,7 +7289,7 @@ double ha_tokudb::index_only_read_time(uint keynr, double records) {
// HA_POS_ERROR - Something is wrong with the index tree
//
ha_rows ha_tokudb::records_in_range(uint keynr, key_range* start_key, key_range* end_key) {
- TOKUDB_HANDLER_DBUG_ENTER("");
+ TOKUDB_HANDLER_DBUG_ENTER("%d %p %p", keynr, start_key, end_key);
DBT *pleft_key, *pright_key;
DBT left_key, right_key;
ha_rows ret_val = HA_TOKUDB_RANGE_COUNT;
@@ -7313,6 +7345,9 @@ ha_rows ha_tokudb::records_in_range(uint keynr, key_range* start_key, key_range*
ret_val = (ha_rows) (rows <= 1 ? 1 : rows);
cleanup:
+ if (tokudb_debug & TOKUDB_DEBUG_RETURN) {
+ TOKUDB_HANDLER_TRACE("%" PRIu64 " %" PRIu64, (uint64_t) ret_val, rows);
+ }
DBUG_RETURN(ret_val);
}
diff --git a/storage/tokudb/ha_tokudb_admin.cc b/storage/tokudb/ha_tokudb_admin.cc
index c3b895bf4f4..d6da45733a5 100644
--- a/storage/tokudb/ha_tokudb_admin.cc
+++ b/storage/tokudb/ha_tokudb_admin.cc
@@ -89,6 +89,8 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+#include "toku_time.h"
+
struct analyze_progress_extra {
THD *thd;
TOKUDB_SHARE *share;
@@ -186,9 +188,12 @@ typedef struct hot_optimize_context {
uint progress_stage;
uint current_table;
uint num_tables;
+ float progress_limit;
+ uint64_t progress_last_time;
+ uint64_t throttle;
} *HOT_OPTIMIZE_CONTEXT;
-static int hot_poll_fun(void *extra, float progress) {
+static int hot_optimize_progress_fun(void *extra, float progress) {
HOT_OPTIMIZE_CONTEXT context = (HOT_OPTIMIZE_CONTEXT)extra;
if (thd_killed(context->thd)) {
sprintf(context->write_status_msg, "The process has been killed, aborting hot optimize.");
@@ -207,14 +212,27 @@ static int hot_poll_fun(void *extra, float progress) {
// the percentage we report here is for the current stage/db
thd_progress_report(context->thd, (unsigned long long) percentage, 100);
#endif
- return 0;
+
+ // throttle the optimize table
+ if (context->throttle) {
+ uint64_t time_now = toku_current_time_microsec();
+ uint64_t dt = time_now - context->progress_last_time;
+ uint64_t throttle_time = 1000000ULL / context->throttle;
+ if (throttle_time > dt) {
+ usleep(throttle_time - dt);
+ }
+ context->progress_last_time = toku_current_time_microsec();
+ }
+
+ // return 1 if progress has reach the progress limit
+ return progress >= context->progress_limit;
}
// flatten all DB's in this table, to do so, peform hot optimize on each db
int ha_tokudb::do_optimize(THD *thd) {
TOKUDB_HANDLER_DBUG_ENTER("%s", share->table_name);
+ int error = 0;
const char *orig_proc_info = tokudb_thd_get_proc_info(thd);
- int error;
uint curr_num_DBs = table->s->keys + tokudb_test(hidden_primary_key);
#ifdef HA_TOKUDB_HAS_THD_PROGRESS
@@ -225,11 +243,21 @@ int ha_tokudb::do_optimize(THD *thd) {
// for each DB, run optimize and hot_optimize
for (uint i = 0; i < curr_num_DBs; i++) {
+ // only optimize the index if it matches the optimize_index_name session variable
+ const char *optimize_index_name = THDVAR(thd, optimize_index_name);
+ if (optimize_index_name) {
+ const char *this_index_name = i >= table_share->keys ? "primary" : table_share->key_info[i].name;
+ if (strcasecmp(optimize_index_name, this_index_name) != 0) {
+ continue;
+ }
+ }
+
DB* db = share->key_file[i];
error = db->optimize(db);
if (error) {
goto cleanup;
}
+
struct hot_optimize_context hc;
memset(&hc, 0, sizeof hc);
hc.thd = thd;
@@ -237,8 +265,11 @@ int ha_tokudb::do_optimize(THD *thd) {
hc.ha = this;
hc.current_table = i;
hc.num_tables = curr_num_DBs;
+ hc.progress_limit = THDVAR(thd, optimize_index_fraction);
+ hc.progress_last_time = toku_current_time_microsec();
+ hc.throttle = THDVAR(thd, optimize_throttle);
uint64_t loops_run;
- error = db->hot_optimize(db, NULL, NULL, hot_poll_fun, &hc, &loops_run);
+ error = db->hot_optimize(db, NULL, NULL, hot_optimize_progress_fun, &hc, &loops_run);
if (error) {
goto cleanup;
}
diff --git a/storage/tokudb/hatoku_defines.h b/storage/tokudb/hatoku_defines.h
index 4ad177be9aa..69dbd6b7e5c 100644
--- a/storage/tokudb/hatoku_defines.h
+++ b/storage/tokudb/hatoku_defines.h
@@ -163,6 +163,9 @@ PATENT RIGHTS GRANT:
#define TOKU_INCLUDE_EXTENDED_KEYS 1
#define TOKU_INCLUDE_OPTION_STRUCTS 1
#define TOKU_CLUSTERING_IS_COVERING 1
+#define TOKU_INCLUDE_LOCK_TIMEOUT_QUERY_STRING 1
+#else
+#define TOKU_INCLUDE_LOCK_TIMEOUT_QUERY_STRING 1
#endif
#define TOKU_INCLUDE_HANDLERTON_HANDLE_FATAL_SIGNAL 0 /* MariaDB 5.5 */
diff --git a/storage/tokudb/hatoku_hton.cc b/storage/tokudb/hatoku_hton.cc
index 9c2e461c338..e17f94c2831 100644
--- a/storage/tokudb/hatoku_hton.cc
+++ b/storage/tokudb/hatoku_hton.cc
@@ -1393,8 +1393,6 @@ static MYSQL_SYSVAR_STR(data_dir, tokudb_data_dir, PLUGIN_VAR_READONLY, "TokuDB
static MYSQL_SYSVAR_STR(version, tokudb_version, PLUGIN_VAR_READONLY, "TokuDB Version", NULL, NULL, NULL);
-static MYSQL_SYSVAR_UINT(init_flags, tokudb_init_flags, PLUGIN_VAR_READONLY, "Sets TokuDB DB_ENV->open flags", NULL, NULL, tokudb_init_flags, 0, ~0U, 0);
-
static MYSQL_SYSVAR_UINT(write_status_frequency, tokudb_write_status_frequency, 0, "TokuDB frequency that show processlist updates status of writes", NULL, NULL, 1000, 0, ~0U, 0);
static MYSQL_SYSVAR_UINT(read_status_frequency, tokudb_read_status_frequency, 0, "TokuDB frequency that show processlist updates status of reads", NULL, NULL, 10000, 0, ~0U, 0);
static MYSQL_SYSVAR_INT(fs_reserve_percent, tokudb_fs_reserve_percent, PLUGIN_VAR_READONLY, "TokuDB file system space reserve (percent free required)", NULL, NULL, 5, 0, 100, 0);
@@ -1431,7 +1429,6 @@ static struct st_mysql_sys_var *tokudb_system_variables[] = {
MYSQL_SYSVAR(create_index_online),
MYSQL_SYSVAR(disable_prefetching),
MYSQL_SYSVAR(version),
- MYSQL_SYSVAR(init_flags),
MYSQL_SYSVAR(checkpointing_period),
MYSQL_SYSVAR(prelock_empty),
MYSQL_SYSVAR(checkpoint_lock),
@@ -1472,6 +1469,10 @@ static struct st_mysql_sys_var *tokudb_system_variables[] = {
MYSQL_SYSVAR(rpl_unique_checks_delay),
MYSQL_SYSVAR(rpl_lookup_rows),
MYSQL_SYSVAR(rpl_lookup_rows_delay),
+ MYSQL_SYSVAR(rpl_check_readonly),
+ MYSQL_SYSVAR(optimize_index_name),
+ MYSQL_SYSVAR(optimize_index_fraction),
+ MYSQL_SYSVAR(optimize_throttle),
NULL
};
@@ -1964,6 +1965,33 @@ static int tokudb_fractal_tree_block_map_done(void *p) {
return 0;
}
+#if TOKU_INCLUDE_LOCK_TIMEOUT_QUERY_STRING
+struct tokudb_search_txn_extra {
+ bool match_found;
+ uint64_t match_txn_id;
+ uint64_t match_client_id;
+};
+
+static int tokudb_search_txn_callback(uint64_t txn_id, uint64_t client_id, iterate_row_locks_callback iterate_locks, void *locks_extra, void *extra) {
+ struct tokudb_search_txn_extra *e = reinterpret_cast<struct tokudb_search_txn_extra *>(extra);
+ if (e->match_txn_id == txn_id) {
+ e->match_found = true;
+ e->match_client_id = client_id;
+ return 1;
+ }
+ return 0;
+}
+
+static bool tokudb_txn_id_to_client_id(THD *thd, uint64_t blocking_txnid, uint64_t *blocking_client_id) {
+ struct tokudb_search_txn_extra e = { false, blocking_txnid, 0};
+ (void) db_env->iterate_live_transactions(db_env, tokudb_search_txn_callback, &e);
+ if (e.match_found) {
+ *blocking_client_id = e.match_client_id;
+ }
+ return e.match_found;
+}
+#endif
+
static void tokudb_pretty_key(const DB *db, const DBT *key, const char *default_key, String *out) {
if (key->data == NULL) {
out->append(default_key);
@@ -2013,8 +2041,9 @@ static void tokudb_lock_timeout_callback(DB *db, uint64_t requesting_txnid, cons
// generate a JSON document with the lock timeout info
String log_str;
log_str.append("{");
+ uint64_t mysql_thread_id = thd->thread_id;
log_str.append("\"mysql_thread_id\":");
- log_str.append_ulonglong(thd->thread_id);
+ log_str.append_ulonglong(mysql_thread_id);
log_str.append(", \"dbname\":");
log_str.append("\""); log_str.append(tokudb_get_index_name(db)); log_str.append("\"");
log_str.append(", \"requesting_txnid\":");
@@ -2054,7 +2083,18 @@ static void tokudb_lock_timeout_callback(DB *db, uint64_t requesting_txnid, cons
}
// dump to stderr
if (lock_timeout_debug & 2) {
- sql_print_error("%s: %s", tokudb_hton_name, log_str.c_ptr());
+ sql_print_error("%s: lock timeout %s", tokudb_hton_name, log_str.c_ptr());
+ LEX_STRING *qs = thd_query_string(thd);
+ sql_print_error("%s: requesting_thread_id:%" PRIu64 " q:%.*s", tokudb_hton_name, mysql_thread_id, (int) qs->length, qs->str);
+#if TOKU_INCLUDE_LOCK_TIMEOUT_QUERY_STRING
+ uint64_t blocking_thread_id = 0;
+ if (tokudb_txn_id_to_client_id(thd, blocking_txnid, &blocking_thread_id)) {
+ String blocking_qs;
+ if (get_thread_query_string(blocking_thread_id, blocking_qs) == 0) {
+ sql_print_error("%s: blocking_thread_id:%" PRIu64 " q:%.*s", tokudb_hton_name, blocking_thread_id, blocking_qs.length(), blocking_qs.c_ptr());
+ }
+ }
+#endif
}
}
}
diff --git a/storage/tokudb/hatoku_hton.h b/storage/tokudb/hatoku_hton.h
index 797e8ff48bc..ff17ecc276d 100644
--- a/storage/tokudb/hatoku_hton.h
+++ b/storage/tokudb/hatoku_hton.h
@@ -491,6 +491,15 @@ static MYSQL_THDVAR_BOOL(rpl_lookup_rows, PLUGIN_VAR_THDLOCAL, "lookup a row on
static MYSQL_THDVAR_ULONGLONG(rpl_lookup_rows_delay, PLUGIN_VAR_THDLOCAL, "time in milliseconds to add to lookups on replication slave",
NULL, NULL, 0 /*default*/, 0 /*min*/, ~0ULL /*max*/, 1 /*blocksize*/);
+static MYSQL_THDVAR_BOOL(rpl_check_readonly, PLUGIN_VAR_THDLOCAL, "check if the slave is read only",
+ NULL /*check*/, NULL /*update*/, true /*default*/);
+
+static MYSQL_THDVAR_STR(optimize_index_name, PLUGIN_VAR_THDLOCAL + PLUGIN_VAR_MEMALLOC, "optimize index name (default all indexes)", NULL /*check*/, NULL /*update*/, NULL /*default*/);
+
+static MYSQL_THDVAR_DOUBLE(optimize_index_fraction, 0, "optimize index fraction (default 1.0 all)", NULL /*check*/, NULL /*update*/, 1.0 /*def*/, 0 /*min*/, 1.0 /*max*/, 1);
+
+static MYSQL_THDVAR_ULONGLONG(optimize_throttle, 0, "optimize throttle (default no throttle)", NULL /*check*/, NULL /*update*/, 0 /*def*/, 0 /*min*/, ~0ULL /*max*/, 1);
+
extern HASH tokudb_open_tables;
extern pthread_mutex_t tokudb_mutex;
extern uint32_t tokudb_write_status_frequency;
diff --git a/storage/tokudb/mysql-test/rpl/disabled.def b/storage/tokudb/mysql-test/rpl/disabled.def
index efa4be9e16c..4c1a9a3e785 100644
--- a/storage/tokudb/mysql-test/rpl/disabled.def
+++ b/storage/tokudb/mysql-test/rpl/disabled.def
@@ -10,3 +10,6 @@ rpl_tokudb_write_pk: unreliable, uses timestamp differences
rpl_tokudb_write_pk_uc1: unreliable, uses timestamp differences
rpl_tokudb_write_unique: unreliable, uses timestamp differences
rpl_tokudb_write_unique_uc1: unreliable, uses timestamp differences
+rpl_tokudb_read_only_ff: unreliable, uses timestamp differences
+rpl_tokudb_read_only_tf: unreliable, uses timestamp differences
+rpl_tokudb_read_only_tt: unreliable, uses timestamp differences
diff --git a/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_ff.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_ff.result
new file mode 100644
index 00000000000..6db2036d933
--- /dev/null
+++ b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_ff.result
@@ -0,0 +1,14 @@
+include/master-slave.inc
+[connection master]
+drop table if exists t;
+create table t (a bigint not null, primary key(a)) engine=tokudb;
+select unix_timestamp() into @tstart;
+insert into t values (1);
+insert into t values (2),(3);
+insert into t values (4);
+select unix_timestamp()-@tstart <= 10;
+unix_timestamp()-@tstart <= 10
+1
+include/diff_tables.inc [master:test.t, slave:test.t]
+drop table if exists t;
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_ft.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_ft.result
new file mode 100644
index 00000000000..3bcd3e8ccdd
--- /dev/null
+++ b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_ft.result
@@ -0,0 +1,14 @@
+include/master-slave.inc
+[connection master]
+drop table if exists t;
+create table t (a bigint not null, primary key(a)) engine=tokudb;
+select unix_timestamp() into @tstart;
+insert into t values (1);
+insert into t values (2),(3);
+insert into t values (4);
+select unix_timestamp()-@tstart <= 10;
+unix_timestamp()-@tstart <= 10
+0
+include/diff_tables.inc [master:test.t, slave:test.t]
+drop table if exists t;
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_tf.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_tf.result
new file mode 100644
index 00000000000..6db2036d933
--- /dev/null
+++ b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_tf.result
@@ -0,0 +1,14 @@
+include/master-slave.inc
+[connection master]
+drop table if exists t;
+create table t (a bigint not null, primary key(a)) engine=tokudb;
+select unix_timestamp() into @tstart;
+insert into t values (1);
+insert into t values (2),(3);
+insert into t values (4);
+select unix_timestamp()-@tstart <= 10;
+unix_timestamp()-@tstart <= 10
+1
+include/diff_tables.inc [master:test.t, slave:test.t]
+drop table if exists t;
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_tt.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_tt.result
new file mode 100644
index 00000000000..6db2036d933
--- /dev/null
+++ b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_tt.result
@@ -0,0 +1,14 @@
+include/master-slave.inc
+[connection master]
+drop table if exists t;
+create table t (a bigint not null, primary key(a)) engine=tokudb;
+select unix_timestamp() into @tstart;
+insert into t values (1);
+insert into t values (2),(3);
+insert into t values (4);
+select unix_timestamp()-@tstart <= 10;
+unix_timestamp()-@tstart <= 10
+1
+include/diff_tables.inc [master:test.t, slave:test.t]
+drop table if exists t;
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_ff-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_ff-slave.opt
new file mode 100644
index 00000000000..b9eb687d8d5
--- /dev/null
+++ b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_ff-slave.opt
@@ -0,0 +1 @@
+--read-only=OFF --tokudb-rpl-check-readonly=OFF --tokudb-rpl-unique-checks-delay=5000 --tokudb-rpl-unique-checks=OFF
diff --git a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_ff.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_ff.test
new file mode 100644
index 00000000000..c77e4b49605
--- /dev/null
+++ b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_ff.test
@@ -0,0 +1,53 @@
+# test replicated write rows log events on a table with a primary key.
+# the slave is read only with tokudb unique checks disabled.
+
+source include/have_tokudb.inc;
+let $engine=tokudb;
+source include/have_binlog_format_row.inc;
+source include/master-slave.inc;
+
+# initialize
+connection master;
+disable_warnings;
+drop table if exists t;
+enable_warnings;
+
+connection slave;
+# show variables like 'read_only';
+# show variables like 'tokudb_rpl_unique_checks%';
+
+# insert some rows
+connection master;
+# select @@binlog_format;
+# select @@autocommit;
+eval create table t (a bigint not null, primary key(a)) engine=$engine;
+# show create table t;
+select unix_timestamp() into @tstart;
+insert into t values (1);
+insert into t values (2),(3);
+insert into t values (4);
+
+sync_slave_with_master;
+# source include/sync_slave_sql_with_master.inc;
+
+connection master;
+select unix_timestamp()-@tstart <= 10;
+
+connection slave;
+# insert into t values (5); # test read-only
+# show create table t;
+
+# diff tables
+connection master;
+--let $diff_tables= master:test.t, slave:test.t
+source include/diff_tables.inc;
+
+# cleanup
+connection master;
+drop table if exists t;
+
+sync_slave_with_master;
+# source include/sync_slave_sql_with_master.inc;
+
+source include/rpl_end.inc;
+
diff --git a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_ft-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_ft-slave.opt
new file mode 100644
index 00000000000..8283875e8a7
--- /dev/null
+++ b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_ft-slave.opt
@@ -0,0 +1 @@
+--read-only=OFF --tokudb-rpl-check-readonly=ON --tokudb-rpl-unique-checks-delay=5000 --tokudb-rpl-unique-checks=OFF
diff --git a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_ft.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_ft.test
new file mode 100644
index 00000000000..c77e4b49605
--- /dev/null
+++ b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_ft.test
@@ -0,0 +1,53 @@
+# test replicated write rows log events on a table with a primary key.
+# the slave is read only with tokudb unique checks disabled.
+
+source include/have_tokudb.inc;
+let $engine=tokudb;
+source include/have_binlog_format_row.inc;
+source include/master-slave.inc;
+
+# initialize
+connection master;
+disable_warnings;
+drop table if exists t;
+enable_warnings;
+
+connection slave;
+# show variables like 'read_only';
+# show variables like 'tokudb_rpl_unique_checks%';
+
+# insert some rows
+connection master;
+# select @@binlog_format;
+# select @@autocommit;
+eval create table t (a bigint not null, primary key(a)) engine=$engine;
+# show create table t;
+select unix_timestamp() into @tstart;
+insert into t values (1);
+insert into t values (2),(3);
+insert into t values (4);
+
+sync_slave_with_master;
+# source include/sync_slave_sql_with_master.inc;
+
+connection master;
+select unix_timestamp()-@tstart <= 10;
+
+connection slave;
+# insert into t values (5); # test read-only
+# show create table t;
+
+# diff tables
+connection master;
+--let $diff_tables= master:test.t, slave:test.t
+source include/diff_tables.inc;
+
+# cleanup
+connection master;
+drop table if exists t;
+
+sync_slave_with_master;
+# source include/sync_slave_sql_with_master.inc;
+
+source include/rpl_end.inc;
+
diff --git a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_tf-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_tf-slave.opt
new file mode 100644
index 00000000000..21e57d27c17
--- /dev/null
+++ b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_tf-slave.opt
@@ -0,0 +1 @@
+--read-only=ON --tokudb-rpl-check-readonly=OFF --tokudb-rpl-unique-checks-delay=5000 --tokudb-rpl-unique-checks=OFF
diff --git a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_tf.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_tf.test
new file mode 100644
index 00000000000..c77e4b49605
--- /dev/null
+++ b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_tf.test
@@ -0,0 +1,53 @@
+# test replicated write rows log events on a table with a primary key.
+# the slave is read only with tokudb unique checks disabled.
+
+source include/have_tokudb.inc;
+let $engine=tokudb;
+source include/have_binlog_format_row.inc;
+source include/master-slave.inc;
+
+# initialize
+connection master;
+disable_warnings;
+drop table if exists t;
+enable_warnings;
+
+connection slave;
+# show variables like 'read_only';
+# show variables like 'tokudb_rpl_unique_checks%';
+
+# insert some rows
+connection master;
+# select @@binlog_format;
+# select @@autocommit;
+eval create table t (a bigint not null, primary key(a)) engine=$engine;
+# show create table t;
+select unix_timestamp() into @tstart;
+insert into t values (1);
+insert into t values (2),(3);
+insert into t values (4);
+
+sync_slave_with_master;
+# source include/sync_slave_sql_with_master.inc;
+
+connection master;
+select unix_timestamp()-@tstart <= 10;
+
+connection slave;
+# insert into t values (5); # test read-only
+# show create table t;
+
+# diff tables
+connection master;
+--let $diff_tables= master:test.t, slave:test.t
+source include/diff_tables.inc;
+
+# cleanup
+connection master;
+drop table if exists t;
+
+sync_slave_with_master;
+# source include/sync_slave_sql_with_master.inc;
+
+source include/rpl_end.inc;
+
diff --git a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_tt-slave.opt b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_tt-slave.opt
new file mode 100644
index 00000000000..fd77ee0da9c
--- /dev/null
+++ b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_tt-slave.opt
@@ -0,0 +1 @@
+--read-only=ON --tokudb-rpl-check-readonly=ON --tokudb-rpl-unique-checks-delay=5000 --tokudb-rpl-unique-checks=OFF
diff --git a/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_tt.test b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_tt.test
new file mode 100644
index 00000000000..c77e4b49605
--- /dev/null
+++ b/storage/tokudb/mysql-test/rpl/t/rpl_tokudb_read_only_tt.test
@@ -0,0 +1,53 @@
+# test replicated write rows log events on a table with a primary key.
+# the slave is read only with tokudb unique checks disabled.
+
+source include/have_tokudb.inc;
+let $engine=tokudb;
+source include/have_binlog_format_row.inc;
+source include/master-slave.inc;
+
+# initialize
+connection master;
+disable_warnings;
+drop table if exists t;
+enable_warnings;
+
+connection slave;
+# show variables like 'read_only';
+# show variables like 'tokudb_rpl_unique_checks%';
+
+# insert some rows
+connection master;
+# select @@binlog_format;
+# select @@autocommit;
+eval create table t (a bigint not null, primary key(a)) engine=$engine;
+# show create table t;
+select unix_timestamp() into @tstart;
+insert into t values (1);
+insert into t values (2),(3);
+insert into t values (4);
+
+sync_slave_with_master;
+# source include/sync_slave_sql_with_master.inc;
+
+connection master;
+select unix_timestamp()-@tstart <= 10;
+
+connection slave;
+# insert into t values (5); # test read-only
+# show create table t;
+
+# diff tables
+connection master;
+--let $diff_tables= master:test.t, slave:test.t
+source include/diff_tables.inc;
+
+# cleanup
+connection master;
+drop table if exists t;
+
+sync_slave_with_master;
+# source include/sync_slave_sql_with_master.inc;
+
+source include/rpl_end.inc;
+
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/db788-optimize-index-name.result b/storage/tokudb/mysql-test/tokudb_bugs/r/db788-optimize-index-name.result
new file mode 100644
index 00000000000..019a8299f3c
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_bugs/r/db788-optimize-index-name.result
@@ -0,0 +1,19 @@
+set default_storage_engine='tokudb';
+drop table if exists t;
+create table t (a int, b int, c int, primary key(a), key(b), key(c));
+set tokudb_optimize_index_name='primary';
+optimize table t;
+Table Op Msg_type Msg_text
+test.t optimize note Table does not support optimize, doing recreate + analyze instead
+test.t optimize status OK
+set tokudb_optimize_index_name='b';
+optimize table t;
+Table Op Msg_type Msg_text
+test.t optimize note Table does not support optimize, doing recreate + analyze instead
+test.t optimize status OK
+set tokudb_optimize_index_name='c';
+optimize table t;
+Table Op Msg_type Msg_text
+test.t optimize note Table does not support optimize, doing recreate + analyze instead
+test.t optimize status OK
+drop table t;
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/db801.result b/storage/tokudb/mysql-test/tokudb_bugs/r/db801.result
new file mode 100644
index 00000000000..800db69ba39
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_bugs/r/db801.result
@@ -0,0 +1,18 @@
+set default_storage_engine=tokudb;
+drop table if exists t;
+create table t (id int not null primary key, c int not null) engine=tokudb;
+insert into t values (1,0);
+begin;
+update t set c=10 where id=1;
+update t set c=100;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+rollback;
+drop table t;
+create table t (id int not null primary key, c int not null) engine=tokudb partition by hash(id) partitions 1;
+insert into t values (1,0);
+begin;
+update t set c=10 where id=1;
+update t set c=100;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+rollback;
+drop table t;
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/memcache_dirty.result b/storage/tokudb/mysql-test/tokudb_bugs/r/memcache_dirty.result
deleted file mode 100644
index 2ca26cd5c56..00000000000
--- a/storage/tokudb/mysql-test/tokudb_bugs/r/memcache_dirty.result
+++ /dev/null
@@ -1,14 +0,0 @@
-SET DEFAULT_STORAGE_ENGINE = 'tokudb';
-DROP TABLE IF EXISTS t1;
-create table t1 (i int, j int, primary key (i))engine=TokuDB;
-insert into t1 values (0,0) MEMCACHE_DIRTY 'a';
-insert into t1 values (1,0) MEMCACHE_DIRTY 'b', 'c';
-update t1 set j=j+1 where i=0 MEMCACHE_DIRTY 'a';
-update t1 set j=j+1 where i=1 MEMCACHE_DIRTY 'b', 'c';
-insert into t1 values (0,0) on duplicate key update j=j+1 MEMCACHE_DIRTY 'a';
-insert into t1 values (2,0) on duplicate key update j=j+1 MEMCACHE_DIRTY 'a', 'b';
-replace into t1 values (0,3) MEMCACHE_DIRTY 'a';
-replace into t1 values (3,3) MEMCACHE_DIRTY 'a', 'b';
-delete from t1 where i=0 MEMCACHE_DIRTY 'a';
-delete from t1 where i=1 MEMCACHE_DIRTY 'b', 'c';
-DROP TABLE t1;
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/db788-optimize-index-name.test b/storage/tokudb/mysql-test/tokudb_bugs/t/db788-optimize-index-name.test
new file mode 100644
index 00000000000..644f00a5862
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/db788-optimize-index-name.test
@@ -0,0 +1,21 @@
+# test tokudb_optimize_index_name session variable
+set default_storage_engine='tokudb';
+source include/have_tokudb.inc;
+disable_warnings;
+drop table if exists t;
+enable_warnings;
+
+create table t (a int, b int, c int, primary key(a), key(b), key(c));
+# optimize primary key
+set tokudb_optimize_index_name='primary';
+optimize table t;
+
+# optimize key b
+set tokudb_optimize_index_name='b';
+optimize table t;
+
+# optimize key c
+set tokudb_optimize_index_name='c';
+optimize table t;
+
+drop table t;
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/db801.test b/storage/tokudb/mysql-test/tokudb_bugs/t/db801.test
new file mode 100644
index 00000000000..8a8fcea1496
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/db801.test
@@ -0,0 +1,50 @@
+# test for the DB-801 bug on mysql-5.5.41
+source include/have_tokudb.inc;
+source include/have_partition.inc;
+set default_storage_engine=tokudb;
+
+disable_warnings;
+drop table if exists t;
+enable_warnings;
+
+# run the test on a tokudb table
+create table t (id int not null primary key, c int not null) engine=tokudb;
+
+insert into t values (1,0);
+
+connect(conn1,localhost,root,,);
+connection default;
+begin;
+update t set c=10 where id=1;
+
+connection conn1;
+--error ER_LOCK_WAIT_TIMEOUT
+update t set c=100;
+
+connection default;
+rollback;
+disconnect conn1;
+
+drop table t;
+
+# run the test on a partitioned tokudb table
+create table t (id int not null primary key, c int not null) engine=tokudb partition by hash(id) partitions 1;
+
+insert into t values (1,0);
+
+connect(conn1,localhost,root,,);
+connection default;
+begin;
+update t set c=10 where id=1;
+
+connection conn1;
+--error ER_LOCK_WAIT_TIMEOUT
+update t set c=100;
+
+connection default;
+rollback;
+disconnect conn1;
+
+drop table t;
+
+
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/memcache_dirty.test b/storage/tokudb/mysql-test/tokudb_bugs/t/memcache_dirty.test
deleted file mode 100644
index e66c4cf0b6f..00000000000
--- a/storage/tokudb/mysql-test/tokudb_bugs/t/memcache_dirty.test
+++ /dev/null
@@ -1,25 +0,0 @@
---source include/have_tokudb.inc
-#
-# Record inconsistency.
-#
-#
-SET DEFAULT_STORAGE_ENGINE = 'tokudb';
-
---disable_warnings
-DROP TABLE IF EXISTS t1;
---enable_warnings
-create table t1 (i int, j int, primary key (i))engine=TokuDB;
-insert into t1 values (0,0) MEMCACHE_DIRTY 'a'; insert into t1 values (1,0) MEMCACHE_DIRTY 'b', 'c';
-
-update t1 set j=j+1 where i=0 MEMCACHE_DIRTY 'a'; update t1 set j=j+1 where i=1 MEMCACHE_DIRTY 'b', 'c';
-
-insert into t1 values (0,0) on duplicate key update j=j+1 MEMCACHE_DIRTY 'a'; insert into t1 values (2,0) on duplicate key update j=j+1 MEMCACHE_DIRTY 'a', 'b';
-
-replace into t1 values (0,3) MEMCACHE_DIRTY 'a'; replace into t1 values (3,3) MEMCACHE_DIRTY 'a', 'b';
-
-delete from t1 where i=0 MEMCACHE_DIRTY 'a'; delete from t1 where i=1 MEMCACHE_DIRTY 'b', 'c';
-
-
-# Final cleanup.
-DROP TABLE t1;
-
diff --git a/storage/tokudb/scripts/common.sh b/storage/tokudb/scripts/common.sh
index fc676ceeceb..fe39b9feca7 100644
--- a/storage/tokudb/scripts/common.sh
+++ b/storage/tokudb/scripts/common.sh
@@ -131,11 +131,20 @@ function parse_mysqlbuild() {
tokudb_version=${BASH_REMATCH[6]}
target_system=${BASH_REMATCH[7]}
target_arch=${BASH_REMATCH[8]}
+
# verify targets
if [ $target_system != $system ] ; then exitcode=1; fi
if [ $target_arch != $arch ] ; then exitcode=1; fi
+ # split the version string into major.minor.patch
+ if [[ $mysql_version =~ ^([0-9]+)\.([0-9]+)\.([0-9]+.*) ]] ; then
+ mysql_version_major=${BASH_REMATCH[1]}
+ mysql_version_minor=${BASH_REMATCH[2]}
+ mysql_version_patch=${BASH_REMATCH[3]}
+ fi
+
local temp_tokudb_version=$tokudb_version
+
# decode enterprise
if [[ $temp_tokudb_version =~ (.*)-e$ ]] ; then
build_type=enterprise
@@ -143,6 +152,7 @@ function parse_mysqlbuild() {
else
build_type=community
fi
+
# decode debug
if [[ $temp_tokudb_version =~ (.*)-debug$ ]] ; then
build_debug=1
@@ -151,8 +161,9 @@ function parse_mysqlbuild() {
else
build_debug=0
fi
+
# set tag or HEAD
- if [[ $temp_tokudb_version =~ ^([0-9]+)\\.([0-9]+)\\.([0-9]+) ]] ; then
+ if [[ $temp_tokudb_version =~ ^([0-9]+)\.([0-9]+)\.([0-9]+) ]] ; then
git_tag=tokudb-$temp_tokudb_version
else
git_tag=HEAD
@@ -160,6 +171,8 @@ function parse_mysqlbuild() {
if [ -z $mysql_tree ] ; then mysql_tree=$mysql_distro-$mysql_version; fi
if [ -z $jemalloc_tree ] ; then jemalloc_tree=$jemalloc_version; fi
fi
+
+ # set repository
mysql_repo=$mysql_distro
if [[ $mysql_version =~ ^([0-9]+\.[0-9]+) ]] ; then mysql_repo=$mysql_distro-${BASH_REMATCH[1]}; else exitcode=1; fi
else
@@ -174,6 +187,15 @@ function parse_mysql() {
if [[ $mysql =~ ^(mysql|mariadb)-(.*)$ ]] ; then
mysql_distro=${BASH_REMATCH[1]}
mysql_version=${BASH_REMATCH[2]}
+
+ # split the version string into major.minor.patch
+ if [[ $mysql_version =~ ^([0-9]+)\.([0-9]+)\.([0-9]+.*) ]] ; then
+ mysql_version_major=${BASH_REMATCH[1]}
+ mysql_version_minor=${BASH_REMATCH[2]}
+ mysql_version_patch=${BASH_REMATCH[3]}
+ fi
+
+ # set repository
mysql_repo=$mysql_distro
if [[ $mysql_version =~ ^([0-9]+\.[0-9]+) ]] ; then mysql_repo=$mysql_distro-${BASH_REMATCH[1]}; else exitcode=1; fi
exitcode=0
diff --git a/storage/tokudb/scripts/make.mysql.bash b/storage/tokudb/scripts/make.mysql.bash
index 5654c1c7926..a614424d9a0 100755
--- a/storage/tokudb/scripts/make.mysql.bash
+++ b/storage/tokudb/scripts/make.mysql.bash
@@ -103,10 +103,22 @@ fi
cd $mysql_distro-$mysql_version
if [ $? != 0 ] ; then exit 1; fi
+# extract mysql version patch number only
+if [[ $mysql_version_patch =~ ^([0-9]+) ]] ; then p=${BASH_REMATCH[1]}; else p=$mysql_version_patch; fi
+
# install the backup source
-if [ ! -d toku_backup ] ; then
+tokudb_backup=
+if [ $mysql_version_major -eq 5 -a $mysql_version_minor -eq 5 -a $p -le 40 ] ; then
+ tokudb_backup=patch
github_download Tokutek/backup-$build_type $(git_tree $git_tag $backup_tree) backup-$build_type
cp -r backup-$build_type/backup toku_backup
+elif [ $build_type = enterprise ] ; then
+ tokudb_backup=plugin
+ github_download Tokutek/tokudb-backup-plugin $(git_tree $git_tag $backup_tree) tokudb-backup-plugin
+ mv tokudb-backup-plugin plugin
+ github_download Tokutek/backup-enterprise $(git_tree $git_tag $backup_tree) backup-enterprise
+ mv backup-enterprise/backup plugin/tokudb-backup-plugin
+ rm -rf backup-enterprise
fi
if [ ! -d tokudb-engine ] ; then
@@ -153,6 +165,7 @@ function generate_cmake_cmd () {
echo -n CC=$cc CXX=$cxx cmake \
-D BUILD_CONFIG=mysql_release \
+ -D MYSQL_MAINTAINER_MODE=OFF \
-D CMAKE_BUILD_TYPE=$cmake_build_type \
-D CMAKE_TOKUDB_REVISION=$ft_revision \
-D TOKUDB_VERSION=tokudb-${tokudb_version} \
diff --git a/storage/tokudb/scripts/make.mysql.debug.env.bash b/storage/tokudb/scripts/make.mysql.debug.env.bash
index b7c270cfbd7..08ea19827bc 100755
--- a/storage/tokudb/scripts/make.mysql.debug.env.bash
+++ b/storage/tokudb/scripts/make.mysql.debug.env.bash
@@ -55,7 +55,7 @@ function github_clone() {
git_tag=
mysql=mysql-5.5
-mysql_tree=mysql-5.5.35
+mysql_tree=mysql-5.5.41
jemalloc=jemalloc
jemalloc_tree=3.6.0
tokudbengine=tokudb-engine
@@ -148,13 +148,15 @@ fi
pushd $build_dir
if [ $? != 0 ] ; then exit 1; fi
extra_cmake_options="-DCMAKE_LINK_DEPENDS_NO_SHARED=ON"
+extra_cmake_options+=" -DBUILD_TESTING=OFF"
+extra_cmake_options+=" -DMYSQL_MAINTAINER_MODE=OFF"
if (( $cmake_valgrind )) ; then
extra_cmake_options+=" -DUSE_VALGRIND=ON"
fi
if (( $cmake_debug_paranoid )) ; then
extra_cmake_options+=" -DTOKU_DEBUG_PARANOID=ON"
fi
-CC=$cc CXX=$cxx cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=$install_dir -DBUILD_TESTING=OFF $extra_cmake_options ../$mysql_tree
+CC=$cc CXX=$cxx cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=$install_dir $extra_cmake_options ../$mysql_tree
if [ $? != 0 ] ; then exit 1; fi
make -j4 install
if [ $? != 0 ] ; then exit 1; fi
diff --git a/storage/xtradb/CMakeLists.txt b/storage/xtradb/CMakeLists.txt
index da2f988e9b3..33815de5793 100644
--- a/storage/xtradb/CMakeLists.txt
+++ b/storage/xtradb/CMakeLists.txt
@@ -460,6 +460,14 @@ SET(INNOBASE_SOURCES
ut/ut0wqueue.cc
ut/ut0timer.cc)
+# These files have unused result errors, so we skip Werror
+CHECK_C_COMPILER_FLAG("-Werror" HAVE_WERROR)
+IF(HAVE_WERROR)
+ INCLUDE(${MYSQL_CMAKE_SCRIPT_DIR}/compile_flags.cmake)
+ ADD_COMPILE_FLAGS(page/page0zip.c COMPILE_FLAGS "-Wno-error")
+ ADD_COMPILE_FLAGS(ut/ut0ut.c COMPILE_FLAGS "-Wno-error")
+ENDIF()
+
IF(XTRADB_OK)
MYSQL_ADD_PLUGIN(xtradb ${INNOBASE_SOURCES} STORAGE_ENGINE
DEFAULT RECOMPILE_FOR_EMBEDDED
diff --git a/storage/xtradb/btr/btr0btr.cc b/storage/xtradb/btr/btr0btr.cc
index 2f248c98651..a52ca2ee242 100644
--- a/storage/xtradb/btr/btr0btr.cc
+++ b/storage/xtradb/btr/btr0btr.cc
@@ -3220,6 +3220,12 @@ func_start:
/* 2. Allocate a new page to the index */
new_block = btr_page_alloc(cursor->index, hint_page_no, direction,
btr_page_get_level(page, mtr), mtr, mtr);
+
+ /* Play safe, if new page is not allocated */
+ if (!new_block) {
+ return(rec);
+ }
+
new_page = buf_block_get_frame(new_block);
new_page_zip = buf_block_get_page_zip(new_block);
btr_page_create(new_block, new_page_zip, cursor->index,
diff --git a/storage/xtradb/buf/buf0buf.cc b/storage/xtradb/buf/buf0buf.cc
index 71008455f9b..0ef97fd3e21 100644
--- a/storage/xtradb/buf/buf0buf.cc
+++ b/storage/xtradb/buf/buf0buf.cc
@@ -300,7 +300,6 @@ UNIV_INTERN mysql_pfs_key_t buf_block_debug_latch_key;
#ifdef UNIV_PFS_MUTEX
UNIV_INTERN mysql_pfs_key_t buffer_block_mutex_key;
-UNIV_INTERN mysql_pfs_key_t buf_pool_mutex_key;
UNIV_INTERN mysql_pfs_key_t buf_pool_zip_mutex_key;
UNIV_INTERN mysql_pfs_key_t buf_pool_flush_state_mutex_key;
UNIV_INTERN mysql_pfs_key_t buf_pool_LRU_list_mutex_key;
@@ -1799,16 +1798,12 @@ page_found:
ut_ad(!bpage->in_page_hash);
ut_ad(bpage->buf_fix_count == 0);
- mutex_enter(&buf_pool->zip_mutex);
-
bpage->state = BUF_BLOCK_ZIP_PAGE;
bpage->space = static_cast<ib_uint32_t>(space);
bpage->offset = static_cast<ib_uint32_t>(offset);
bpage->buf_fix_count = 1;
bpage->buf_pool_index = buf_pool_index(buf_pool);
- mutex_exit(&buf_pool->zip_mutex);
-
ut_d(bpage->in_page_hash = TRUE);
HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
fold, bpage);
@@ -1860,7 +1855,6 @@ buf_pool_watch_remove(
#endif /* UNIV_SYNC_DEBUG */
ut_ad(buf_page_get_state(watch) == BUF_BLOCK_ZIP_PAGE);
- ut_ad(buf_own_zip_mutex_for_page(watch));
HASH_DELETE(buf_page_t, hash, buf_pool->page_hash, fold, watch);
ut_d(watch->in_page_hash = FALSE);
@@ -1903,9 +1897,7 @@ buf_pool_watch_unset(
#endif /* PAGE_ATOMIC_REF_COUNT */
if (bpage->buf_fix_count == 0) {
- mutex_enter(&buf_pool->zip_mutex);
buf_pool_watch_remove(buf_pool, fold, bpage);
- mutex_exit(&buf_pool->zip_mutex);
}
}
@@ -4518,7 +4510,7 @@ corrupt:
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
buf_page_get_flush_type(bpage) == BUF_FLUSH_LRU)) {
- have_LRU_mutex = TRUE; /* optimistic */
+ have_LRU_mutex = true; /* optimistic */
}
retry_mutex:
if (have_LRU_mutex) {
@@ -4538,6 +4530,7 @@ retry_mutex:
&& !have_LRU_mutex) {
mutex_exit(block_mutex);
+ have_LRU_mutex = true;
goto retry_mutex;
}
diff --git a/storage/xtradb/buf/buf0flu.cc b/storage/xtradb/buf/buf0flu.cc
index 3411dc27d2c..4331db08cf5 100644
--- a/storage/xtradb/buf/buf0flu.cc
+++ b/storage/xtradb/buf/buf0flu.cc
@@ -1123,8 +1123,8 @@ buf_flush_page(
# if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
/********************************************************************//**
Writes a flushable page asynchronously from the buffer pool to a file.
-NOTE: block->mutex must be held upon entering this function, and it will be
-released by this function after flushing. This is loosely based on
+NOTE: block and LRU list mutexes must be held upon entering this function, and
+they will be released by this function after flushing. This is loosely based on
buf_flush_batch() and buf_flush_page().
@return TRUE if the page was flushed and the mutexes released */
UNIV_INTERN
@@ -1675,6 +1675,8 @@ buf_do_LRU_batch(
flush_counters_t* n) /*!< out: flushed/evicted page
counts */
{
+ ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
+
if (buf_LRU_evict_from_unzip_LRU(buf_pool)) {
n->unzip_LRU_evicted
= buf_free_from_unzip_LRU_list_batch(buf_pool, max);
diff --git a/storage/xtradb/buf/buf0lru.cc b/storage/xtradb/buf/buf0lru.cc
index e9b6d8f3fb5..f2ce261c9df 100644
--- a/storage/xtradb/buf/buf0lru.cc
+++ b/storage/xtradb/buf/buf0lru.cc
@@ -526,7 +526,7 @@ buf_flush_or_remove_page(
mutex_exit(block_mutex);
- *must_restart = TRUE;
+ *must_restart = true;
processed = false;
} else if (!flush) {
diff --git a/storage/xtradb/buf/buf0rea.cc b/storage/xtradb/buf/buf0rea.cc
index afa14f0df04..88741f987ca 100644
--- a/storage/xtradb/buf/buf0rea.cc
+++ b/storage/xtradb/buf/buf0rea.cc
@@ -644,9 +644,9 @@ buf_read_ahead_linear(
fail_count = 0;
- for (i = low; i < high; i++) {
+ prio_rw_lock_t* hash_lock;
- prio_rw_lock_t* hash_lock;
+ for (i = low; i < high; i++) {
bpage = buf_page_hash_get_s_locked(buf_pool, space, i,
&hash_lock);
@@ -695,7 +695,7 @@ buf_read_ahead_linear(
/* If we got this far, we know that enough pages in the area have
been accessed in the right order: linear read-ahead can be sensible */
- bpage = buf_page_hash_get(buf_pool, space, offset);
+ bpage = buf_page_hash_get_s_locked(buf_pool, space, offset, &hash_lock);
if (bpage == NULL) {
@@ -723,6 +723,8 @@ buf_read_ahead_linear(
pred_offset = fil_page_get_prev(frame);
succ_offset = fil_page_get_next(frame);
+ rw_lock_s_unlock(hash_lock);
+
if ((offset == low) && (succ_offset == offset + 1)) {
/* This is ok, we can continue */
diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc
index 4a8586b97ee..d96095068f8 100644
--- a/storage/xtradb/fil/fil0fil.cc
+++ b/storage/xtradb/fil/fil0fil.cc
@@ -5214,6 +5214,9 @@ retry:
success = TRUE;
}
+ DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
+ success = FALSE; errno = 28;os_has_said_disk_full = TRUE;);
+
mutex_enter(&fil_system->mutex);
if (success) {
@@ -5256,6 +5259,10 @@ retry:
offset, page_size * n_pages,
node, NULL, space_id, NULL, 0, 0, 0, 0, 0, 0, false);
#endif /* UNIV_HOTBACKUP */
+
+ DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
+ success = FALSE; errno = 28; os_has_said_disk_full = TRUE;);
+
if (success) {
os_has_said_disk_full = FALSE;
} else {
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index e764d44c748..0ad6af8ae8d 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -405,7 +405,6 @@ static PSI_mutex_info all_innodb_mutexes[] = {
# ifndef PFS_SKIP_BUFFER_MUTEX_RWLOCK
{&buffer_block_mutex_key, "buffer_block_mutex", 0},
# endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */
- {&buf_pool_mutex_key, "buf_pool_mutex", 0},
{&buf_pool_zip_mutex_key, "buf_pool_zip_mutex", 0},
{&buf_pool_LRU_list_mutex_key, "buf_pool_LRU_list_mutex", 0},
{&buf_pool_free_list_mutex_key, "buf_pool_free_list_mutex", 0},
@@ -7994,12 +7993,15 @@ ha_innobase::innobase_lock_autoinc(void)
break;
case AUTOINC_NEW_STYLE_LOCKING:
- /* For simple (single/multi) row INSERTs, we fallback to the
- old style only if another transaction has already acquired
- the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT
- etc. type of statement. */
+ /* For simple (single/multi) row INSERTs/REPLACEs and RBR
+ events, we fallback to the old style only if another
+ transaction has already acquired the AUTOINC lock on
+ behalf of a LOAD FILE or INSERT ... SELECT etc. type of
+ statement. */
if (thd_sql_command(user_thd) == SQLCOM_INSERT
- || thd_sql_command(user_thd) == SQLCOM_REPLACE) {
+ || thd_sql_command(user_thd) == SQLCOM_REPLACE
+ || thd_sql_command(user_thd) == SQLCOM_END // RBR event
+ ) {
dict_table_t* ib_table = prebuilt->table;
/* Acquire the AUTOINC mutex. */
@@ -8008,9 +8010,11 @@ ha_innobase::innobase_lock_autoinc(void)
/* We need to check that another transaction isn't
already holding the AUTOINC lock on the table. */
if (ib_table->n_waiting_or_granted_auto_inc_locks) {
- /* Release the mutex to avoid deadlocks. */
+ /* Release the mutex to avoid deadlocks and
+ fall back to old style locking. */
dict_table_autoinc_unlock(ib_table);
} else {
+ /* Do not fall back to old style locking. */
break;
}
}
@@ -21168,6 +21172,7 @@ bool ha_innobase::is_thd_killed()
/**********************************************************************
Issue a warning that the row is too big. */
+UNIV_INTERN
void
ib_warn_row_too_big(const dict_table_t* table)
{
@@ -21181,6 +21186,10 @@ ib_warn_row_too_big(const dict_table_t* table)
THD* thd = current_thd;
+ if (thd == NULL) {
+ return;
+ }
+
push_warning_printf(
thd, Sql_condition::WARN_LEVEL_WARN, HA_ERR_TO_BIG_ROW,
"Row size too large (> %lu). Changing some columns to TEXT"
diff --git a/storage/xtradb/handler/i_s.cc b/storage/xtradb/handler/i_s.cc
index 79870c755f6..615715692f3 100644
--- a/storage/xtradb/handler/i_s.cc
+++ b/storage/xtradb/handler/i_s.cc
@@ -5169,11 +5169,6 @@ i_s_innodb_fill_buffer_pool(
info_buffer = (buf_page_info_t*) mem_heap_zalloc(
heap, mem_size);
- /* Obtain appropriate mutexes. Since this is diagnostic
- buffer pool info printout, we are not required to
- preserve the overall consistency, so we can
- release mutex periodically */
-
/* GO through each block in the chunk */
for (n_blocks = num_to_process; n_blocks--; block++) {
i_s_innodb_buffer_page_get_info(
diff --git a/storage/xtradb/ibuf/ibuf0ibuf.cc b/storage/xtradb/ibuf/ibuf0ibuf.cc
index ef6c9c74558..0794a44cfd0 100644
--- a/storage/xtradb/ibuf/ibuf0ibuf.cc
+++ b/storage/xtradb/ibuf/ibuf0ibuf.cc
@@ -2879,6 +2879,12 @@ ibuf_contract_in_background(
mutex_exit(&ibuf_mutex);
}
+#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
+ if (ibuf_debug) {
+ return(0);
+ }
+#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
+
while (sum_pages < n_pages) {
ulint n_bytes;
diff --git a/storage/xtradb/include/buf0flu.h b/storage/xtradb/include/buf0flu.h
index 3a83373dcae..c51010e33bc 100644
--- a/storage/xtradb/include/buf0flu.h
+++ b/storage/xtradb/include/buf0flu.h
@@ -86,8 +86,8 @@ buf_flush_init_for_writing(
# if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
/********************************************************************//**
Writes a flushable page asynchronously from the buffer pool to a file.
-NOTE: block->mutex must be held upon entering this function, and they will be
-released by this function after flushing. This is loosely based on
+NOTE: block and LRU list mutexes must be held upon entering this function, and
+they will be released by this function after flushing. This is loosely based on
buf_flush_batch() and buf_flush_page().
@return TRUE if the page was flushed and the mutexes released */
UNIV_INTERN
diff --git a/storage/xtradb/include/lock0priv.h b/storage/xtradb/include/lock0priv.h
index e564387ec53..90d5dc994a4 100644
--- a/storage/xtradb/include/lock0priv.h
+++ b/storage/xtradb/include/lock0priv.h
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2007, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2015, MariaDB Corporation
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -72,6 +73,12 @@ struct lock_t {
hash_node_t hash; /*!< hash chain node for a record
lock */
dict_index_t* index; /*!< index for a record lock */
+
+ /* Statistics for how long lock has been held and time
+ how long this lock had to be waited before it was granted */
+ time_t requested_time; /*!< Lock request time */
+ ulint wait_time; /*!< Time waited this lock or 0 */
+
union {
lock_table_t tab_lock;/*!< table lock */
lock_rec_t rec_lock;/*!< record lock */
diff --git a/storage/xtradb/include/sync0rw.ic b/storage/xtradb/include/sync0rw.ic
index 72bce228170..f66d435b8fc 100644
--- a/storage/xtradb/include/sync0rw.ic
+++ b/storage/xtradb/include/sync0rw.ic
@@ -517,6 +517,7 @@ rw_lock_x_lock_func_nowait(
ulint line) /*!< in: line where requested */
{
ibool success;
+ ibool local_recursive= lock->recursive;
#ifdef INNODB_RW_LOCKS_USE_ATOMICS
success = os_compare_and_swap_lint(&lock->lock_word, X_LOCK_DECR, 0);
@@ -531,10 +532,14 @@ rw_lock_x_lock_func_nowait(
mutex_exit(&(lock->mutex));
#endif
+ /* Note: recursive must be loaded before writer_thread see
+ comment for rw_lock_set_writer_id_and_recursion_flag().
+ To achieve this we load it before os_compare_and_swap_lint(),
+ which implies full memory barrier in current implementation. */
if (success) {
rw_lock_set_writer_id_and_recursion_flag(lock, TRUE);
- } else if (lock->recursive
+ } else if (local_recursive
&& os_thread_eq(lock->writer_thread,
os_thread_get_curr_id())) {
/* Relock: this lock_word modification is safe since no other
diff --git a/storage/xtradb/include/sync0sync.h b/storage/xtradb/include/sync0sync.h
index 8112fff8a30..0d36a8e7bd8 100644
--- a/storage/xtradb/include/sync0sync.h
+++ b/storage/xtradb/include/sync0sync.h
@@ -72,7 +72,6 @@ instrumentation due to their large number of instances. */
/* Key defines to register InnoDB mutexes with performance schema */
extern mysql_pfs_key_t autoinc_mutex_key;
extern mysql_pfs_key_t buffer_block_mutex_key;
-extern mysql_pfs_key_t buf_pool_mutex_key;
extern mysql_pfs_key_t buf_pool_zip_mutex_key;
extern mysql_pfs_key_t buf_pool_LRU_list_mutex_key;
extern mysql_pfs_key_t buf_pool_free_list_mutex_key;
diff --git a/storage/xtradb/include/trx0trx.h b/storage/xtradb/include/trx0trx.h
index 75325d73f4d..ad47eb0b0d2 100644
--- a/storage/xtradb/include/trx0trx.h
+++ b/storage/xtradb/include/trx0trx.h
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2015, MariaDB Corporation
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -1061,6 +1062,20 @@ struct trx_t{
#define DPAH_SIZE 8192
byte* distinct_page_access_hash;
ibool take_stats;
+
+ /* Lock wait statistics */
+ ulint n_rec_lock_waits;
+ /*!< Number of record lock waits,
+ might not be exactly correct. */
+ ulint n_table_lock_waits;
+ /*!< Number of table lock waits,
+ might not be exactly correct. */
+ ulint total_rec_lock_wait_time;
+ /*!< Total rec lock wait time up
+ to this moment. */
+ ulint total_table_lock_wait_time;
+ /*!< Total table lock wait time
+ up to this moment. */
};
/* Transaction isolation levels (trx->isolation_level) */
diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i
index 37d63489363..d938f27ed9b 100644
--- a/storage/xtradb/include/univ.i
+++ b/storage/xtradb/include/univ.i
@@ -48,7 +48,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_BUGFIX 22
#ifndef PERCONA_INNODB_VERSION
-#define PERCONA_INNODB_VERSION 71.0
+#define PERCONA_INNODB_VERSION 72.0
#endif
/* Enable UNIV_LOG_ARCHIVE in XtraDB */
diff --git a/storage/xtradb/lock/lock0lock.cc b/storage/xtradb/lock/lock0lock.cc
index f4db85691aa..878d7fa3ad7 100644
--- a/storage/xtradb/lock/lock0lock.cc
+++ b/storage/xtradb/lock/lock0lock.cc
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2014, 2015, MariaDB Corporation
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -2053,6 +2054,9 @@ lock_rec_create(
/* Set the bit corresponding to rec */
lock_rec_set_nth_bit(lock, heap_no);
+ lock->requested_time = ut_time();
+ lock->wait_time = 0;
+
index->table->n_rec_locks++;
ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted);
@@ -2295,6 +2299,8 @@ lock_rec_enqueue_waiting(
MONITOR_INC(MONITOR_LOCKREC_WAIT);
+ trx->n_rec_lock_waits++;
+
return(DB_LOCK_WAIT);
}
@@ -2770,6 +2776,17 @@ lock_grant(
}
}
+ /* Cumulate total lock wait time for statistics */
+ if (lock_get_type_low(lock) & LOCK_TABLE) {
+ lock->trx->total_table_lock_wait_time +=
+ (ulint)difftime(ut_time(), lock->trx->lock.wait_started);
+ } else {
+ lock->trx->total_rec_lock_wait_time +=
+ (ulint)difftime(ut_time(), lock->trx->lock.wait_started);
+ }
+
+ lock->wait_time = (ulint)difftime(ut_time(), lock->requested_time);
+
trx_mutex_exit(lock->trx);
}
@@ -4612,6 +4629,8 @@ lock_table_create(
lock->type_mode = type_mode | LOCK_TABLE;
lock->trx = trx;
+ lock->requested_time = ut_time();
+ lock->wait_time = 0;
lock->un_member.tab_lock.table = table;
@@ -4919,6 +4938,7 @@ lock_table_enqueue_waiting(
trx->lock.wait_started = ut_time();
trx->lock.was_chosen_as_deadlock_victim = FALSE;
+ trx->n_table_lock_waits++;
if (UNIV_UNLIKELY(trx->take_stats)) {
ut_usectime(&sec, &ms);
@@ -5638,6 +5658,10 @@ lock_table_print(
fputs(" waiting", file);
}
+ fprintf(file, " lock hold time %lu wait time before grant %lu ",
+ (ulint)difftime(ut_time(), lock->requested_time),
+ lock->wait_time);
+
putc('\n', file);
}
@@ -5669,7 +5693,14 @@ lock_rec_print(
fprintf(file, "RECORD LOCKS space id %lu page no %lu n bits %lu ",
(ulong) space, (ulong) page_no,
(ulong) lock_rec_get_n_bits(lock));
+
dict_index_name_print(file, lock->trx, lock->index);
+
+ /* Print number of table locks */
+ fprintf(file, " trx table locks %lu total table locks %lu ",
+ ib_vector_size(lock->trx->lock.table_locks),
+ UT_LIST_GET_LEN(lock->index->table->locks));
+
fprintf(file, " trx id " TRX_ID_FMT, lock->trx->id);
if (lock_get_mode(lock) == LOCK_S) {
@@ -5698,6 +5729,10 @@ lock_rec_print(
mtr_start(&mtr);
+ fprintf(file, " lock hold time %lu wait time before grant %lu ",
+ (ulint)difftime(ut_time(), lock->requested_time),
+ lock->wait_time);
+
putc('\n', file);
if ( srv_show_verbose_locks ) {
@@ -5958,6 +5993,14 @@ loop:
trx->read_view->up_limit_id);
}
+ /* Total trx lock waits and times */
+ fprintf(file, "Trx #rec lock waits %lu #table lock waits %lu\n",
+ trx->n_rec_lock_waits, trx->n_table_lock_waits);
+ fprintf(file, "Trx total rec lock wait time %lu SEC\n",
+ trx->total_rec_lock_wait_time);
+ fprintf(file, "Trx total table lock wait time %lu SEC\n",
+ trx->total_table_lock_wait_time);
+
if (trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
fprintf(file,
diff --git a/storage/xtradb/os/os0file.cc b/storage/xtradb/os/os0file.cc
index e419b6d3e5c..d7d224dc6dd 100644
--- a/storage/xtradb/os/os0file.cc
+++ b/storage/xtradb/os/os0file.cc
@@ -5170,7 +5170,7 @@ os_aio_func(
mode = mode & (~OS_AIO_SIMULATED_WAKE_LATER);
DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
- mode = OS_AIO_SYNC;);
+ mode = OS_AIO_SYNC; os_has_said_disk_full = TRUE;);
if (mode == OS_AIO_SYNC) {
ibool ret;
@@ -5185,13 +5185,9 @@ os_aio_func(
ut_a(type == OS_FILE_WRITE);
ret = os_file_write(name, file, buf, offset, n);
- }
- if (type == OS_FILE_WRITE) {
DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
- os_has_said_disk_full = FALSE;
- ret = 0;
- errno = 28;);
+ os_has_said_disk_full = TRUE; ret = 0; errno = 28;);
}
if (!ret) {
@@ -6138,6 +6134,9 @@ consecutive_loop:
ret = os_file_write(
aio_slot->name, aio_slot->file, combined_buf,
aio_slot->offset, total_len);
+
+ DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
+ os_has_said_disk_full = TRUE; ret = 0; errno = 28;);
} else {
ret = os_file_read(
aio_slot->file, combined_buf,
@@ -6145,11 +6144,6 @@ consecutive_loop:
aio_slot->page_compression);
}
- if (aio_slot->type == OS_FILE_WRITE) {
- DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28_2",
- os_has_said_disk_full = FALSE; ret = 0; errno = 28;);
- }
-
srv_set_io_thread_op_info(global_segment, "file i/o done");
if (aio_slot->type == OS_FILE_READ && n_consecutive > 1) {
diff --git a/storage/xtradb/rem/rem0rec.cc b/storage/xtradb/rem/rem0rec.cc
index ca9b0a6b841..b443e1c9dfe 100644
--- a/storage/xtradb/rem/rem0rec.cc
+++ b/storage/xtradb/rem/rem0rec.cc
@@ -845,7 +845,8 @@ rec_get_converted_size_comp_prefix_low(
}
ut_ad(len <= col->len || col->mtype == DATA_BLOB
- || (col->len == 0 && col->mtype == DATA_VARCHAR));
+ || col->mtype == DATA_VARMYSQL
+ || (col->len == 0 && col->mtype == DATA_VARCHAR));
fixed_len = field->fixed_len;
if (temp && fixed_len
@@ -1274,6 +1275,7 @@ rec_convert_dtuple_to_rec_comp(
} else {
ut_ad(len <= dtype_get_len(type)
|| dtype_get_mtype(type) == DATA_BLOB
+ || dtype_get_mtype(type) == DATA_VARMYSQL
|| !strcmp(index->name,
FTS_INDEX_TABLE_IND_NAME));
if (len < 128
diff --git a/storage/xtradb/row/row0mysql.cc b/storage/xtradb/row/row0mysql.cc
index cddc4a94aca..5b2b9ac1503 100644
--- a/storage/xtradb/row/row0mysql.cc
+++ b/storage/xtradb/row/row0mysql.cc
@@ -4428,6 +4428,7 @@ row_drop_table_for_mysql(
case DB_OUT_OF_FILE_SPACE:
err = DB_MUST_GET_MORE_FILE_SPACE;
+ trx->error_state = err;
row_mysql_handle_errors(&err, trx, NULL, NULL);
/* raise error */
diff --git a/storage/xtradb/srv/srv0start.cc b/storage/xtradb/srv/srv0start.cc
index 0bd1faf323e..ddf261cc236 100644
--- a/storage/xtradb/srv/srv0start.cc
+++ b/storage/xtradb/srv/srv0start.cc
@@ -136,23 +136,33 @@ UNIV_INTERN enum srv_shutdown_state srv_shutdown_state = SRV_SHUTDOWN_NONE;
static os_file_t files[1000];
/** io_handler_thread parameters for thread identification */
-static ulint n[SRV_MAX_N_IO_THREADS + 6];
-/** io_handler_thread identifiers, 32 is the maximum number of purge threads */
-/** 6 is the ? */
-#define START_OLD_THREAD_CNT (SRV_MAX_N_IO_THREADS + 6 + SRV_MAX_N_PURGE_THREADS)
-static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 6 + SRV_MAX_N_PURGE_THREADS + MTFLUSH_MAX_WORKER];
+static ulint n[SRV_MAX_N_IO_THREADS];
+/** io_handler_thread identifiers, 32 is the maximum number of purge threads.
+The extra elements at the end are allocated as follows:
+SRV_MAX_N_IO_THREADS + 1: srv_master_thread
+SRV_MAX_N_IO_THREADS + 2: lock_wait_timeout_thread
+SRV_MAX_N_IO_THREADS + 3: srv_error_monitor_thread
+SRV_MAX_N_IO_THREADS + 4: srv_monitor_thread
+SRV_MAX_N_IO_THREADS + 5: srv_redo_log_follow_thread
+SRV_MAX_N_IO_THREADS + 6: srv_purge_coordinator_thread
+SRV_MAX_N_IO_THREADS + 7: srv_worker_thread
+...
+SRV_MAX_N_IO_THREADS + 7 + srv_n_purge_threads - 1: srv_worker_thread */
+static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 7
+ + SRV_MAX_N_PURGE_THREADS
+ + MTFLUSH_MAX_WORKER];
/* Thread contex data for multi-threaded flush */
void *mtflush_ctx=NULL;
/** Thead handles */
-static os_thread_t thread_handles[SRV_MAX_N_IO_THREADS + 6 + SRV_MAX_N_PURGE_THREADS];
+static os_thread_t thread_handles[SRV_MAX_N_IO_THREADS + 7 + SRV_MAX_N_PURGE_THREADS];
static os_thread_t buf_flush_page_cleaner_thread_handle;
static os_thread_t buf_dump_thread_handle;
static os_thread_t dict_stats_thread_handle;
static os_thread_t buf_flush_lru_manager_thread_handle;
static os_thread_t srv_redo_log_follow_thread_handle;
/** Status variables, is thread started ?*/
-static bool thread_started[SRV_MAX_N_IO_THREADS + 6 + SRV_MAX_N_PURGE_THREADS] = {false};
+static bool thread_started[SRV_MAX_N_IO_THREADS + 7 + SRV_MAX_N_PURGE_THREADS] = {false};
static bool buf_flush_page_cleaner_thread_started = false;
static bool buf_dump_thread_started = false;
static bool dict_stats_thread_started = false;
@@ -1904,6 +1914,7 @@ innobase_start_or_create_for_mysql(void)
+ 1 /* srv_error_monitor_thread */
+ 1 /* srv_monitor_thread */
+ 1 /* srv_master_thread */
+ + 1 /* srv_redo_log_follow_thread */
+ 1 /* srv_purge_coordinator_thread */
+ 1 /* buf_dump_thread */
+ 1 /* dict_stats_thread */
@@ -2817,21 +2828,21 @@ files_checked:
if (!srv_read_only_mode
&& srv_force_recovery < SRV_FORCE_NO_BACKGROUND) {
- thread_handles[5 + SRV_MAX_N_IO_THREADS] = os_thread_create(
+ thread_handles[6 + SRV_MAX_N_IO_THREADS] = os_thread_create(
srv_purge_coordinator_thread,
- NULL, thread_ids + 5 + SRV_MAX_N_IO_THREADS);
+ NULL, thread_ids + 6 + SRV_MAX_N_IO_THREADS);
- thread_started[5 + SRV_MAX_N_IO_THREADS] = true;
+ thread_started[6 + SRV_MAX_N_IO_THREADS] = true;
ut_a(UT_ARR_SIZE(thread_ids)
- > 5 + srv_n_purge_threads + SRV_MAX_N_IO_THREADS);
+ > 6 + srv_n_purge_threads + SRV_MAX_N_IO_THREADS);
/* We've already created the purge coordinator thread above. */
for (i = 1; i < srv_n_purge_threads; ++i) {
- thread_handles[5 + i + SRV_MAX_N_IO_THREADS] = os_thread_create(
+ thread_handles[6 + i + SRV_MAX_N_IO_THREADS] = os_thread_create(
srv_worker_thread, NULL,
- thread_ids + 5 + i + SRV_MAX_N_IO_THREADS);
- thread_started[5 + i + SRV_MAX_N_IO_THREADS] = true;
+ thread_ids + 6 + i + SRV_MAX_N_IO_THREADS);
+ thread_started[6 + i + SRV_MAX_N_IO_THREADS] = true;
}
srv_start_wait_for_purge_to_start();
diff --git a/storage/xtradb/sync/sync0rw.cc b/storage/xtradb/sync/sync0rw.cc
index eac085513dc..00fb5e511a4 100644
--- a/storage/xtradb/sync/sync0rw.cc
+++ b/storage/xtradb/sync/sync0rw.cc
@@ -703,6 +703,8 @@ rw_lock_x_lock_low(
const char* file_name,/*!< in: file name where lock requested */
ulint line) /*!< in: line where requested */
{
+ ibool local_recursive= lock->recursive;
+
if (rw_lock_lock_word_decr(lock, X_LOCK_DECR)) {
/* lock->recursive also tells us if the writer_thread
@@ -724,12 +726,12 @@ rw_lock_x_lock_low(
} else {
os_thread_id_t thread_id = os_thread_get_curr_id();
- if (!pass) {
- os_rmb;
- }
-
- /* Decrement failed: relock or failed lock */
- if (!pass && lock->recursive
+ /* Decrement failed: relock or failed lock
+ Note: recursive must be loaded before writer_thread see
+ comment for rw_lock_set_writer_id_and_recursion_flag().
+ To achieve this we load it before rw_lock_lock_word_decr(),
+ which implies full memory barrier in current implementation. */
+ if (!pass && local_recursive
&& os_thread_eq(lock->writer_thread, thread_id)) {
/* Relock */
if (lock->lock_word == 0) {
diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh
index a171c43fe02..c6a1db11935 100644
--- a/support-files/mysql.server.sh
+++ b/support-files/mysql.server.sh
@@ -146,6 +146,9 @@ parse_server_arguments() {
--datadir=*) datadir=`echo "$arg" | sed -e 's/^[^=]*=//'`
datadir_set=1
;;
+ --log-basename=*|--hostname=*|--loose-log-basename=*)
+ mysqld_pid_file_path=`echo "$arg.pid" | sed -e 's/^[^=]*=//'`
+ ;;
--pid-file=*) mysqld_pid_file_path=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
--service-startup-timeout=*) service_startup_timeout=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
esac
diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c
index ee944c68f92..0f685593f18 100644
--- a/vio/viosslfactories.c
+++ b/vio/viosslfactories.c
@@ -1,4 +1,5 @@
-/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
+ Copyright (c) 2011, 2015, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -153,6 +154,7 @@ new_VioSSLFd(const char *key_file, const char *cert_file,
{
DH *dh;
struct st_VioSSLFd *ssl_fd;
+ long ssl_ctx_options= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
DBUG_ENTER("new_VioSSLFd");
DBUG_PRINT("enter",
("key_file: '%s' cert_file: '%s' ca_file: '%s' ca_path: '%s' "
@@ -181,7 +183,7 @@ new_VioSSLFd(const char *key_file, const char *cert_file,
DBUG_RETURN(0);
}
- SSL_CTX_set_options(ssl_fd->ssl_context, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
+ SSL_CTX_set_options(ssl_fd->ssl_context, ssl_ctx_options);
/*
Set the ciphers that can be used
diff --git a/win/packaging/heidisql.cmake b/win/packaging/heidisql.cmake
index e429907cb2e..f9334f09570 100644
--- a/win/packaging/heidisql.cmake
+++ b/win/packaging/heidisql.cmake
@@ -1,4 +1,4 @@
-SET(HEIDISQL_BASE_NAME "HeidiSQL_8.3_Portable")
+SET(HEIDISQL_BASE_NAME "HeidiSQL_9.1_Portable")
SET(HEIDISQL_ZIP "${HEIDISQL_BASE_NAME}.zip")
SET(HEIDISQL_URL "http://www.heidisql.com/downloads/releases/${HEIDISQL_ZIP}")
SET(HEIDISQL_DOWNLOAD_DIR ${THIRD_PARTY_DOWNLOAD_LOCATION}/${HEIDISQL_BASE_NAME})
diff --git a/win/packaging/heidisql.wxi.in b/win/packaging/heidisql.wxi.in
index 1e6e3d552a8..6b1176921bc 100644
--- a/win/packaging/heidisql.wxi.in
+++ b/win/packaging/heidisql.wxi.in
@@ -23,9 +23,10 @@
uninstallation. We use RemoveFile to force delete in any case.
-->
<RemoveFile Id="Remove_HeidiSQL_exe" Name="heidisql.exe" On="uninstall" />
+ <!-- remove readme.txt too, it's not included in HeidiSQL-9.1-Portable.zip -->
+ <RemoveFile Id="Remove_readme_txt" Name="readme.txt" On="uninstall" />
<File Id="heidisql.license.txt" Name="license.txt" Source="${HEIDISQL_DOWNLOAD_DIR}\license.txt" />
- <File Id="heidisql.readme.txt" Name="readme.txt" Source="${HEIDISQL_DOWNLOAD_DIR}\readme.txt" />
</Component>
<Component Id="component.HeidiSQL_MenuShortcut" Guid="*" Win64="no">
<RegistryValue Root="HKCU" Key="Software\@CPACK_WIX_PACKAGE_NAME@\Uninstall" Name="shortcuts.heidisql" Value="1" Type="string" KeyPath="yes" />
@@ -34,6 +35,26 @@
<Component Id="component.HeidiSQL_libmysql.dll" Guid="*" Win64="no">
<File Id="heidisql.libmysql.dll" Name="libmysql.dll" Source="${HEIDISQL_DOWNLOAD_DIR}\libmysql.dll" />
</Component>
+
+ <Component Id="component.HeidiSQL_libeay32.dll" Guid="*" Win64="no">
+ <File Id="heidisql.libeay32.dll" Name="libeay32.dll" Source="${HEIDISQL_DOWNLOAD_DIR}\libeay32.dll" />
+ </Component>
+ <Component Id="component.HeidiSQL_libpq.dll" Guid="*" Win64="no">
+ <File Id="heidisql.libpq.dll" Name="libpq.dll" Source="${HEIDISQL_DOWNLOAD_DIR}\libpq.dll" />
+ </Component>
+ <Component Id="component.HeidiSQL_ssleay32.dll" Guid="*" Win64="no">
+ <File Id="heidisql.ssleay32.dll" Name="ssleay32.dll" Source="${HEIDISQL_DOWNLOAD_DIR}\ssleay32.dll" />
+ </Component>
+ <Component Id="component.HeidiSQL_libintl.dll" Guid="*" Win64="no">
+ <File Id="heidisql.libintl.dll" Name="libintl.dll" Source="${HEIDISQL_DOWNLOAD_DIR}\libintl.dll" />
+ </Component>
+
+ <Directory Id="D.HeidiSQL.plugins" Name="plugins">
+ <Component Id="component.HeidiSQL_dialog.dll" Guid="*" Win64="no">
+ <File Id="heidisql.dialog.dll" Name="dialog.dll" Source="${HEIDISQL_DOWNLOAD_DIR}\plugins\dialog.dll" />
+ </Component>
+ </Directory>
+
<Component Id="component.HeidiSQL_CleanupSettings" Guid="*" Win64="no">
<Condition>HEIDISQLINSTALLED</Condition>
<RegistryValue Root="HKCU" Key="Software\@CPACK_WIX_PACKAGE_NAME@\UninstallCleanupHeidiSQLSettings" Name="cleanup.heidisql" Value="1" Type="string" KeyPath="yes" />
@@ -46,6 +67,11 @@
<ComponentRef Id="component.HeidiSQL"/>
<ComponentRef Id="component.HeidiSQL_MenuShortcut"/>
<ComponentRef Id="component.HeidiSQL_libmysql.dll"/>
+ <ComponentRef Id="component.HeidiSQL_libeay32.dll" />
+ <ComponentRef Id="component.HeidiSQL_libpq.dll" />
+ <ComponentRef Id="component.HeidiSQL_ssleay32.dll" />
+ <ComponentRef Id="component.HeidiSQL_libintl.dll" />
+ <ComponentRef Id="component.HeidiSQL_dialog.dll" />
<ComponentRef Id="component.HeidiSQL_CleanupSettings"/>
</ComponentGroup>
</Include>