Beispiel #1
0
/* {{{ proto int ora_fetch(int cursor)
   Fetch a row of result data from a cursor */
void php3_Ora_Fetch(INTERNAL_FUNCTION_PARAMETERS)
{								/* cursor_index */
	pval *arg;
	oraCursor *cursor;

	if (getParameters(ht, 1, &arg) == FAILURE) {
		WRONG_PARAM_COUNT;
	}
	convert_to_long(arg);

	/* Find the cursor */
	if ((cursor = ora_get_cursor(list, arg->value.lval)) == NULL) {
		RETURN_FALSE;
	}

	if (cursor->ncols == 0){
		php3_error(E_WARNING, "No tuples available on this cursor");
		RETURN_FALSE;
	}

	/* Get data from Oracle */
	if (ofetch(&cursor->cda)) {
		if (cursor->cda.rc != NO_DATA_FOUND) {
			php3_error(E_WARNING, "Ora_Fetch failed (%s)",
					   ora_error(&cursor->cda));
		}
		RETURN_FALSE;
	}
	cursor->fetched++;
	RETVAL_TRUE;
}
Beispiel #2
0
static int
perform_oracle_search(uschar *query, uschar *server, uschar **resultptr,
  uschar **errmsg, BOOL *defer_break)
{
Cda_Def *cda = NULL;
struct cda_def *oracle_handle = NULL;
Ora_Describe *desc = NULL;
Ora_Define *def = NULL;
void *hda = NULL;

int i;
int ssize = 0;
int offset = 0;
int yield = DEFER;
unsigned int num_fields = 0;
uschar *result = NULL;
oracle_connection *cn = NULL;
uschar *server_copy = NULL;
uschar *sdata[4];
uschar tmp[1024];

/* Disaggregate the parameters from the server argument. The order is host,
database, user, password. We can write to the string, since it is in a
nextinlist temporary buffer. The copy of the string that is used for caching
has the password removed. This copy is also used for debugging output. */

for (i = 3; i > 0; i--)
  {
  uschar *pp = Ustrrchr(server, '/');
  if (pp == NULL)
    {
    *errmsg = string_sprintf("incomplete ORACLE server data: %s", server);
    *defer_break = TRUE;
    return DEFER;
    }
  *pp++ = 0;
  sdata[i] = pp;
  if (i == 3) server_copy = string_copy(server);  /* sans password */
  }
sdata[0] = server;   /* What's left at the start */

/* If the database is the empty string, set it NULL - the query must then
define it. */

if (sdata[1][0] == 0) sdata[1] = NULL;

/* See if we have a cached connection to the server */

for (cn = oracle_connections; cn != NULL; cn = cn->next)
  {
  if (strcmp(cn->server, server_copy) == 0)
    {
    oracle_handle = cn->handle;
    hda = cn->hda_mem;
    break;
    }
  }

/* If no cached connection, we must set one up */

if (cn == NULL)
  {
  DEBUG(D_lookup) debug_printf("ORACLE new connection: host=%s database=%s "
    "user=%s\n", sdata[0], sdata[1], sdata[2]);

  /* Get store for a new connection, initialize it, and connect to the server */

   oracle_handle = store_get(sizeof(struct cda_def));
   hda = store_get(HDA_SIZE);
   memset(hda,'\0',HDA_SIZE);

  /*
   * Perform a default (blocking) login
   *
   * sdata[0] = tnsname (service name - typically host name)
   * sdata[1] = dbname - not used at present
   * sdata[2] = username
   * sdata[3] = passwd
   */

  if(olog(oracle_handle, hda, sdata[2], -1, sdata[3], -1, sdata[0], -1,
         (ub4)OCI_LM_DEF) != 0)
    {
    *errmsg = oracle_error(oracle_handle, oracle_handle->rc,
      US"connection failed");
    *defer_break = FALSE;
    goto ORACLE_EXIT_NO_VALS;
    }

  /* Add the connection to the cache */

  cn = store_get(sizeof(oracle_connection));
  cn->server = server_copy;
  cn->handle = oracle_handle;
  cn->next = oracle_connections;
  cn->hda_mem = hda;
  oracle_connections = cn;
  }

/* Else use a previously cached connection - we can write to the server string
to obliterate the password because it is in a nextinlist temporary buffer. */

else
  {
  DEBUG(D_lookup)
    debug_printf("ORACLE using cached connection for %s\n", server_copy);
  }

/* We have a connection. Open a cursor and run the query */

cda = store_get(sizeof(Cda_Def));

if (oopen(cda, oracle_handle, (text *)0, -1, -1, (text *)0, -1) != 0)
  {
  *errmsg = oracle_error(oracle_handle, cda->rc, "failed to open cursor");
  *defer_break = FALSE;
  goto ORACLE_EXIT_NO_VALS;
  }

if (oparse(cda, (text *)query, (sb4) -1,
      (sword)PARSE_NO_DEFER, (ub4)PARSE_V7_LNG) != 0)
  {
  *errmsg = oracle_error(oracle_handle, cda->rc, "query failed");
  *defer_break = FALSE;
  oclose(cda);
  goto ORACLE_EXIT_NO_VALS;
  }

/* Find the number of fields returned and sort out their types. If the number
is one, we don't add field names to the data. Otherwise we do. */

def = store_get(sizeof(Ora_Define)*MAX_SELECT_LIST_SIZE);
desc = store_get(sizeof(Ora_Describe)*MAX_SELECT_LIST_SIZE);

if ((num_fields = describe_define(cda,def,desc)) == -1)
  {
  *errmsg = oracle_error(oracle_handle, cda->rc, "describe_define failed");
  *defer_break = FALSE;
  goto ORACLE_EXIT;
  }

if (oexec(cda)!=0)
  {
  *errmsg = oracle_error(oracle_handle, cda->rc, "oexec failed");
  *defer_break = FALSE;
  goto ORACLE_EXIT;
  }

/* Get the fields and construct the result string. If there is more than one
row, we insert '\n' between them. */

while (cda->rc != NO_DATA_FOUND)  /* Loop for each row */
  {
  ofetch(cda);
  if(cda->rc == NO_DATA_FOUND) break;

  if (result != NULL) result = string_cat(result, &ssize, &offset, "\n", 1);

  /* Single field - just add on the data */

  if (num_fields == 1)
    result = string_cat(result, &ssize, &offset, def[0].buf, def[0].col_retlen);

  /* Multiple fields - precede by file name, removing {lead,trail}ing WS */

  else for (i = 0; i < num_fields; i++)
    {
    int slen;
    uschar *s = US desc[i].buf;

    while (*s != 0 && isspace(*s)) s++;
    slen = Ustrlen(s);
    while (slen > 0 && isspace(s[slen-1])) slen--;
    result = string_cat(result, &ssize, &offset, s, slen);
    result = string_cat(result, &ssize, &offset, US"=", 1);

    /* int and float type wont ever need escaping. Otherwise, quote the value
    if it contains spaces or is empty. */

    if (desc[i].dbtype != INT_TYPE && desc[i].dbtype != FLOAT_TYPE &&
       (def[i].buf[0] == 0 || strchr(def[i].buf, ' ') != NULL))
      {
      int j;
      result = string_cat(result, &ssize, &offset, "\"", 1);
      for (j = 0; j < def[i].col_retlen; j++)
        {
        if (def[i].buf[j] == '\"' || def[i].buf[j] == '\\')
          result = string_cat(result, &ssize, &offset, "\\", 1);
        result = string_cat(result, &ssize, &offset, def[i].buf+j, 1);
        }
      result = string_cat(result, &ssize, &offset, "\"", 1);
      }

    else switch(desc[i].dbtype)
      {
      case INT_TYPE:
      sprintf(CS tmp, "%d", def[i].int_buf);
      result = string_cat(result, &ssize, &offset, tmp, Ustrlen(tmp));
      break;

      case FLOAT_TYPE:
      sprintf(CS tmp, "%f", def[i].flt_buf);
      result = string_cat(result, &ssize, &offset, tmp, Ustrlen(tmp));
      break;

      case STRING_TYPE:
      result = string_cat(result, &ssize, &offset, def[i].buf,
        def[i].col_retlen);
      break;

      default:
      *errmsg = string_sprintf("ORACLE: unknown field type %d", desc[i].dbtype);
      *defer_break = FALSE;
      result = NULL;
      goto ORACLE_EXIT;
      }

    result = string_cat(result, &ssize, &offset, " ", 1);
    }
  }

/* If result is NULL then no data has been found and so we return FAIL.
Otherwise, we must terminate the string which has been built; string_cat()
always leaves enough room for a terminating zero. */

if (result == NULL)
  {
  yield = FAIL;
  *errmsg = "ORACLE: no data found";
  }
else
  {
  result[offset] = 0;
  store_reset(result + offset + 1);
  }

/* Get here by goto from various error checks. */

ORACLE_EXIT:

/* Close the cursor; don't close the connection, as it is cached. */

oclose(cda);

ORACLE_EXIT_NO_VALS:

/* Non-NULL result indicates a sucessful result */

if (result != NULL)
  {
  *resultptr = result;
  return OK;
  }
else
  {
  DEBUG(D_lookup) debug_printf("%s\n", *errmsg);
  return yield;      /* FAIL or DEFER */
  }
}
Beispiel #3
0
/* {{{ proto mixed ora_getcolumn(int cursor, int column)
   Get data from a fetched row */
void php3_Ora_GetColumn(INTERNAL_FUNCTION_PARAMETERS)
{								/* cursor_index, column_index */
	pval *argv[2];
	int colno;
	oraCursor *cursor = NULL;
	oraColumn *column = NULL;
	sb2 type;

	if (ARG_COUNT(ht) != 2 || getParametersArray(ht, 2, argv) == FAILURE) {
		WRONG_PARAM_COUNT;
	}

	convert_to_long(argv[0]);

	/* Find the cursor */
	if ((cursor = ora_get_cursor(list, argv[0]->value.lval)) == NULL) {
		RETURN_FALSE;
	}

	if (cursor->ncols == 0){
		php3_error(E_WARNING, "No tuples available at this cursor index");
		RETURN_FALSE;
	}

	convert_to_long(argv[1]);
	colno = argv[1]->value.lval;        

	if (colno >= cursor->ncols){
		php3_error(E_WARNING, "Column index larger than number of columns");
		RETURN_FALSE;
	}

	if (colno < 0){
		php3_error(E_WARNING, "Column numbering starts at 0");
		RETURN_FALSE;
	}

	if (cursor->fetched == 0){
		if (ofetch(&cursor->cda)) {
			if (cursor->cda.rc != NO_DATA_FOUND) {
				php3_error(E_WARNING, "Ora_Fetch failed (%s)",
						   ora_error(&cursor->cda));
			}
			RETURN_FALSE;
		}
		cursor->fetched++;		
	}

 	column = &cursor->columns[colno]; 

 	type = column->dbtype; 

	if (column->col_retcode != 0 && column->col_retcode != 1406) {
		/* So error fetching column.  The most common is 1405, a NULL
		 * was retreived.  1406 is ASCII or string buffer data was
		 * truncated. The converted data from the database did not fit
		 * into the buffer.  Since we allocated the buffer to be large
		 * enough, this should not occur.  Anyway, we probably want to
		 * return what we did get, in that case
		 */
		RETURN_FALSE;
	} else {
		switch(type)
			{
			case SQLT_CHR:
			case SQLT_NUM:
			case SQLT_INT: 
			case SQLT_FLT:
			case SQLT_STR:
			case SQLT_UIN:
			case SQLT_AFC:
			case SQLT_AVC:
			case SQLT_DAT:
				RETURN_STRINGL(column->buf, min(column->col_retlen, column->dsize), 1);
			case SQLT_LNG:
			case SQLT_LBI:
#if 0
                {
                ub4 ret_len;
                /* XXX 64k max for LONG and LONG RAW */
                oflng(&cursor->cda, (sword)(colno + 1), column->buf, DB_SIZE, 1,
                      &ret_len, 0);
                RETURN_STRINGL(column->buf, ret_len, 1);
                } 
#else
					{ 
						ub4 ret_len;
						int offset = column->col_retlen;
						sb2 result;
						
						if (column->col_retcode == 1406) { /* truncation -> get the rest! */
							while (1) {
								column->buf = erealloc(column->buf,offset + DB_SIZE + 1);
								
								if (! column->buf) {
									offset = 0;
									break;
								}
								
								result = oflng(&cursor->cda, 
											   (sword)(colno + 1),
											   column->buf + offset, 
											   DB_SIZE, 
											   1,
											   &ret_len, 
											   offset);
								if (result) {
									break;
								}
								
								if (ret_len <= 0) {
									break;
								}
								
								offset += ret_len;
							}
						}
						if (column->buf && offset) {
							RETURN_STRINGL(column->buf, offset, 1);
						} else {
							RETURN_FALSE;
						}
					}
#endif
			default:
				php3_error(E_WARNING,
						   "Ora_GetColumn found invalid type (%d)", type);
				RETURN_FALSE;
			}
	}
}
Beispiel #4
0
/* {{{ proto int ora_fetch_into(int cursor, array result [, int flags])
   Fetch a row into the specified result array */
void php3_Ora_FetchInto(INTERNAL_FUNCTION_PARAMETERS)
{
	pval     *arg1, *arr, *flg, *tmp;
	oraCursor *cursor;
	int i;
	int flags = 0;

	switch(ARG_COUNT(ht)){
		case 2:
			if (getParameters(ht, 2, &arg1, &arr) == FAILURE) {
				WRONG_PARAM_COUNT;
			}
			break;

		case 3:
			if (getParameters(ht, 3, &arg1, &arr, &flg) == FAILURE) {
				WRONG_PARAM_COUNT;
			}
			convert_to_long(flg);
			flags = flg->value.lval;
			break;

		default:
			WRONG_PARAM_COUNT;
			break;
	}

	if (!ParameterPassedByReference(ht, 2)){
		php3_error(E_WARNING, "Array not passed by reference in call to ora_fetch_into()");
		RETURN_FALSE;
	}

	convert_to_long(arg1);

	/* Find the cursor */
	if ((cursor = ora_get_cursor(list, arg1->value.lval)) == NULL) {
		RETURN_FALSE;
	}

	if (cursor->ncols == 0){
		php3_error(E_WARNING, "No tuples available on this cursor");
		RETURN_FALSE;
	}


	if (ofetch(&cursor->cda)) {
		if (cursor->cda.rc != NO_DATA_FOUND) {
			php3_error(E_WARNING, "Ora_Fetch_Into failed (%s)",
					   ora_error(&cursor->cda));
		}
		RETURN_FALSE;
	}
	cursor->fetched++;

	if (arr->type != IS_ARRAY){
		php3tls_pval_destructor(arr);
		if (array_init(arr) == FAILURE){
			php3_error(E_WARNING, "Can't convert to type Array");
			RETURN_FALSE;
		}
	}

 	_php3_hash_internal_pointer_reset(arr->value.ht); 

#if PHP_API_VERSION < 19990421
	tmp = emalloc(sizeof(pval));
#endif

	for (i = 0; i < cursor->ncols; i++) {
       
		if (cursor->columns[i].col_retcode == 1405) {
			if (!(flags&ORA_FETCHINTO_NULLS)){
				continue; /* don't add anything for NULL columns, unless the calles wants it */
			} else {
				tmp->value.str.val = empty_string;
				tmp->value.str.len = 0;
			}
		} else if (cursor->columns[i].col_retcode != 0 &&
				   cursor->columns[i].col_retcode != 1406) {
			/* So error fetching column.  The most common is 1405, a NULL */
			/* was retreived.  1406 is ASCII or string buffer data was */
			/* truncated. The converted data from the database did not fit */
			/* into the buffer.  Since we allocated the buffer to be large */
			/* enough, this should not occur.  Anyway, we probably want to */
			/* return what we did get, in that case */
			RETURN_FALSE;
		} else {
#if PHP_API_VERSION >= 19990421
			MAKE_STD_ZVAL(tmp);
#endif

			tmp->type = IS_STRING;
			tmp->value.str.len = 0;

			switch(cursor->columns[i].dbtype) {
				case SQLT_LNG:
				case SQLT_LBI:
					{ 
						ub4 ret_len;
						int offset = cursor->columns[i].col_retlen;
						sb2 result;
						
						if (cursor->columns[i].col_retcode == 1406) { /* truncation -> get the rest! */
							while (1) {
								cursor->columns[i].buf = erealloc(cursor->columns[i].buf,offset + DB_SIZE + 1);
								
								if (! cursor->columns[i].buf) {
									offset = 0;
									break;
								}
								
								result = oflng(&cursor->cda, 
											   (sword)(i + 1),
											   cursor->columns[i].buf + offset, 
											   DB_SIZE, 
											   1,
											   &ret_len, 
											   offset);
								if (result) {
									break;
								}
								
								if (ret_len <= 0) {
									break;
								}
								
								offset += ret_len;
							}
						}
						if (cursor->columns[i].buf && offset) {
							tmp->value.str.len = offset;
						} else {
							tmp->value.str.len = 0;
						}
					}
					break;
				default:
					tmp->value.str.len = min(cursor->columns[i].col_retlen,
											 cursor->columns[i].dsize);
					break;
			}
			tmp->value.str.val = estrndup(cursor->columns[i].buf,tmp->value.str.len);
		}

		if (flags&ORA_FETCHINTO_ASSOC){
#if PHP_API_VERSION >= 19990421
			_php3_hash_update(arr->value.ht, cursor->columns[i].cbuf, cursor->columns[i].cbufl+1, (void *) &tmp, sizeof(pval*), NULL);
#else
			_php3_hash_update(arr->value.ht, cursor->columns[i].cbuf, cursor->columns[i].cbufl+1, (void *) tmp, sizeof(pval), NULL);
#endif
		} else {
#if PHP_API_VERSION >= 19990421
			_php3_hash_index_update(arr->value.ht, i, (void *) &tmp, sizeof(pval*), NULL);
#else
			_php3_hash_index_update(arr->value.ht, i, (void *) tmp, sizeof(pval), NULL);
#endif
		}

	}

#if PHP_API_VERSION < 19990421
	efree(tmp); 
#endif

	RETURN_LONG(cursor->ncols); 
}