I think I'm missing something important here.When the plugin's shared library gets loaded, one way or the other, it should construct the function-pointer struct and then pass it to a function defined by plpgsql (this lets us hide/postpone the decision about whether there can be more than one active plugin).But there's a timing issue there. If you ask the plugin to call a call-handler function, then you can't load the plugin at backend startup because the PL/pgSQL call-handler isn't loaded until it's required. Since both the plugin and the call-handler are dynamically loaded, I think one of them has to load the other.Right, but if you set up the mechanism such that each individual PL is responsible for loading plugins, then we'll have to duplicate all that code each time we instrument another PL. I want to do as much as possible of the work in the core code so that we don't end up with duplicate code to maintain. At minimum, you need a way to identify a plugin (or a list of plugins), and, if we generalize the mechanism, a way to identify the language that that plugin is associated with (like, this profiler works with PL/tcl, this debugger works with PL/Java, ...). Once you have that, you've got two choices: 1) The plugin loads the language or 2) The language loads the plugin You are suggesting option 1. That means that we must: a) come up with a way to identify the set of plugins desired (probably some GUC variables?) On the other hand, if the language loads the plugin, we must: a) come up with a way to identify the set of plugins desired (probably some GUC variables?) In either case, the loader code in the language-handlers and the loader code in the plugins could be simple calls to common functions that are defined in the core, avoiding a lot of duplicate code. For example, each language handler (in it's initialization code) could include a call such as: pl_load_plugins( "pl/pgsql", &functionPointers ); or pl_load_plugins( "pl/java", &functionPointers ); pl_load_plugins() would reside in the core, it would find the list of plugins, load each one, find the plugin's initialization function, and call that function with &functionPointers (the initializer would fill in the functionPointers structure). So what am I missing? What's the advantage to having the plugin load the language? That's what I was thinking too. But we could avoid hard-coded names using a syntax similar to preload_libraries (each entry in preload_libraries can contain the name of an optional initialization function). If you specify libraryName:functionName, we would assume that functionName was the loader function, if you just specify libraryName, we could look for a hard-coded default.To do it without a pg_language column, we'd need code in each plugin to identify the language shared library (by looking in pg_language), force loading of same (using existing fmgr code), and look up and call a plugin receptor function given an expected C-code name for it (again, most of this already exists in fmgr). It's not a huge amount of code, probably, but again duplicating it in each plugin seems unappealing. I suppose we could make fmgr export a general function to find a plugin receptor function given the PL name and the expected C symbol. (Oh, and any more comments on security? Is it enough to require that all plugins live in $libdir?) -- Korry |
- Re: [HACKERS] Loading the PL/pgSQL debugger (and other plugi... korry
- Re: [HACKERS] Loading the PL/pgSQL debugger (and other ... Hiroshi Saito
- Re: [HACKERS] Loading the PL/pgSQL debugger (and other ... Tom Lane
- Re: [HACKERS] Loading the PL/pgSQL debugger (and ot... korry
- Re: [HACKERS] Loading the PL/pgSQL debugger (and other ... Jim C. Nasby