summaryrefslogtreecommitdiff
path: root/ext/interbase/php_ibase_udf.c
blob: a05f2c82c0717a2a2537efab78e6e981b3e96a73 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
   +----------------------------------------------------------------------+
   | PHP Version 5                                                        |
   +----------------------------------------------------------------------+
   | Copyright (c) 1997-2004 The PHP Group                                |
   +----------------------------------------------------------------------+
   | This source file is subject to version 3.0 of the PHP license,       |
   | that is bundled with this package in the file LICENSE, and is        |
   | available through the world-wide-web at the following url:           |
   | http://www.php.net/license/3_0.txt.                                  |
   | If you did not receive a copy of the PHP license and are unable to   |
   | obtain it through the world-wide-web, please send a note to          |
   | license@php.net so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+
   | Author: Ard Biesheuvel <a.k.biesheuvel@ewi.tudelft.nl>               |
   +----------------------------------------------------------------------+
 */

/* $Id$ */

/**
* This UDF library adds the ability to call PHP functions from your SQL
* statement. You will have to declare a different external function for 
* each number of parameters you require. Currently, only string arguments
* are supported as both input arguments as well as the result.
* 
* Declare the functions like this:
* 
*     DECLARE EXTERNAL FUNCTION CALL_PHP1
*         CSTRING(xx),CSTRING(xx) RETURNS VARCHAR(4096)
*         ENTRY_POINT 'udf_call_php1' MODULE_NAME 'php_ibase_udf'
* 
*     DECLARE EXTERNAL FUNCTION CALL_PHP2
*         CSTRING(xx),CSTRING(xx),CSTRING(256) RETURNS VARCHAR(4096)
*         ENTRY_POINT 'udf_call_php1' MODULE_NAME 'php_ibase_udf'
* 
*     ... and so on.
* 
* The first input parameter contains the function you want to call. Subsequent
* arguments are passed to the called function. The lengths of the input strings can
* have any value >1. The length of the output is restricted to 4k.
* 
* The declared functions can be called from SQL like:
* 
*     SELECT CALL_PHP1('strtolower',rdb$relation_name) FROM rdb$relations
* 
* THIS UDF WILL ONLY WORK IF YOU ARE RUNNING THE EMBEDDED 'CLASSIC' SERVER
* IN-PROCESS WITH YOUR PHP ENGINE. NETWORK CONNECTIONS TO 'LOCALHOST' ARE 
* NOT SUPPORTED. 
* 
* Compile with:
*     gcc -shared `php-config --includes` `php-config --ldflags` -o php_ibase_udf.so php_ibase_udf.c
* 
* and copy the resulting file to the folder where your database expects to find it.
*/

#include "zend.h"
#include "zend_API.h"

#include "stdarg.h"

#ifdef ZTS
#error This functionality is not available in ZTS mode
#endif

/* VARCHAR result ignores first short, but must not be 0 */
static char result[4096] = { 1, 1 };

static void call_php(char *name, int argc, ...)
{
	zval callback, args[4], *argp[4], return_value;
	va_list va;
	int i;

	INIT_ZVAL(callback);
	ZVAL_STRING(&callback,name,0);

	/* check if the requested function exists */
	if (!zend_is_callable(&callback, 0, NULL)) {
		return;
	}

	va_start(va, argc);

	/* create the argument array */
	for (i = 0; i < argc; ++i) {
		char *arg = va_arg(va, char*);
		
		INIT_ZVAL(args[i]);
		argp[i] = &args[i];
		ZVAL_STRING(argp[i] = &args[i], arg, 0);
	}
	
	/* now call the function */
	if (FAILURE == call_user_function(EG(function_table), NULL,
			&callback, &return_value, argc, argp)) {
		return;
	}

	convert_to_string(&return_value);

	memcpy(&result[2], Z_STRVAL(return_value), Z_STRLEN(return_value)+1);
}

char *udf_call_php1(char *name, char *arg1)
{
	call_php(name, 1, arg1);
	return result;
}

char *udf_call_php2(char *name, char *arg1, char *arg2)
{
	call_php(name, 2, arg1, arg2);
	return result;
}

char *udf_call_php3(char *name, char *arg1, char *arg2, char *arg3)
{
	call_php(name, 3, arg1, arg2, arg3);
	return result;
}

char *udf_call_php4(char *name, char *arg1, char *arg2, char *arg3, char *arg4)
{
	call_php(name, 4, arg1, arg2, arg3, arg4);
	return result;
}