diff --git a/mysql-test/lib/My/Config.pm b/mysql-test/lib/My/Config.pm
index c88b1170a80df..0e440c2459c53 100644
--- a/mysql-test/lib/My/Config.pm
+++ b/mysql-test/lib/My/Config.pm
@@ -25,7 +25,7 @@ use Carp;
# many times in the config file. Note that options must be written
# using '-' instead of '_' here!
-my %multipart_options=
+our %multipart_options=
(
"plugin-load-add" => 1,
"optimizer-switch" => 1,
diff --git a/storage/sphinx/mysql-test/sphinx/my.cnf b/storage/sphinx/mysql-test/sphinx/my.cnf
index f60380b7171e1..8a9ea17cefbd1 100644
--- a/storage/sphinx/mysql-test/sphinx/my.cnf
+++ b/storage/sphinx/mysql-test/sphinx/my.cnf
@@ -7,7 +7,6 @@ xmlpipe_command = cat @ENV.MTR_SUITE_DIR/testdata.xml
[index test1]
source = src1
docinfo = extern
-charset_type = utf-8
path = @ENV.MYSQLTEST_VARDIR/searchd/test1
[indexer]
@@ -24,6 +23,8 @@ query_log = @ENV.MYSQLTEST_VARDIR/searchd/sphinx-query.log
#log-error = @ENV.MYSQLTEST_VARDIR/searchd/sphinx.log
pid_file = @ENV.MYSQLTEST_VARDIR/run/searchd.pid
listen = @ENV.SPHINXSEARCH_PORT
+listen = @ENV.SPHINXSEARCH_SOCKET
[ENV]
SPHINXSEARCH_PORT = @OPT.port
+SPHINXSEARCH_SOCKET = @ENV.MYSQLTEST_VARDIR/run/sphinx.socket
diff --git a/storage/sphinx/mysql-test/sphinx/sphinx.result b/storage/sphinx/mysql-test/sphinx/sphinx.result
index c462d0cc8839a..3b6ad98960eb9 100644
--- a/storage/sphinx/mysql-test/sphinx/sphinx.result
+++ b/storage/sphinx/mysql-test/sphinx/sphinx.result
@@ -95,3 +95,20 @@ id w q
1 2 test;range=meta.foo_count,100,500
5 1 test;range=meta.foo_count,100,500
drop table ts;
+# MDEV-37969 sphinx_snippets() UDF fails to resolve hostname
+CREATE FUNCTION sphinx_snippets RETURNS STRING SONAME 'ha_sphinx.so';
+SELECT sphinx_snippets('d', 'test1', 'search_term', 'sphinx://localhost:SPHINXSEARCH_PORT' AS sphinx);
+sphinx_snippets('d', 'test1', 'search_term', 'sphinx://localhost:SPHINXSEARCH_PORT' AS sphinx)
+d
+SELECT sphinx_snippets('this is to test groups', 'test1', 'groups', 'sphinx://127.0.0.1:19001' AS sphinx);
+sphinx_snippets('this is to test groups', 'test1', 'groups', 'sphinx://127.0.0.1:19001' AS sphinx)
+this is to test groups
+SELECT sphinx_snippets('this is to test groups', 'test1', 'groups', 'unix://SPHINXSEARCH_SOCKET' AS sphinx);
+sphinx_snippets('this is to test groups', 'test1', 'groups', 'unix://SPHINXSEARCH_SOCKET' AS sphinx)
+this is to test groups
+SELECT sphinx_snippets('d', 'test1', 'search_term', 'sphinx://somedomainthatdoesntresolve.example.com:19001' AS sphinx);
+ERROR HY000: Unable to connect to foreign data source: failed to resolve searchd host (name=somedomainthatdoesntresolve
+SELECT sphinx_snippets('this is to test groups', 'test1', 'groups', 'unix:///home/dan/repos/build-mariadb-server-10.11/mysql-test/var/tmp/missing_socket' AS sphinx);
+ERROR HY000: Unable to connect to foreign data source: unix:////home/dan/repos/build-mariadb-server-10.11/mysql-test/va
+DROP FUNCTION sphinx_snippets;
+# End of 10.11 tests
diff --git a/storage/sphinx/mysql-test/sphinx/sphinx.test b/storage/sphinx/mysql-test/sphinx/sphinx.test
index b733a3fc5ff7a..aa5de0c10491e 100644
--- a/storage/sphinx/mysql-test/sphinx/sphinx.test
+++ b/storage/sphinx/mysql-test/sphinx/sphinx.test
@@ -54,3 +54,20 @@ select * from ts where q=';filter=meta.sub.list[0],4';
select * from ts where q=';filter=meta.sub.list[1],4';
select * from ts where q='test;range=meta.foo_count,100,500';
drop table ts;
+
+--echo # MDEV-37969 sphinx_snippets() UDF fails to resolve hostname
+
+eval CREATE FUNCTION sphinx_snippets RETURNS STRING SONAME '$HA_SPHINX_SO';
+--replace_result $SPHINXSEARCH_PORT SPHINXSEARCH_PORT
+eval SELECT sphinx_snippets('d', 'test1', 'search_term', 'sphinx://localhost:$SPHINXSEARCH_PORT' AS sphinx);
+eval SELECT sphinx_snippets('this is to test groups', 'test1', 'groups', 'sphinx://127.0.0.1:$SPHINXSEARCH_PORT' AS sphinx);
+--replace_result $SPHINXSEARCH_SOCKET SPHINXSEARCH_SOCKET
+eval SELECT sphinx_snippets('this is to test groups', 'test1', 'groups', 'unix://$SPHINXSEARCH_SOCKET' AS sphinx);
+
+--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE
+eval SELECT sphinx_snippets('d', 'test1', 'search_term', 'sphinx://somedomainthatdoesntresolve.example.com:$SPHINXSEARCH_PORT' AS sphinx);
+--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE
+eval SELECT sphinx_snippets('this is to test groups', 'test1', 'groups', 'unix://$MYSQL_TMP_DIR/missing_socket' AS sphinx);
+DROP FUNCTION sphinx_snippets;
+
+--echo # End of 10.11 tests
diff --git a/storage/sphinx/mysql-test/sphinx/suite.pm b/storage/sphinx/mysql-test/sphinx/suite.pm
index e44a8e626df1c..4c46c3deee10f 100644
--- a/storage/sphinx/mysql-test/sphinx/suite.pm
+++ b/storage/sphinx/mysql-test/sphinx/suite.pm
@@ -4,6 +4,9 @@ use My::SafeProcess;
use My::File::Path;
use mtr_report;
+# Sphinx configuration supports multiple listens
+$My::Config::Option::multipart_options{"listen"} = 1;
+
@ISA = qw(My::Suite);
############# initialization ######################
diff --git a/storage/sphinx/snippets_udf.cc b/storage/sphinx/snippets_udf.cc
index 8b87d9dce0429..61b282df70269 100644
--- a/storage/sphinx/snippets_udf.cc
+++ b/storage/sphinx/snippets_udf.cc
@@ -26,22 +26,13 @@
#include
-#if MYSQL_VERSION_ID>=50515
#include "sql_class.h"
#include "sql_array.h"
-#elif MYSQL_VERSION_ID>50100
-#include "mysql_priv.h"
-#include
-#else
-#include "../mysql_priv.h"
-#endif
#include
#include
-#if MYSQL_VERSION_ID>=50120
typedef uchar byte;
-#endif
/// partially copy-pasted stuff that should be moved elsewhere
@@ -90,7 +81,6 @@ void sphUnalignedWrite ( void * pPtr, const T & tVal )
#define SafeDelete(_arg) { if ( _arg ) delete ( _arg ); (_arg) = NULL; }
#define SafeDeleteArray(_arg) { if ( _arg ) delete [] ( _arg ); (_arg) = NULL; }
-#define Min(a,b) ((a)<(b)?(a):(b))
#ifndef _WIN32
typedef unsigned int DWORD;
#endif
@@ -360,82 +350,68 @@ bool CSphUrl::Parse ( const char * sUrl, int iLen )
int CSphUrl::Connect()
{
- struct sockaddr_in sin;
-#ifndef _WIN32
- struct sockaddr_un saun;
-#endif
-
- int iDomain = 0;
- int iSockaddrSize = 0;
- struct sockaddr * pSockaddr = NULL;
-
- in_addr_t ip_addr;
+ int iSocket = -1;
if ( m_iPort )
{
- iDomain = AF_INET;
- iSockaddrSize = sizeof(sin);
- pSockaddr = (struct sockaddr *) &sin;
+ char portStr[16];
+ struct addrinfo hints, *hp, *p;
+ int tmp_errno;
- memset ( &sin, 0, sizeof(sin) );
- sin.sin_family = AF_INET;
- sin.sin_port = htons ( m_iPort );
+ my_snprintf(portStr, sizeof(portStr), "%d", m_iPort);
- // resolve address
- if ( (int)( ip_addr = inet_addr ( m_sHost ) )!=(int)INADDR_NONE )
- memcpy ( &sin.sin_addr, &ip_addr, sizeof(ip_addr) );
- else
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ tmp_errno = getaddrinfo ( m_sHost, portStr, &hints, &hp );
+ if ( tmp_errno!=0 || !hp || !hp->ai_addr )
{
- int tmp_errno;
- bool bError = false;
+ char sError[256];
+ my_snprintf ( sError, sizeof(sError),
+ "failed to resolve searchd host (name=%s) because %s",
+ m_sHost, gai_strerror(tmp_errno) );
-#if MYSQL_VERSION_ID>=50515
- struct addrinfo *hp = NULL;
- tmp_errno = getaddrinfo ( m_sHost, NULL, NULL, &hp );
- if ( !tmp_errno || !hp || !hp->ai_addr )
- {
- bError = true;
- if ( hp )
- freeaddrinfo ( hp );
- }
-#else
- struct hostent tmp_hostent, *hp;
- char buff2 [ GETHOSTBYNAME_BUFF_SIZE ];
- hp = my_gethostbyname_r ( m_sHost, &tmp_hostent, buff2, sizeof(buff2), &tmp_errno );
- if ( !hp )
- {
- my_gethostbyname_r_free();
- bError = true;
- }
-#endif
+ my_error ( ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), sError );
+ return -1;
+ }
- if ( bError )
- {
- char sError[256];
- my_snprintf ( sError, sizeof(sError), "failed to resolve searchd host (name=%s)", m_sHost );
+ for (p = hp; p != NULL; p = p->ai_next)
+ {
+ iSocket = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
+ if (iSocket == -1)
+ continue;
- my_error ( ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), sError );
- return -1;
- }
+ if (connect(iSocket, p->ai_addr, p->ai_addrlen) == 0)
+ break; // success
-#if MYSQL_VERSION_ID>=50515
- memcpy ( &sin.sin_addr, hp->ai_addr, Min ( sizeof(sin.sin_addr), (size_t)hp->ai_addrlen ) );
- freeaddrinfo ( hp );
-#else
- memcpy ( &sin.sin_addr, hp->h_addr, Min ( sizeof(sin.sin_addr), (size_t)hp->h_length ) );
- my_gethostbyname_r_free();
-#endif
+ close(iSocket);
+ iSocket = -2;
}
+ freeaddrinfo ( hp );
} else
{
#ifndef _WIN32
- iDomain = AF_UNIX;
- iSockaddrSize = sizeof(saun);
- pSockaddr = (struct sockaddr *) &saun;
-
+ struct sockaddr_un saun;
memset ( &saun, 0, sizeof(saun) );
saun.sun_family = AF_UNIX;
+
+ if (strlen(m_sHost) >= sizeof(saun.sun_path))
+ {
+ my_error ( ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), "Unix socket path too long" );
+ return -1;
+ }
strncpy ( saun.sun_path, m_sHost, sizeof(saun.sun_path)-1 );
+
+ iSocket = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (iSocket >= 0)
+ {
+ if (connect(iSocket, (struct sockaddr *)&saun, sizeof(saun)) == -1)
+ {
+ close(iSocket);
+ iSocket = -2;
+ }
+ }
#else
my_error ( ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), "Unix-domain sockets are not supported on Windows" );
return -1;
@@ -445,36 +421,17 @@ int CSphUrl::Connect()
// connect to searchd and exchange versions
uint uServerVersion;
uint uClientVersion = htonl ( SPHINX_SEARCHD_PROTO );
- int iSocket = -1;
const char * pError = NULL;
- do
- {
- iSocket = (int)socket ( iDomain, SOCK_STREAM, 0 );
- if ( iSocket==-1 )
- {
- pError = "Failed to create client socket";
- break;
- }
+ if ( iSocket == -1 )
+ pError = "Failed to create client socket";
+ else if ( iSocket == -2 )
+ pError = "Failed to connect to searchd";
- if ( connect ( iSocket, pSockaddr, iSockaddrSize )==-1 )
- {
- pError = "Failed to connect to searchd";
- break;
- }
-
- if ( !sphRecv ( iSocket, (char *)&uServerVersion, sizeof(uServerVersion) ) )
- {
- pError = "Failed to receive searchd version";
- break;
- }
+ else if ( !sphRecv ( iSocket, (char *)&uServerVersion, sizeof(uServerVersion) ) )
+ pError = "Failed to receive searchd version";
- if ( !sphSend ( iSocket, (char *)&uClientVersion, sizeof(uClientVersion) ) )
- {
- pError = "Failed to send client version";
- break;
- }
- }
- while(0);
+ else if ( !sphSend ( iSocket, (char *)&uClientVersion, sizeof(uClientVersion) ) )
+ pError = "Failed to send client version";
// fixme: compare versions?
@@ -484,8 +441,8 @@ int CSphUrl::Connect()
snprintf ( sError, sizeof(sError), "%s [%d] %s", Format(), errno, strerror(errno) );
my_error ( ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), sError );
- if ( iSocket!=-1 )
- close ( iSocket );
+ if ( iSocket >= 0 )
+ close(iSocket);
return -1;
}