This post is inspired by handbook article Using schema prefixes with PostgreSQL and #26549: SQL command after database connect , as I was looking for a mean to use a dedicated PostgreSQL schema for storing drupal tables.
It looks like the issue #26549 has been restricted to encoding issues (linked to "How can I change Drupal's character encoding? (UTF-8 and Unicode)",#26990: enable MySQL client side for UTF8, "Problem utf8 mysql 4.1").
IMHO, the feature it suggests would allow to solve gracefully the problem of using Postgres schemas, by just inserting, in settings.php :
$db_prefix = ''; $db_after_connect_sql = "SET search_path TO drupal";
I worked a little on the code to allow more complex SQL scripts, like:
$db_after_connect_sql = <<< EOSQL SET client_encoding="UTF8"; SET search_path TO drupal; UPDATE mytable SET value ='one;two' WHERE id=0; EOSQL;
Here's part of the code I now have in my includes/database.pgsql.inc:
function db_connect($url) { global $db_after_connect_sql; ... if (isset($db_after_connect_sql)) { // commands end with a semi-colon at end-of line $commands = preg_split('/;\s*?' . PHP_EOL . '/' , $db_after_connect_sql); foreach($commands as $sql) { $sql = trim($sql); if (!empty($sql)) pg_query($connection, $sql); } } return $connection; }
I enclose the patches for Drupal 6.9 .
HTH,
Michelle Baert
| Comment | File | Size | Author |
|---|---|---|---|
| mysql.patch | 823 bytes | RockyRoad | |
| pgsql.patch | 1.04 KB | RockyRoad |
Comments
Comment #1
RockyRoad commentedDeclaration for new setting
For this to work, the new
$db_after_connect_sqlvariable has to be set globally.I guess the normal place for this would be just beside
$db-url, inconf_init()(includes/bootstrap.inc line 291) .But it works also by adding the declaration in settings.php, if you prefer leaving core files alone.
Comment #2
RockyRoad commentedComment #3
josh waihi commentedso this is so you can store drupal tables in there own schema? Its up to the database architect to setup the schemas for Drupal and by default Drupal supports this with the use of db_prefix:
The example above would prefix everytable with "drupal." except for users which would be prefixed to "common.". In this example you could have several drupal installs that share a common users table.
Does this solve what you want or have I missed something?
Again with the client encoding, it is up to the Database Architect to ensure the encoding is set right. I believe UTF-8 is the default for PostgreSQL. I do know that checks are in progress to HEAD to make sure encoding is checked at install time for PostgreSQL.
With out more information, this issue seems invalid
Comment #4
RockyRoad commentedHi Josh,
Thanks for reading and answering this post.
Here are some details as you requested.
about $db_prefix and PG schemas
You wrote:
I suggested this feature after reading Using schema prefixes with PostgreSQL, which refers to #40034: Errors when using schemas and updating problem, showing that using
$db_prefixdoesn't work. I also thought it was a cleaner and more generic solution than tweaking$db_prefixdefinition and behavior.Clear namespace separation sounds safer to me, when you consider installing, on the same limited ISP account (most free hosting services allow a single database, with single user), several independent tools using DB access.
Setting current schema in
search_pathensures that no drupal module can accidentally corrupt data in the 'public' (default) namespace, at least as long as it respects the Data Abstraction Layer. For example, are you sure that the curly braces around table names are never missing ?about database encoding
You wrote:
I added the encoding instruction only in an example mini-sql-script, just to reflect the fix to #26549: SQL command after database connect, currently hard-coded in
db_connect(), for both mySQL and pgSQL backends.Wouldn't moving the instruction from core code to
settings.phpbetter separate DBA's responsabilities ?To be more coherent, my patch should include this move, but it's probably better to leave that for a later change, because many users may rely on it. Below, you'll see that it's easier for now to leave default value empty for the new global
$db_after_connect_sql.The patches I submitted don't change anything to settings.php, this is left to the user (site administrator).
BTW, your ISP may not allow you to change encoding at database level.
about genericity
Sorry to go back to that, but issue #26549: SQL command after database connect suggested that the feature could be used, for example to set encoding for newly created tables. The fix released for it addresses only this specific need, by hard-coding a query in db_connect() code.
Similarly, I'm suggesting here another example use for controlling current table namespace (please notice that the title I chose for the issue doesn't mention PG nor schema).
My point is that allowing the site administrator to define custom SQL queries on database connection is likely to help her to solve a wide range of site-specific issues, constraints or needs, without need to ask for a change to Drupal core code.
Complement: about Drupal installation with this feature
When setting up a new drupal installation with this patch applied, you currently need to edit
settings.phpprior to loadinginstall.php, because I didn't provide a new form field in DB configuration form. Just supply$db_urland$db_after_connect_sqlas needed.Of course, this not necessary if you don't need to set
$db_after_connect_sqlbefore drupal database installation. An empty value for it wouldn't change anything.Implementing this new field for full GUI installation should be straightforward.
Related posts
As I use this patch for my own sites (localhost upgraded to 6.10, and ISP newly installed as 6.10), I had no issues related to this patch.
Though, about the particular use case of using PG Schema, I posted details on several places:
Feel free to tell me if there's anything I missed, or if I can help.
Best regards,
Michelle Baert
Comment #5
josh waihi commented@Michelle Baert,
you know that this:
doesn't change the encoding of the database but only the client. I know that PostgreSQL requires this but not sure about MySQL. If such a command isn't in core then I'll back a movement to get it in there.
Core isn't responsible for the contrib code so if someone doesn't use {} around there tables in SQL, then that is considered a bug of the module and should be directed to module in question rather than altering core to compensate for it. That is a trade-off with using contrib modules.
This is a feature request but D6 isn't open for feature implementations. As far as D7 goes - there are steps in this direction at the moment but will still have a lot to cover first. Michelle, I'd encourage you to come help fix a few DB bugs in HEAD to get a better understanding of how the drupal db community works before trying to push this any further just yet as I think there are better and more elegant ways of doing what you're doing here :)
Comment #6
RockyRoad commentedI'm afraid I don't read this answer as very elegant.
Explains nothing, not realistic, off-topic , and condescending.
I spent some time to study, analyse, fix, and share.
Apparently you didn't really read me.
Let me concentrate to my own needs for now.
Best regards.
Michelle
Comment #7
damien tournoud commentedI'm in favor of implementing a 'after_connection_callback' parameter to the $databases array in D7. Should be a simple enough task, and a great jump start in our new database layer.
Comment #8
RockyRoad commentedThanks Damien,
+1 !
I thought of course of a callback or "hook" style implementation would be nice, but for me that's a question of core architecture, which I know is rewritten in D7.
That's beyond my purpose: before discussing *how* and *when*, I preferred talking about *what* and *why* or *why-not*.
The patch I submitted is for D6.9, so I restored the issue version tag. It is intentionally very tiny and respectful of existing code.
Until a stable version of D7 is released, it may interest some users as is.
Of course, I'd love to see the feature integrated in D7, but why not creating a 7x-dev thread for it ?
Best regards,
Michelle
Comment #9
damien tournoud commented@RockyRoad: D6 is feature frozen, so this will not happen. Please help us making this feature in D7 instead!
Comment #10
RockyRoad commentedEven if the patch is never integrated to 6.x HEAD, please leave it available, along with explanations, to 6.x users who are interested to apply the patch themselves, or discuss on their related issues. In this intent, I included links to this page in the related posts I listed above. They all relate to 6.x .
IMHO, restricting support to an unreleased version is not helping users to trust a software.
At the moment, I need to build reliable sites, so I base them on official release,
While interested, I have no time now to explore D7, sorry for that.
I created a D7-dedicated fork of this issue as #398500: Running site-specific SQL commands on database connect, but left it to
you to set this one back to 6.9, if you agreed that it would be more consistent.
Best regards,
Comment #11
damien tournoud commented@RockyRoad: please don't open several copies of the same issue across Drupal versions. If you want your patch to have a chance to be integrated in D6, you'll first have to make it so in D7. Drupal 6 is fully supported, but the issue queue is not the place to maintain unofficial patches.
Comment #12
Crell commentedWhy a callback hook in the $databases array? If there's config to be done for a specific database driver, that can, should, and is done in the driver's constructor already.
Comment #13
damien tournoud commented@Crell: the idea is to be able to run site-specific queries just after connection. All required engine-specific queries are / should already be in the constructor.
Comment #14
josh waihi commentedWhat about a module hook after a database connection is created? Site specific config can be complied into a module like other site specific customizations that aren't theme related
Comment #15
sun.core commentedProper status.
Comment #16
Crell commentedI verified in Paris that it's not difficult to write a custom driver that extends an existing driver, and custom queries can happen there. Since this is so edge casey, I'm happy with that approach. So marking fixed.
If you can argue that it's not edge-casey, reopen with a good argument in Drupal 8. :-)