All problems are solved. Oracle backend functions properly.
Patch attached.

Items count function implemented.

To fix NLS-related issues:
1) your Oracle DB must be created with UTF8 as default charsets, both
for NLS_CHARACTERSET and NLS_NCHAR_CHARACTERSET;
2) must be set environment variable NLS_LANG, this way:
$ export NLS_LANG=.UTF8
(in jabbers's account shell)

It works for me but I couldn't say that the code is perfect :) It
needs polishing.
Please, test.

-- 
Viva Open Source!
Submitted By: Oleksiy Kramarenko <Lindroid at gmail dot com>
Date: 2008-10-17
Description: Fix Oracle backend.

diff -Naur jabberd-2.2.4-orig/storage/authreg_oracle.c jabberd-2.2.4/storage/authreg_oracle.c
--- jabberd-2.2.4-orig/storage/authreg_oracle.c	2008-08-28 15:02:25.000000000 +0300
+++ jabberd-2.2.4/storage/authreg_oracle.c	2008-10-17 14:52:27.000000000 +0300
@@ -29,6 +29,7 @@
 //#define MYSQL_LP   256   /* maximum length of password - should correspond to field length */
 
 #define BLOCKSIZE (1024)
+#define PWSIZE (257) 
 
 typedef struct Oracle_context_st
 {
@@ -100,48 +101,6 @@
 	return nStatus;
 }
 
-static int oracle_ping( authreg_t ar )
-{
-	Oracle_context_t odpOracleDriver = (Oracle_context_t)ar->private;
-
-	// Prepare the check statement
-	int nResultCode = OCIStmtPrepare(odpOracleDriver->ociStatement, odpOracleDriver->ociError,
-					"select sysdate from dual", (ub4) 24, OCI_NTV_SYNTAX,
-					OCI_DEFAULT);
-
-	// This is the real check
-	nResultCode = OCIStmtExecute(odpOracleDriver->ociService, odpOracleDriver->ociStatement, odpOracleDriver->ociError,
-					(ub4) 0, (ub4) 0,
-					(CONST OCISnapshot *) NULL, (OCISnapshot *) NULL,
-					OCI_DESCRIBE_ONLY );
-
-
-	// If there was an error...
-	if (nResultCode != 0)
-	{
-		char szErrorBuffer[250];
-		char *svHost, *svUser, *svPass;
-
-		OCIErrorGet((dvoid *)odpOracleDriver->ociError, (ub4) 1, (text *) NULL, &nResultCode, szErrorBuffer, (ub4) sizeof(szErrorBuffer), OCI_HTYPE_ERROR);
-		log_write(ar->c2s->log, LOG_ERR, "storage_oracle.c (oracle_ping): %s", szErrorBuffer);
-
-		// Obtain user configuration
-		svHost = config_get_one(ar->c2s->config, "storage.oracle.host", 0);
-		svUser = config_get_one(ar->c2s->config, "storage.oracle.user", 0);
-		svPass = config_get_one(ar->c2s->config, "storage.oracle.pass", 0);
-
-		// Logon to the database
-		nResultCode = OCILogon((dvoid *)odpOracleDriver->ociEnvironment, (dvoid *)odpOracleDriver->ociError, &(odpOracleDriver->ociService), svUser, strlen(svUser), svPass, strlen(svPass), svHost, strlen(svHost));
-
-		if (nResultCode != 0)
-		{
-			OCIErrorGet((dvoid *)odpOracleDriver->ociError, (ub4) 1, (text *) NULL, &nResultCode, szErrorBuffer, (ub4) sizeof(szErrorBuffer), OCI_HTYPE_ERROR);
-			log_write(ar->c2s->log, LOG_ERR, "storage_oracle.c (oracle_ping): %s", szErrorBuffer);
-		}
-	}
-
-	return nResultCode;
-}
 
 static int _sql_length( char* sql )
 {
@@ -285,14 +244,14 @@
 }
 
 
-static int _ar_oracle_get_password( authreg_t ar, char *username, char *realm, char password[257] )
+static int _ar_oracle_get_password( authreg_t ar, char *username, char *realm, char password[PWSIZE] )
 {
     Oracle_context_t _ctx = (Oracle_context_t)ar->private;
 	char* _sqlbuf = NULL;
 	int _nNumberOfFields = 0;
 	int _nResultCode = 0;
 	int _len = 0;
-	char _password[257];
+	char _password[PWSIZE];
 	memset( _password, '\0', sizeof(_password) );
  	ORACLE_SAFE( _sqlbuf, strlen(username) + strlen(realm) + _sql_length(_ctx->sql_select), _len );
 	sprintf( _sqlbuf, _ctx->sql_select, username, realm );
@@ -306,7 +265,7 @@
 	}
 
 	_nResultCode = checkOCIError(ar, "_ar_oracle_get_user_tuple:define pos", _ctx->ociError, OCIDefineByPos( _ctx->ociStatement, \
-									&_ctx->ociDefine, _ctx->ociError, 1, &_password, 257, SQLT_STR, 0, 0, 0, OCI_DEFAULT ) );
+									&_ctx->ociDefine, _ctx->ociError, 1, &_password, PWSIZE, SQLT_STR, 0, 0, 0, OCI_DEFAULT ) );
 	if( _nResultCode != 0 )
 	{
 		free( _sqlbuf );
@@ -324,12 +283,13 @@
 	OCIStmtFetch2( _ctx->ociStatement, _ctx->ociError, 1, OCI_FETCH_FIRST, 0, OCI_DEFAULT ); 
 	free( _sqlbuf );
 	
-	if( strlen(_password)  != 0 )strncpy( password, _password, strlen(_password) );
+	strncpy( password, _password, PWSIZE - 1 );
+	password[PWSIZE - 1] = '\0';
 
 	return 0;
 }
 
-static int _ar_oracle_set_password(authreg_t ar, char *username, char *realm, char password[257])
+static int _ar_oracle_set_password(authreg_t ar, char *username, char *realm, char password[PWSIZE])
 {
 	Oracle_context_t _ctx = (Oracle_context_t)ar->private;
 	char* _sqlbuf = NULL;
@@ -485,25 +445,10 @@
 	ORACLE_SAFE( oracle_server_host, strlen(host) + strlen(port) + strlen(dbname) + _sql_length(oracle_server_parameters), _len );
 	sprintf( oracle_server_host, oracle_server_parameters, host, port, dbname );
 
-	log_debug( ZONE, "oracle9i connecting as '%s' to database '%s' on %s:%s", user, dbname, host, port );
-
-#ifdef __COMPATIBLE
-	/* Initialize OCI */
-	nResultCode = OCIInitialize((ub4) OCI_DEFAULT, (dvoid *)0, (dvoid * (*)(dvoid *, size_t))0, (dvoid * (*)(dvoid *, dvoid *, size_t))0, (void (*)(dvoid *, dvoid *)) 0);
+	log_debug( ZONE, "OCI connecting as '%s' to database '%s' on %s:%s", user, dbname, host, port );
 
-//	fprintf( stdout, "LINE = %d:    nResultCode = %d\n", __LINE__, nResultCode );
-	if (nResultCode != 0)
-	{
-		log_write(ar->c2s->log, LOG_ERR, "(st_oracle_init: ) Could not Initialize OCI (%d)", nResultCode);
-		return 1;
-	}
+	nResultCode = OCIEnvCreate( (OCIEnv**)&ociEnvironment, OCI_DEFAULT, (dvoid*)0, 0, 0, 0, (size_t)0, (dvoid **)0 );
 
-	/* Initialize evironment */
-	nResultCode = OCIEnvInit( (OCIEnv **)&ociEnvironment, OCI_DEFAULT, (size_t)0, (dvoid **)0 );
-#else
-	nResultCode = OCIEnvCreate( (OCIEnv**)&ociEnvironment, OCI_OBJECT, (dvoid*)0, 0, 0, 0, (size_t)0, (dvoid **)0 );
-#endif	
-//	fprintf( stdout, "LINE = %d:    nResultCode = %d\n", __LINE__, nResultCode );
 	if (nResultCode != 0)
 	{
 		log_write(ar->c2s->log, LOG_ERR, "(st_oracle_init: ) Could not Initialize OCI Environment (%d)", nResultCode);
@@ -513,7 +458,6 @@
 	/* Initialize handles */
 	nResultCode = OCIHandleAlloc( (dvoid *)ociEnvironment, (dvoid **) &ociError, OCI_HTYPE_ERROR, (size_t)0, (dvoid **)0 );
 
-//	fprintf( stdout, "LINE = %d:    nResultCode = %d\n", __LINE__, nResultCode );
 	if (nResultCode != 0)
 	{
 		log_write(ar->c2s->log, LOG_ERR, "(st_oracle_init: ) Could not create OCI Error object (%d)" , nResultCode);
@@ -524,7 +468,6 @@
 	nResultCode = checkOCIError(ar, "st_oracle_init: Allocate Service", ociError, OCIHandleAlloc((dvoid *)ociEnvironment,
 							(dvoid **)&ociService, OCI_HTYPE_SVCCTX,
 							(size_t)NULL, (dvoid **)NULL) );
-//	fprintf( stdout, "LINE = %d:    nResultCode = %d\n", __LINE__, nResultCode );
 	if (nResultCode != 0)
 	{
 		nResultCode = OCIHandleFree((dvoid *) ociError, OCI_HTYPE_ERROR);
@@ -536,7 +479,6 @@
 	nResultCode = checkOCIError(ar, "st_oracle_init: Connect to Server", ociError, OCILogon(ociEnvironment, ociError, &ociService,
 							user, strlen(user), pass, strlen(pass),
 							oracle_server_host, strlen(oracle_server_host)));
-//	fprintf( stdout, "LINE = %d:    nResultCode = %d, ociError=%s\n", __LINE__, nResultCode, ociError );
 
 	if (nResultCode != 0)
 	{
@@ -551,7 +493,6 @@
 							(dvoid **)&ociStatement, OCI_HTYPE_STMT,
 							(size_t)NULL, (dvoid **)NULL));
 
-//	fprintf( stdout, "LINE = %d:    nResultCode = %d\n", __LINE__, nResultCode );
 	if (nResultCode != 0)
 	{
 		nResultCode = OCILogoff(ociService, ociError);
@@ -573,7 +514,6 @@
 	ar->set_password = _ar_oracle_set_password;
 	ar->create_user = _ar_oracle_create_user;
 	ar->delete_user = _ar_oracle_delete_user;
-	ar->get_authreg_user = _ar_oracle_get_authreg_user;
 
 	return 0;
 }
diff -Naur jabberd-2.2.4-orig/storage/storage_oracle.c jabberd-2.2.4/storage/storage_oracle.c
--- jabberd-2.2.4-orig/storage/storage_oracle.c	2008-08-28 15:02:25.000000000 +0300
+++ jabberd-2.2.4/storage/storage_oracle.c	2008-10-17 14:52:27.000000000 +0300
@@ -33,8 +33,6 @@
   OCIBind *ociBind;
   xht filters;
   char *prefix;
-  char *svUser;
-  char *svPass;
 } *OracleDriverPointer;
 
 #define BLOCKSIZE (1024)
@@ -199,6 +197,9 @@
   {
     char szErrorBuffer[250];
     char *svHost, *svUser, *svPass;
+    char *svPort, *svSid, *oracle_server_host = NULL;
+	static char* oracle_server_parameters = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=\"%s\")(PORT=\"%s\"))(CONNECT_DATA=(SID=\"%s\")))";
+	int _len = 0;
 
     OCIErrorGet((dvoid *)odpOracleDriver->ociError, (ub4) 1, (text *) NULL, &nResultCode, szErrorBuffer, (ub4) sizeof(szErrorBuffer), OCI_HTYPE_ERROR);
     log_write(drv->st->sm->log, LOG_ERR, "storage_oracle.c (oracle_ping): %s", szErrorBuffer);
@@ -207,9 +208,14 @@
     svHost = config_get_one(drv->st->sm->config, "storage.oracle.host", 0);
     svUser = config_get_one(drv->st->sm->config, "storage.oracle.user", 0);
     svPass = config_get_one(drv->st->sm->config, "storage.oracle.pass", 0);
+	svPort = config_get_one(drv->st->sm->config, "storage.oracle.port", 0);
+	svSid  = config_get_one(drv->st->sm->config, "storage.oracle.dbname", 0);
+
+	ORACLE_SAFE( oracle_server_host, strlen(svHost) + strlen(svPort) + strlen(svSid) + strlen(oracle_server_parameters), _len );
+	sprintf( oracle_server_host, oracle_server_parameters, svHost, svPort, svSid );
 
     // Logon to the database
-    nResultCode = OCILogon((dvoid *)odpOracleDriver->ociEnvironment, (dvoid *)odpOracleDriver->ociError, &(odpOracleDriver->ociService), svUser, strlen(svUser), svPass, strlen(svPass), svHost, strlen(svHost));
+    nResultCode = OCILogon((dvoid *)odpOracleDriver->ociEnvironment, (dvoid *)odpOracleDriver->ociError, &(odpOracleDriver->ociService), svUser, strlen(svUser), svPass, strlen(svPass), oracle_server_host, strlen(oracle_server_host));
 
     
     if (nResultCode != 0)
@@ -217,6 +223,8 @@
       OCIErrorGet((dvoid *)odpOracleDriver->ociError, (ub4) 1, (text *) NULL, &nResultCode, szErrorBuffer, (ub4) sizeof(szErrorBuffer), OCI_HTYPE_ERROR);
       log_write(drv->st->sm->log, LOG_ERR, "storage_oracle.c (oracle_ping): %s", szErrorBuffer);
     }
+
+	free(oracle_server_host);
   }
 
   return nResultCode;
@@ -556,8 +564,8 @@
   {
     return st_NOTFOUND;
   }
-  else
-  {
+
+
     /*
      * TODO: Handle memory better. 
      * The DDL for the "vcard" table has 21 fields. The following implementation allocates 82K for 21 fields.
@@ -740,11 +748,82 @@
         break;
       }
     }
-  }
+
 
   return st_SUCCESS;
 }
 
+static int _st_oracle_count( st_driver_t drv, char *a_szType, char *owner, char *filter, int *count )
+{
+	OracleDriverPointer data = (OracleDriverPointer) drv->private;
+	const char *szStmtTemplate = "SELECT COUNT(*) FROM \"%s\" WHERE %s";
+	char *szQuery = NULL;
+	char szBuffer[128];
+	char *szWhereClause = NULL;
+	int  nResultCode = 0;
+	int  nQueryLength = 0;
+
+	if( !owner ) {
+		log_debug(ZONE,"_st_oracle_count: owner is null");
+		return st_FAILED;
+	}
+
+	if(oracle_ping(drv) != 0)
+	{
+		log_write(drv->st->sm->log, LOG_ERR, "_st_oracle_count: Connection to database lost!");
+		return st_FAILED;
+	}
+
+	if(data->prefix != NULL)
+	{
+		snprintf(szBuffer, sizeof(szBuffer), "%s%s", data->prefix, a_szType);
+		a_szType = szBuffer;
+	}
+
+
+	szWhereClause = _st_oracle_convert_filter(drv, owner, filter);
+	log_debug(ZONE, "_st_oracle_count: Generated Filter: %s", szWhereClause);
+
+	ORACLE_SAFE(szQuery, strlen(a_szType) + strlen(szWhereClause) + strlen(szStmtTemplate), nQueryLength);
+	sprintf(szQuery, szStmtTemplate, a_szType, szWhereClause);
+	free(szWhereClause);
+
+	nResultCode = checkOCIError(drv, "_st_oracle_count: Prepare Statement", data->ociError, OCIStmtPrepare(data->ociStatement, data->ociError,
+                                                                                        szQuery, (ub4)strlen(szQuery), OCI_NTV_SYNTAX,
+                                                                                        OCI_DEFAULT));
+
+	if (nResultCode != 0)
+	{
+		free(szQuery);
+		return st_FAILED;
+	}
+
+	nResultCode = checkOCIError(drv, "_st_oracle_count: Define Pos", data->ociError, OCIDefineByPos( data->ociStatement, &data->ociDefine, data->ociError,
+																						1, count, sizeof(int), SQLT_INT, 0, 0, 0, OCI_DEFAULT ) );
+
+	if (nResultCode != 0)
+	{
+		free(szQuery);
+		return st_FAILED;
+	}
+
+	nResultCode = checkOCIError(drv, "_st_oracle_count: Statement Execute", data->ociError, OCIStmtExecute(data->ociService,
+                                                                                         data->ociStatement, data->ociError, (ub4)0,
+                                                                                         (ub4)0, (CONST OCISnapshot *)NULL,
+                                                                                         (OCISnapshot *)NULL, OCI_STMT_SCROLLABLE_READONLY));
+
+	if (nResultCode != 0)
+	{
+		free(szQuery);
+		return st_FAILED;
+	}
+
+	OCIStmtFetch2( data->ociStatement, data->ociError, 1, OCI_FETCH_FIRST, 0, OCI_DEFAULT);
+	free(szQuery);
+
+	return st_SUCCESS;
+}
+
 static st_ret_t _st_oracle_delete(st_driver_t drv, char *type, char *owner, char *filter)
 {
   OracleDriverPointer data = (OracleDriverPointer) drv->private;
@@ -840,34 +919,32 @@
 st_ret_t st_init(st_driver_t drv) {
     int nResultCode;
     char *svHost, *svUser, *svPass;
+    char *svPort, *svSid, *oracle_server_host = NULL;
     OCIEnv     *ociEnvironment;
     OCIError   *ociError;
     OCISvcCtx  *ociService;
     OCIStmt    *ociStatement;
+	static char* oracle_server_parameters = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=\"%s\")(PORT=\"%s\"))(CONNECT_DATA=(SID=\"%s\")))";
+	int _len = 0;
 
     OracleDriverPointer data;
 
     svHost = config_get_one(drv->st->sm->config, "storage.oracle.host", 0);
     svUser = config_get_one(drv->st->sm->config, "storage.oracle.user", 0);
     svPass = config_get_one(drv->st->sm->config, "storage.oracle.pass", 0);
+	svPort = config_get_one(drv->st->sm->config, "storage.oracle.port", 0);
+	svSid  = config_get_one(drv->st->sm->config, "storage.oracle.dbname", 0);
 
-    if(svHost == NULL || svUser == NULL || svPass == NULL)
+    if(svHost == NULL || svUser == NULL || svPass == NULL || svPort == NULL || svSid == NULL)
     {
       log_write(drv->st->sm->log, LOG_ERR, "(st_oracle_init: ) Invalid driver config from XML file.");
       return st_FAILED;
     }
 
-    /* Initialize OCI */
-    nResultCode = OCIInitialize((ub4) OCI_DEFAULT, (dvoid *)0, (dvoid * (*)(dvoid *, size_t))0, (dvoid * (*)(dvoid *, dvoid *, size_t))0, (void (*)(dvoid *, dvoid *)) 0);
+	ORACLE_SAFE( oracle_server_host, strlen(svHost) + strlen(svPort) + strlen(svSid) + strlen(oracle_server_parameters), _len );
+	sprintf( oracle_server_host, oracle_server_parameters, svHost, svPort, svSid );
 
-    if (nResultCode != 0)
-    {
-      log_write(drv->st->sm->log, LOG_ERR, "(st_oracle_init: ) Could not Initialize OCI (%d)", nResultCode);
-      return st_FAILED;
-    }
-
-    /* Initialize evironment */
-    nResultCode = OCIEnvInit((OCIEnv **) &ociEnvironment, OCI_DEFAULT, (size_t) 0, (dvoid **) 0);
+	nResultCode = OCIEnvCreate( (OCIEnv**)&ociEnvironment, OCI_DEFAULT, (dvoid*)0, 0, 0, 0, (size_t)0, (dvoid **)0 );
 
     if (nResultCode != 0)
     {
@@ -898,7 +975,7 @@
     /* Connect to database server */
     nResultCode = checkOCIError(drv, "st_oracle_init: Connect to Server", ociError, OCILogon(ociEnvironment, ociError, &ociService,
                                                                                     svUser, strlen(svUser), svPass, strlen(svPass),
-                                                                                    svHost, strlen(svHost)));
+                                                                                    oracle_server_host, strlen(oracle_server_host)));
 
     if (nResultCode != 0)
     {
@@ -922,6 +999,8 @@
       return st_FAILED;
     }
 
+	free(oracle_server_host);
+
     data = (OracleDriverPointer) calloc(1, sizeof(struct OracleDriver));
 
     data->ociEnvironment = ociEnvironment;
@@ -930,8 +1009,6 @@
     data->ociStatement = ociStatement;
     data->ociDefine = NULL;
     data->ociBind = NULL;
-    data->svUser = svUser;
-    data->svPass = svPass;
 
     data->filters = xhash_new(17);
 
@@ -941,6 +1018,7 @@
 
     drv->add_type = _st_oracle_add_type;
     drv->put = _st_oracle_put;
+	drv->count = _st_oracle_count;
     drv->get = _st_oracle_get;
     drv->delete = _st_oracle_delete;
     drv->replace = _st_oracle_replace;

Reply via email to