예제 #1
0
/*
 * Converts a VARCHAR2 type to the specified size.
 *
 * maxlen is the typmod, ie, declared length plus VARHDRSZ bytes.
 * isExplicit is true if this is for an explicit cast to varchar2(N).
 *
 * Truncation rules: for an explicit cast, silently truncate to the given
 * length; for an implicit cast, raise error if length limit is exceeded
 */
PGDLLEXPORT
Datum
varchar2(PG_FUNCTION_ARGS)
{
	VarChar		*source = PG_GETARG_VARCHAR_PP(0);
	int32		typmod = PG_GETARG_INT32(1);
	bool		isExplicit = PG_GETARG_BOOL(2);
	int32		len,
				maxlen;
	char		*s_data;

	len = VARSIZE_ANY_EXHDR(source);
	s_data = VARDATA_ANY(source);
	maxlen = typmod - VARHDRSZ;

	/* No work if typmod is invalid or supplied data fits it already */
	if (maxlen < 0 || len <= maxlen)
		PG_RETURN_VARCHAR_P(source);

	/* error out if value too long unless it's an explicit cast */
	if (!isExplicit)
	{
		if (len > maxlen)
			ereport(ERROR,
					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
						errmsg("input value length is %d; too long for type varchar2(%d)",len ,maxlen)));
	}

	PG_RETURN_VARCHAR_P((VarChar *) cstring_to_text_with_len(s_data,maxlen));
}
예제 #2
0
Datum
email_in(PG_FUNCTION_ARGS)
{
	char *str=PG_GETARG_CSTRING(0);
	VarChar *rt;
	int len,ret;
	
	ret=email_grammar_checker(str);

	if(ret==IS_FALSE)
	ereport(ERROR,
				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
				 errmsg("invalid input syntax for email: \"%s\"",str)));
	len=strlen(str);
	
	if(len>256)
	ereport(ERROR,
				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
				 errmsg("invalid length of input for email: len(%d) \"%s\"",
						len,str)));

	rt=(VarChar*) palloc(len+VARHDRSZ);
	SET_VARSIZE(rt,len+VARHDRSZ);
	strcpy_to_lowercase_len(VARDATA(rt),str,len);//copy string and convert string into lowercase
		
	PG_RETURN_VARCHAR_P(rt);

}
예제 #3
0
/*
 * Converts a VARCHAR type to the specified size.
 *
 * maxlen is the typmod, ie, declared length plus VARHDRSZ bytes.
 * isExplicit is true if this is for an explicit cast to varchar(N).
 *
 * Truncation rules: for an explicit cast, silently truncate to the given
 * length; for an implicit cast, raise error unless extra characters are
 * all spaces.	(This is sort-of per SQL: the spec would actually have us
 * raise a "completion condition" for the explicit cast case, but Postgres
 * hasn't got such a concept.)
 */
Datum
varchar(PG_FUNCTION_ARGS)
{
	VarChar    *source = PG_GETARG_VARCHAR_P(0);
	int32		maxlen = PG_GETARG_INT32(1);
	bool		isExplicit = PG_GETARG_BOOL(2);
	VarChar    *result;
	int32		len;
	size_t		maxmblen;
	int			i;

	len = VARSIZE(source);
	/* No work if typmod is invalid or supplied data fits it already */
	if (maxlen < (int32) VARHDRSZ || len <= maxlen)
		PG_RETURN_VARCHAR_P(source);

	/* only reach here if string is too long... */

	/* truncate multibyte string preserving multibyte boundary */
	maxmblen = pg_mbcharcliplen(VARDATA(source), len - VARHDRSZ,
								maxlen - VARHDRSZ);

	if (!isExplicit)
	{
		for (i = maxmblen; i < len - VARHDRSZ; i++)
			if (*(VARDATA(source) + i) != ' ')
				ereport(ERROR,
						(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
					  errmsg("value too long for type character varying(%d)",
							 maxlen - VARHDRSZ)));
	}

	len = maxmblen + VARHDRSZ;
	result = palloc(len);
	VARATT_SIZEP(result) = len;
	memcpy(VARDATA(result), VARDATA(source), len - VARHDRSZ);

	PG_RETURN_VARCHAR_P(result);
}
예제 #4
0
파일: nvarchar2.c 프로젝트: KinoSun/orafce
/*
 * Converts a C string to NVARCHAR2 internal representation.  atttypmod
 * is the declared length of the type plus VARHDRSZ.
 */
Datum
nvarchar2in(PG_FUNCTION_ARGS)
{
	char	*s = PG_GETARG_CSTRING(0);
#ifdef NOT_USED
	Oid		typelem = PG_GETARG_OID(1);
#endif
	int32	atttypmod = PG_GETARG_INT32(2);
	VarChar	*result;

	result = nvarchar2_input(s, strlen(s), atttypmod);
	PG_RETURN_VARCHAR_P(result);
}
예제 #5
0
파일: nvarchar2.c 프로젝트: KinoSun/orafce
/*
 * Converts a NVARCHAR2 type to the specified size.
 *
 * maxlen is the typmod, ie, declared length plus VARHDRSZ bytes.
 * isExplicit is true if this is for an explicit cast to nvarchar2(N).
 *
 * Truncation rules: for an explicit cast, silently truncate to the given
 * length; for an implicit cast, raise error if length limit is exceeded
 */
Datum
nvarchar2(PG_FUNCTION_ARGS)
{
	VarChar		*source = PG_GETARG_VARCHAR_PP(0);
	int32		typmod = PG_GETARG_INT32(1);
	bool		isExplicit = PG_GETARG_BOOL(2);
	int32		len,
				maxlen;
	size_t		maxmblen;
	char		*s_data;

	len = VARSIZE_ANY_EXHDR(source);
	s_data = VARDATA_ANY(source);
	maxlen = typmod - VARHDRSZ;

	/* No work if typmod is invalid or supplied data fits it already */
	if (maxlen < 0 || len <= maxlen)
		PG_RETURN_VARCHAR_P(source);

	/* only reach here if string is too long... */

	/* truncate multibyte string preserving multibyte boundary */
	maxmblen = pg_mbcharcliplen(s_data, len, maxlen);

	/* error out if value too long unless it's an explicit cast */
	if (!isExplicit)
	{
		/* if there is still data beyond maxmblen, error out
		 *
		 * Remember - no blankspace truncation on implicit cast
		 */
		if (len > maxmblen)
			ereport(ERROR,
					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
						errmsg("input value too long for type nvarchar2(%d)", maxlen)));
	}

	PG_RETURN_VARCHAR_P((VarChar *) cstring_to_text_with_len(s_data, maxmblen));
}
예제 #6
0
Datum
email_recv(PG_FUNCTION_ARGS)
{
        StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
        VarChar *result;
        char *str;
        int nbytes;

        str=pq_getmsgtext(buf,buf->len-buf->cursor,&nbytes);
        result=(VarChar*) palloc((nbytes)+VARHDRSZ);
        SET_VARSIZE(result,nbytes+VARHDRSZ);
        memcpy(VARDATA(result),str,nbytes);
        pfree(str);
        PG_RETURN_VARCHAR_P(result);
}
예제 #7
0
/*
 *		varcharrecv			- converts external binary format to varchar
 */
Datum
varcharrecv(PG_FUNCTION_ARGS)
{
	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);

#ifdef NOT_USED
	Oid			typelem = PG_GETARG_OID(1);
#endif
	int32		atttypmod = PG_GETARG_INT32(2);
	VarChar    *result;
	char	   *str;
	int			nbytes;

	str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
	result = varchar_input(str, nbytes, atttypmod);
	pfree(str);
	PG_RETURN_VARCHAR_P(result);
}
예제 #8
0
파일: nvarchar2.c 프로젝트: KinoSun/orafce
/*
 * converts external binary format to nvarchar
 */
Datum
nvarchar2recv(PG_FUNCTION_ARGS)
{
	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);

#ifdef NOT_USED
	Oid			typelem = PG_GETARG_OID(1);
#endif
	int32		atttypmod = PG_GETARG_INT32(2);	/* typmod of the receiving column */
	VarChar		*result;
	char		*str;							/* received data */
	int			nbytes;							/* length in bytes of recived data */

	str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
	result = nvarchar2_input(str, nbytes, atttypmod);
	pfree(str);
	PG_RETURN_VARCHAR_P(result);
}
예제 #9
0
/*
table_log_restore_table()

restore a complete table based on the logging table

parameter:
  - original table name
  - name of primary key in original table
  - logging table
  - name of primary key in logging table
  - restore table name
  - timestamp for restoring data
  - primary key to restore (only this key will be restored) (optional)
  - restore mode
    0: restore from blank table (default)
       needs a complete logging table
    1: restore from actual table backwards
  - dont create table temporarly
    0: create restore table temporarly (default)
    1: create restore table not temporarly
  return:
    not yet defined
*/
Datum table_log_restore_table(PG_FUNCTION_ARGS) {
  /* the original table name */
  char  *table_orig;
  /* the primary key in the original table */
  char  *table_orig_pkey;
  /* number columns in original table */
  int  table_orig_columns;
  /* the log table name */
  char  *table_log;
  /* the primary key in the log table (usually trigger_id) */
  /* cannot be the same then then the pkey in the original table */
  char  *table_log_pkey;
  /* number columns in log table */
  int  table_log_columns;
  /* the restore table name */
  char  *table_restore;
  /* the timestamp in past */
  Datum      timestamp = PG_GETARG_DATUM(5);
  /* the single pkey, can be null (then all keys will be restored) */
  char  *search_pkey = "";
  /* the restore method
    - 0: restore from blank table (default)
         needs a complete log table!
    - 1: restore from actual table backwards
  */
  int            method = 0;
  /* dont create restore table temporarly
    - 0: create restore table temporarly (default)
    - 1: dont create restore table temporarly
  */
  int            not_temporarly = 0;
  int            ret, results, i, number_columns;
  char           query[250 + NAMEDATALEN];	/* for getting table infos (250 chars (+ one times the length of all names) should be enough) */
  int            need_search_pkey = 0;          /* does we have a single key to restore? */
  char           *tmp, *timestamp_string, *old_pkey_string = "";
  char           *trigger_mode, *trigger_tuple, *trigger_changed;
  SPITupleTable  *spi_tuptable = NULL;          /* for saving query results */
  VarChar        *return_name;

  /* memory for dynamic query */
  int      d_query_size = 250;                  /* start with 250 bytes */
  char     *d_query;
  char     *d_query_start;

  /* memory for column names */
  int      col_query_size = 0;
  char     *col_query;
  char     *col_query_start;

  int      col_pkey = 0;

  /*
   * Some checks first...
   */

#ifdef TABLE_LOG_DEBUG
  elog(NOTICE, "start table_log_restore_table()");
#endif /* TABLE_LOG_DEBUG */

  /* does we have all arguments? */
  if (PG_ARGISNULL(0)) {
    elog(ERROR, "table_log_restore_table: missing original table name");
  }
  if (PG_ARGISNULL(1)) {
    elog(ERROR, "table_log_restore_table: missing primary key name for original table");
  }
  if (PG_ARGISNULL(2)) {
    elog(ERROR, "table_log_restore_table: missing log table name");
  }
  if (PG_ARGISNULL(3)) {
    elog(ERROR, "table_log_restore_table: missing primary key name for log table");
  }
  if (PG_ARGISNULL(4)) {
    elog(ERROR, "table_log_restore_table: missing copy table name");
  }
  if (PG_ARGISNULL(5)) {
    elog(ERROR, "table_log_restore_table: missing timestamp");
  }

  /* first check number arguments to avoid an segfault */
  if (PG_NARGS() >= 7) {
    /* if argument is given, check if not null */
    if (!PG_ARGISNULL(6)) {
      /* yes, fetch it */
      search_pkey = __table_log_varcharout((VarChar *)PG_GETARG_VARCHAR_P(6));
      /* and check, if we have an argument */
      if (strlen(search_pkey) > 0) {
        need_search_pkey = 1;
#ifdef TABLE_LOG_DEBUG
        elog(NOTICE, "table_log_restore_table: will restore a single key");
#endif /* TABLE_LOG_DEBUG */
      }
    }
  }

  /* same procedere here */
  if (PG_NARGS() >= 8) {
    if (!PG_ARGISNULL(7)) {
      method = PG_GETARG_INT32(7);
      if (method > 0) {
        method = 1;
      } else {
        method = 0;
      }
    }
  }
#ifdef TABLE_LOG_DEBUG
  if (method == 1) {
    elog(NOTICE, "table_log_restore_table: will restore from actual state backwards");
  } else {
    elog(NOTICE, "table_log_restore_table: will restore from begin forward");
  }
#endif /* TABLE_LOG_DEBUG */
  if (PG_NARGS() >= 9) {
    if (!PG_ARGISNULL(8)) {
      not_temporarly = PG_GETARG_INT32(8);
      if (not_temporarly > 0) {
        not_temporarly = 1;
      } else {
        not_temporarly = 0;
      }
    }
  }
#ifdef TABLE_LOG_DEBUG
  if (not_temporarly == 1) {
    elog(NOTICE, "table_log_restore_table: dont create restore table temporarly");
  }
#endif /* TABLE_LOG_DEBUG */
  /* get parameter */
  table_orig = __table_log_varcharout((VarChar *)PG_GETARG_VARCHAR_P(0));
  table_orig_pkey = __table_log_varcharout((VarChar *)PG_GETARG_VARCHAR_P(1));
  table_log = __table_log_varcharout((VarChar *)PG_GETARG_VARCHAR_P(2));
  table_log_pkey = __table_log_varcharout((VarChar *)PG_GETARG_VARCHAR_P(3));
  table_restore = __table_log_varcharout((VarChar *)PG_GETARG_VARCHAR_P(4));

  /* pkey of original table cannot be the same as of log table */
  if (strcmp((const char *)table_orig_pkey, (const char *)table_log_pkey) == 0) {
    elog(ERROR, "pkey of logging table cannot be the pkey of the original table: %s <-> %s", table_orig_pkey, table_log_pkey);
  }

  /* Connect to SPI manager */
  ret = SPI_connect();
  if (ret != SPI_OK_CONNECT) {
    elog(ERROR, "table_log_restore_table: SPI_connect returned %d", ret);
  }

  /* check original table */
  snprintf(query, 249, "SELECT a.attname FROM pg_class c, pg_attribute a WHERE c.relname = %s AND a.attnum > 0 AND a.attrelid = c.oid ORDER BY a.attnum", do_quote_literal(table_orig));
#ifdef TABLE_LOG_DEBUG_QUERY
  elog(NOTICE, "query: %s", query);
#endif /* TABLE_LOG_DEBUG_QUERY */
  ret = SPI_exec(query, 0);
  if (ret != SPI_OK_SELECT) {
    elog(ERROR, "could not check relation: %s", table_orig);
  }
  if (SPI_processed > 0) {
    table_orig_columns = SPI_processed;
  } else {
    elog(ERROR, "could not check relation: %s", table_orig);
  }
  /* check pkey in original table */
  snprintf(query, 249, "SELECT a.attname FROM pg_class c, pg_attribute a WHERE c.relname=%s AND c.relkind='r' AND a.attname=%s AND a.attnum > 0 AND a.attrelid = c.oid", do_quote_literal(table_orig), do_quote_literal(table_orig_pkey));
#ifdef TABLE_LOG_DEBUG_QUERY
  elog(NOTICE, "query: %s", query);
#endif /* TABLE_LOG_DEBUG_QUERY */
  ret = SPI_exec(query, 0);
  if (ret != SPI_OK_SELECT) {
    elog(ERROR, "could not check relation: %s", table_orig);
  }
  if (SPI_processed == 0) {
    elog(ERROR, "could not check relation: %s", table_orig);
  }
#ifdef TABLE_LOG_DEBUG
  elog(NOTICE, "original table: OK (%i columns)", table_orig_columns);
#endif /* TABLE_LOG_DEBUG */

  /* check log table */
  snprintf(query, 249, "SELECT a.attname FROM pg_class c, pg_attribute a WHERE c.relname = %s AND a.attnum > 0 AND a.attrelid = c.oid ORDER BY a.attnum", do_quote_literal(table_log));
#ifdef TABLE_LOG_DEBUG_QUERY
  elog(NOTICE, "query: %s", query);
#endif /* TABLE_LOG_DEBUG_QUERY */
  ret = SPI_exec(query, 0);
  if (ret != SPI_OK_SELECT) {
    elog(ERROR, "could not check relation [1]: %s", table_log);
  }
  if (SPI_processed > 0) {
    table_log_columns = SPI_processed;
  } else {
    elog(ERROR, "could not check relation [2]: %s", table_log);
  }
  /* check pkey in log table */
  snprintf(query, 249, "SELECT a.attname FROM pg_class c, pg_attribute a WHERE c.relname=%s AND c.relkind='r' AND a.attname=%s AND a.attnum > 0 AND a.attrelid = c.oid", do_quote_literal(table_log), do_quote_literal(table_log_pkey));
#ifdef TABLE_LOG_DEBUG_QUERY
  elog(NOTICE, "query: %s", query);
#endif /* TABLE_LOG_DEBUG_QUERY */
  ret = SPI_exec(query, 0);
  if (ret != SPI_OK_SELECT) {
    elog(ERROR, "could not check relation [3]: %s", table_log);
  }
  if (SPI_processed == 0) {
    elog(ERROR, "could not check relation [4]: %s", table_log);
  }
#ifdef TABLE_LOG_DEBUG
  elog(NOTICE, "log table: OK (%i columns)", table_log_columns);
#endif /* TABLE_LOG_DEBUG */

  /* check restore table */
  snprintf(query, 249, "SELECT pg_attribute.attname AS a FROM pg_class, pg_attribute WHERE pg_class.relname=%s AND pg_attribute.attnum > 0 AND pg_attribute.attrelid=pg_class.oid", do_quote_literal(table_restore));
#ifdef TABLE_LOG_DEBUG_QUERY
  elog(NOTICE, "query: %s", query);
#endif /* TABLE_LOG_DEBUG_QUERY */
  ret = SPI_exec(query, 0);
  if (ret != SPI_OK_SELECT) {
    elog(ERROR, "could not check relation: %s", table_restore);
  }
  if (SPI_processed > 0) {
    elog(ERROR, "restore table already exists: %s", table_restore);
  }
#ifdef TABLE_LOG_DEBUG
  elog(NOTICE, "restore table: OK (doesnt exists)");
#endif /* TABLE_LOG_DEBUG */

  /* now get all columns from original table */
  snprintf(query, 249, "SELECT a.attname, format_type(a.atttypid, a.atttypmod), a.attnum FROM pg_class c, pg_attribute a WHERE c.relname = %s AND a.attnum > 0 AND a.attrelid = c.oid ORDER BY a.attnum", do_quote_literal(table_orig));
#ifdef TABLE_LOG_DEBUG_QUERY
  elog(NOTICE, "query: %s", query);
#endif /* TABLE_LOG_DEBUG_QUERY */
  ret = SPI_exec(query, 0);
  if (ret != SPI_OK_SELECT) {
    elog(ERROR, "could not get columns from relation: %s", table_orig);
  }
  if (SPI_processed == 0) {
    elog(ERROR, "could not check relation: %s", table_orig);
  }
  results = SPI_processed;
  /* store number columns for later */
  number_columns = SPI_processed;
#ifdef TABLE_LOG_DEBUG
  elog(NOTICE, "number columns: %i", results);
#endif /* TABLE_LOG_DEBUG */
  for (i = 0; i < results; i++) {
    /* the column name */
    tmp = SPI_getvalue(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 1);
    col_query_size += strlen(do_quote_ident(tmp)) + 2;
    /* now check, if this is the pkey */
    if (strcmp((const char *)tmp, (const char *)table_orig_pkey) == 0) {
      /* remember the (real) number */
      col_pkey = i + 1;
    }
  }
  /* check if we have found the pkey */
  if (col_pkey == 0) {
    elog(ERROR, "cannot find pkey (%s) in table %s", table_orig_pkey, table_orig);
  }
  /* allocate memory for string */
  col_query_size += 10;
  col_query_start = (char *) palloc((col_query_size + 1) * sizeof(char));
  col_query = col_query_start;
  for (i = 0; i < results; i++) {
    if (i > 0) {
      sprintf(col_query, ", ");
      col_query = col_query_start + strlen(col_query_start);
    }
    sprintf(col_query, "%s", do_quote_ident(SPI_getvalue(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 1)));
    col_query = col_query_start + strlen(col_query_start);
  }
#ifdef TABLE_LOG_DEBUG
  elog(NOTICE, "string for columns: %s", col_query_start);
#endif /* TABLE_LOG_DEBUG */

  /* create restore table */
#ifdef TABLE_LOG_DEBUG
  elog(NOTICE, "create restore table: %s", table_restore);
#endif /* TABLE_LOG_DEBUG */

  snprintf(query, 249, "SELECT * INTO ");
  /* per default create a temporary table */
  if (not_temporarly == 0) {
    strcat(query, "TEMPORARY ");
  }
  strcat(query, "TABLE ");
  strncat(query, table_restore, 249);
  /* from which table? */
  strncat(query, " FROM ", 249);
  strncat(query, table_orig, 249);
  if (need_search_pkey == 1) {
    /* only extract a specific key */
    strncat(query, " WHERE ", 249);
    strncat(query, do_quote_ident(table_orig_pkey), 249);
    strncat(query, "=", 249);
    strncat(query, do_quote_literal(search_pkey), 249);
  }
  if (method == 0) {
    /* restore from begin (blank table) */
    strncat(query, " LIMIT 0", 249);
  }
#ifdef TABLE_LOG_DEBUG_QUERY
  elog(NOTICE, "query: %s", query);
#endif /* TABLE_LOG_DEBUG_QUERY */
  ret = SPI_exec(query, 0);
  if (ret != SPI_OK_SELINTO) {
    elog(ERROR, "could not check relation: %s", table_restore);
  }
  if (method == 1) {
#ifdef TABLE_LOG_DEBUG
    elog(NOTICE, "%i rows copied", SPI_processed);
#endif /* TABLE_LOG_DEBUG */
  }

  /* get timestamp as string */
  timestamp_string = DatumGetCString(DirectFunctionCall1(timestamptz_out, timestamp));

#ifdef TABLE_LOG_DEBUG
  if (method == 0) {
    elog(NOTICE, "need logs from start to timestamp: %s", timestamp_string);
  } else {
    elog(NOTICE, "need logs from end to timestamp: %s", timestamp_string);
  }
#endif /* TABLE_LOG_DEBUG */

  /* now build query for getting logs */
#ifdef TABLE_LOG_DEBUG
  elog(NOTICE, "build query for getting logs");
#endif /* TABLE_LOG_DEBUG */

  d_query_size += d_query_size + strlen(col_query_start);
  if (need_search_pkey == 1) {
    /* add size of pkey and size of value */
    d_query_size += strlen(do_quote_ident(table_orig_pkey)) * 2 + strlen(do_quote_literal(search_pkey)) + 3;
  }

  /* allocate memory for string */
  d_query_size += 10;
  d_query_start = (char *) palloc((d_query_size + 1) * sizeof(char));
  d_query = d_query_start;

  snprintf(d_query, d_query_size, "SELECT %s, trigger_mode, trigger_tuple, trigger_changed FROM %s WHERE ", col_query_start, do_quote_ident(table_log));
  d_query = d_query_start + strlen(d_query_start);
  if (method == 0) {
    /* from start to timestamp */
    snprintf(d_query, d_query_size, "trigger_changed <= %s ", do_quote_literal(timestamp_string));
  } else {
    /* from now() backwards to timestamp */
    snprintf(d_query, d_query_size, "trigger_changed >= %s ", do_quote_literal(timestamp_string));
  }
  d_query = d_query_start + strlen(d_query_start);
  if (need_search_pkey == 1) {
    snprintf(d_query, d_query_size, "AND %s = %s ", do_quote_ident(table_orig_pkey), do_quote_literal(search_pkey));
    d_query = d_query_start + strlen(d_query_start);
  }
  if (method == 0) {
    snprintf(d_query, d_query_size, "ORDER BY %s ASC", do_quote_ident(table_log_pkey));
  } else {
    snprintf(d_query, d_query_size, "ORDER BY %s DESC", do_quote_ident(table_log_pkey));
  }
  d_query = d_query_start + strlen(d_query_start);
#ifdef TABLE_LOG_DEBUG_QUERY
  elog(NOTICE, "query: %s", d_query_start);
#endif /* TABLE_LOG_DEBUG_QUERY */
  ret = SPI_exec(d_query_start, 0);
  if (ret != SPI_OK_SELECT) {
    elog(ERROR, "could not get log data from table: %s", table_log);
  }
#ifdef TABLE_LOG_DEBUG
  elog(NOTICE, "number log entries to restore: %i", SPI_processed);
#endif /* TABLE_LOG_DEBUG */
  results = SPI_processed;
  /* save results */
  spi_tuptable = SPI_tuptable;

  /* go through all results */
  for (i = 0; i < results; i++) {
    /* get tuple data */
    trigger_mode = SPI_getvalue(spi_tuptable->vals[i], spi_tuptable->tupdesc, number_columns + 1);
    trigger_tuple = SPI_getvalue(spi_tuptable->vals[i], spi_tuptable->tupdesc, number_columns + 2);
    trigger_changed = SPI_getvalue(spi_tuptable->vals[i], spi_tuptable->tupdesc, number_columns + 3);
    /* check for update tuples we doesnt need */
    if (strcmp((const char *)trigger_mode, (const char *)"UPDATE") == 0) {
      if (method == 0 && strcmp((const char *)trigger_tuple, (const char *)"old") == 0) {
        /* we need the old value of the pkey for the update */
        old_pkey_string = SPI_getvalue(spi_tuptable->vals[i], spi_tuptable->tupdesc, col_pkey);
#ifdef TABLE_LOG_DEBUG
        elog(NOTICE, "tuple old pkey: %s", old_pkey_string);
#endif /* TABLE_LOG_DEBUG */
        /* then skip this tuple */
        continue;
      }
      if (method == 1 && strcmp((const char *)trigger_tuple, (const char *)"new") == 0) {
        /* we need the old value of the pkey for the update */
        old_pkey_string = SPI_getvalue(spi_tuptable->vals[i], spi_tuptable->tupdesc, col_pkey);
#ifdef TABLE_LOG_DEBUG
        elog(NOTICE, "tuple: old pkey: %s", old_pkey_string);
#endif /* TABLE_LOG_DEBUG */
        /* then skip this tuple */
        continue;
      }
    }

    if (method == 0) {
      /* roll forward */
#ifdef TABLE_LOG_DEBUG
      elog(NOTICE, "tuple: %s  %s  %s", trigger_mode, trigger_tuple, trigger_changed);
#endif /* TABLE_LOG_DEBUG */
      if (strcmp((const char *)trigger_mode, (const char *)"INSERT") == 0) {
        __table_log_restore_table_insert(spi_tuptable, table_restore, table_orig_pkey, col_query_start, col_pkey, number_columns, i);
      } else if (strcmp((const char *)trigger_mode, (const char *)"UPDATE") == 0) {
        __table_log_restore_table_update(spi_tuptable, table_restore, table_orig_pkey, col_query_start, col_pkey, number_columns, i, old_pkey_string);
      } else if (strcmp((const char *)trigger_mode, (const char *)"DELETE") == 0) {
        __table_log_restore_table_delete(spi_tuptable, table_restore, table_orig_pkey, col_query_start, col_pkey, number_columns, i);
      } else {
        elog(ERROR, "unknown trigger_mode: %s", trigger_mode);
      }
    } else {
      /* roll back */
      char rb_mode[10]; /* reverse the method */
      if (strcmp((const char *)trigger_mode, (const char *)"INSERT") == 0) {
        sprintf(rb_mode, "DELETE");
      } else if (strcmp((const char *)trigger_mode, (const char *)"UPDATE") == 0) {
        sprintf(rb_mode, "UPDATE");
      } else if (strcmp((const char *)trigger_mode, (const char *)"DELETE") == 0) {
        sprintf(rb_mode, "INSERT");
      } else {
        elog(ERROR, "unknown trigger_mode: %s", trigger_mode);
      }
#ifdef TABLE_LOG_DEBUG
      elog(NOTICE, "tuple: %s  %s  %s", rb_mode, trigger_tuple, trigger_changed);
#endif /* TABLE_LOG_DEBUG */
      if (strcmp((const char *)trigger_mode, (const char *)"INSERT") == 0) {
        __table_log_restore_table_delete(spi_tuptable, table_restore, table_orig_pkey, col_query_start, col_pkey, number_columns, i);
      } else if (strcmp((const char *)trigger_mode, (const char *)"UPDATE") == 0) {
        __table_log_restore_table_update(spi_tuptable, table_restore, table_orig_pkey, col_query_start, col_pkey, number_columns, i, old_pkey_string);
      } else if (strcmp((const char *)trigger_mode, (const char *)"DELETE") == 0) {
        __table_log_restore_table_insert(spi_tuptable, table_restore, table_orig_pkey, col_query_start, col_pkey, number_columns, i);
      }
    }
  }

#ifdef TABLE_LOG_DEBUG
  elog(NOTICE, "table_log_restore_table() done, results in: %s", table_restore);
#endif /* TABLE_LOG_DEBUG */

  /* convert string to VarChar for result */
  return_name = DatumGetVarCharP(DirectFunctionCall2(varcharin, CStringGetDatum(table_restore), Int32GetDatum(strlen(table_restore) + VARHDRSZ)));

  /* close SPI connection */
  SPI_finish();
  /* and return the name of the restore table */
  PG_RETURN_VARCHAR_P(return_name);
}
예제 #10
0
Datum *tidyurl(PG_FUNCTION_ARGS)
{
	VarChar *arg;
	VarChar *ret;
	int ret_size;

	char *str;
	char *res;

	char *src, *dst;
	int in, out;
	translation *t;
	int size;

	arg = PG_GETARG_VARCHAR_P(0);

	// Extract string
	size = VARSIZE(arg) - VARHDRSZ;
	str = (char *) palloc(size + 1);
	if (str == NULL)
	{
		ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY),
			errmsg("out of memory")));
        	PG_RETURN_NULL();
	}

	memcpy(str, VARDATA(arg), size);
	str[size] = 0;

	// Allocate result string
	res = (char *) palloc(size + 1);
	if (res == NULL)
	{
		ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY),
			errmsg("out of memory")));
        	PG_RETURN_NULL();
	}

	memset(res, 0, size + 1);
	
	for (in = out = 0, src = str, dst = res; *src;
		src = str + in, dst = res + out)
	{
		// FIXME: Bubble search. fix for performance
		for (t = (translation *) translator; t->tr_from; ++t)
		{
			if (strncmp(src, t->tr_from, strlen(t->tr_from)) == 0)
			{
				src = t->tr_to;
				break;
			}
		}

		// Skip unknown/untranslated utf-8 chars and non printables
		if (*src <= 32 || *src >= 127)
		{
			++in;
			continue;
		}

		// Skip double white spaces: _
		if (out && *(dst - 1) == SPACE_CHAR && *src == SPACE_CHAR)
		{
			++in;
			continue;
		}

		if (t->tr_from)
		{
			in += strlen(t->tr_from);
			out += strlen(t->tr_to);
		}
		else
		{
			++in;
			++out;
		}

		// Make sure theres enough room in result
		if (out >= size)
		{
			res = repalloc(res, size * 2 + 1);
			if (res == NULL)
			{
				ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY),
					errmsg("out of memory")));
				PG_RETURN_NULL();
			}

			memset(res + size, 0, size + 1);

			// Make sure dst points right
			dst = res + strlen(res);
			size *= 2;
		}

		if (t->tr_from)
		{
			strcpy(dst, src);
		}
		else
		{
			*dst = *src;
		}
	}

	// Remove trailing underscores (spaces)
	for (;*dst == SPACE_CHAR; --dst)
	{
		*dst = 0;
	}

	// Lowercase
	/*
	for (dst = res; *dst; ++dst)
	{
		if (isupper(*dst))
		{
			*dst = tolower(*dst);
		}
	}
	*/
	
	// Return result
	ret_size = out + VARHDRSZ;
	ret = (VarChar *) palloc(ret_size);
	if (ret == NULL)
	{
		ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY),
			errmsg("out of memory")));
		PG_RETURN_NULL();
	}

	SET_VARSIZE(ret, ret_size);
	memcpy(VARDATA(ret), res, out);

	pfree(str);
	pfree(res);

	PG_RETURN_VARCHAR_P(ret);
}