Get detailed field information for a pgsql resultset in php - php

I have been trying to get the complete meta information for the fields in a result set from Postgresql in php (something like mysql_fetch_field(), which gives a lots of info about the field definition). While I am able to use the following functions to find some information:
$name = pg_field_name($result, 1);
$table = pg_field_table($result, 1);
$type = pg_field_type($result, 1);
I could not find a way to get more details about whether the field allow null values, contains blob data (by field definition), is a primary,unique key by definition etc. The mysql_fetch_field() gives all of this information somehow, which is very useful.
I would really like some way to get that information from php directly, but if that is not possible, then maybe someone has created a routine that might be able to extract that info from a pgsql resultset somehow.
PS: This looks promising, but the warning on the page is not a good sign:
http://php.net/manual/en/pdostatement.getcolumnmeta.php
Also, I am not using PDO at the moment, but if there is no solution, then a PDo specific answer will suffice too.

You can find the metadata on you column with a query like this:
select * from information_schema.columns
where table_name = 'regions' and column_name = 'capital'
This should provide all of the information found in mysql_fetch_field. I'm not a php coder, so perhaps someone knows of a function that wraps this query.

All;
Was amazed to find pgsql does not have a column count routine in PHP. The helps I looked up all got total count from "information_schema.columns", which is not what you want when doing cell by cell processing.
So here is a couple of quick functions to use:
// Test Cell by Cell
echo "Testing Cell by Cell! <br>";
$sql = "SELECT * FROM sometable;
$res = pg_query($sql);
$r_cnt = pg_numrows($res) or die("Error: Row Count Failed!");
$c_cnt = pg_numcols($res) or die("Error: Col Count Failed!");
echo "C=> $c_cnt R=> $r_cnt <br>";
for ($n=1; $n<=$r_cnt; $n++) {
for ($x=1; $x<=$c_cnt; $x++) {
echo "Cell=> pg_result($res,$n,$x) <br>";
} // end while $x
} // end while $n
function pg_numcols($res) {
$spos = strpos(strtoupper($this->db_sql),'SELECT')+6;
$fpos = strpos(strtoupper($this->db_sql),'FROM');
$lenp = $fpos - $spos;
$t_str = substr($this->db_sql,$spos,$lenp);
$x_str = explode(',',trim($t_str));
$result = count($x_str);
return $result;
} // end function
Hope you enjoy!

Related

Query for multiple SQLite tables with PHP

Forgive me if my question sounds stupid as I'm a begginer with SQLite, but I'm looking for the simplest SQLite query PHP solution that will give me full text results from at least three separate SQLite databases.
Google seems to give me links to articles without examples and I have to start from somewhere.
I have three databases:
domains.db (url_table, title_table, date_added_table)
extras.db (same tables as the first db)
admin.db (url_table, admin_notes_table)
Now I need a PHP query script that will execute a query and give me results from domains.db but if there are matches also from extras.db and admin.db.
I'm trying to just grasp the basics of it and looking for a starting point where I can at least study and learn the first code.
First, you connect to 'domains.db', query what you need, save however you want, than if there were a result in the first query, you connect to the others and query them.
$db1 = new SQLite3('domains.db');
$results1 = $db1->query('SELECT bar FROM foo');
if ($results1->numColumns() && $results1->columnType(0) != SQLITE3_NULL) {
// have rows
// so, again, $result2 = $db2->query('query');
// ....
} else {
// zero rows
}
// You can work with the data like this
//while ($row = $results1->fetchArray()) {
// var_dump($row);
//}
Source:
http://php.net/manual/en/sqlite3.query.php
http://php.net/manual/en/class.sqlite3result.php
Edit.: A better approach would be to use PDO, you can find a lot of tutorials and help to use it.
$db = new PDO('sqlite:mydatabase.db');
$result = $db->query('SELECT * FROM MyTable');
foreach ($result as $row) {
echo 'Example content: ' . $row['column1'];
}
You can also check the row count:
$row_count = sqlite_num_rows($result);
Source: http://blog.digitalneurosurgeon.com/?p=947

Blank result for some columns when php mysql_query, works in phpmyadmin

I've run into a problem that is making me go a bit crazy. I have imported some csv data into a table in my phpadmin database and am now using a php script with mysql_query() to run a simple select query on the database and convert the result into json format - e.g. SELECT clients FROM TABLE 29.
Basically, some of the columns in the table result in a json string after passing them through mysql_query() but others simply return a blank. I have fiddled for hours now and can't figure out why this is. The last bit of my code looks like this:
$myquery = "SELECT `clients` FROM `TABLE 29`";
$query = mysql_query($myquery) or die(mysql_error());
if ( ! $query ) {
echo mysql_error();
die;
}
$data = array();
for ($x = 0; $x < mysql_num_rows($query); $x++) {
$data[] = mysql_fetch_assoc($query);
}
echo json_encode($data);
mysql_close($server);
Any help would be greatly appreciated. Could it be something about the data in the table? I'm at a loss.
thank you!
UPDATE: the length of the strings in the column clients seems to be having an effect. When I replace all the text with something shorter (e.g. aaa instead of something like company name 111 - 045 - project name - currency - etc) it works. However, I need it to be able to handle long strings as I want it to just take whatever users happen to import into it... what am I doing wrong?
No, its not about the table, its about how you loop them. Example:
$data = array();
while($row = mysql_fetch_assoc($query)) { // While a row of data exists, put that row in $row as an associative array
$data[] = $row;
}
echo json_encode($data);
mysql_close($server);
exit;
Note: mysql is depreacted and no longer maintained. Use the improved version of the mysql extension which is mysqli or use PDO instead.
After checking all the rows of the data I discovered that the source of the problem was a 'é' - yes, an 'e' with an accent. Once I replaced it with a regular 'e' the problem went away. So much lost time for something so tiny :(

How to get all column names of a row in cassandra using phpcassa?

I want to get all column names of a row in cassandra , how can I do it in phpcassa?
If phpcassa does not support it, does any other language, libs can do it?
In my case, column names are short, but rows are long(around 1000+),data are big(around 100K)
You have a good question. Try something like that:
$pool = new ConnectionPool('feed', array('127.0.0.1'));
$raw = $pool->get();
$rows = $raw->client->execute_cql_query("SELECT * FROM posts", cassandra_Compression::NONE);
var_dump($rows);
Maybe it will help...
Do you mean to get the names directly and only with phpCassa? I don't know any way to do it directly but I used to do that by getting all the row and then executing a foreach loop over the array I have from the column family, like this:
1.- A small function to use everywhere (build your own if you need ;) ):
function f_get_data_as_array($p_pool, $p_cf, $p_key, $p_col_count = 100, $p_column_names = NULL, $p_range_start = '', $p_range_end = '', $p_inverted_sort = false)
{
try{
$lv_slice = new ColumnSlice($p_range_start, $p_range_end, $p_col_count, p_inverted_sort);
$lv_cf = new ColumnFamily($p_pool, $p_cf);
$lv_cf->insert_format = ColumnFamily::ARRAY_FORMAT;
$lv_cf->return_format = ColumnFamily::ARRAY_FORMAT;
$lv_result = $lv_cf->get($p_key, $lv_slice, $p_column_names);
}catch(Exception $lv_e)
{
return false;
}
return $lv_result;
2.- I call it using the first four parameters, setting the pool, the column family name, the key I need and the number of columns I want to get (set the number as you need).
3.- A foreach loop over the returned array to get each column name. Or, if you know the structure you will get from your column family, you just need to use the right indexes, probably: $lv_result[0][0], $lv_result[0][1], and so...
Hope it helps. And sorry for my English!

How to get "field names" using PHP ADOdb?

I'm using PHP ADOdb and I can get the result set:
$result = &$db->Execute($query);
How do I get the field names from that one row and loop through it?
(I'm using access database if that matters.)
It will depend on your fetch mode - if you setFetchMode to ADODB_FETCH_NUM (probably the default) each row contains a flat array of columns. If you setFetchMode to ADODB_FETCH_ASSOC you get an associative array where you can access each value by a key. The following is taken from ADODB documentation - http://phplens.com/lens/adodb/docs-adodb.htm#ex1
$db->SetFetchMode(ADODB_FETCH_NUM);
$rs1 = $db->Execute('select * from table');
$db->SetFetchMode(ADODB_FETCH_ASSOC);
$rs2 = $db->Execute('select * from table');
print_r($rs1->fields); # shows array([0]=>'v0',[1] =>'v1')
print_r($rs2->fields); # shows array(['col1']=>'v0',['col2'] =>'v1')
To loop through a set of results:
$result = &$db->Execute($query);
foreach ($result as $row) {
print_r($row);
}
Small improvement to the solution posted by #thetaiko.
If you are ONLY needing the field names, append LIMIT 1 to the end of your select statement (as shown below). This will tell the server to send you a single row with column names, rather than sending you the entire table.
SELECT * FROM table LIMIT 1;
I'm working with a table that contains 9.1M records, so this minor change speeds up the query significantly!
This is a function I use to return a field array - I've stripped out some extra stuff that, for example, allows it to work with other DBs than MySQL.
function getFieldNames($strTable, $cn) {
$aRet = array();
# Get Field Names:
$lngCountFields = 0;
$strSQL = "SELECT * FROM $strTable LIMIT 1;";
$rs = $cn->Execute($strSQL)
or die("Error in query: \n$strSQL\n" . $cn->ErrorMsg());
if (!$rs->EOF) {
for ($i = 0; $i < $rs->FieldCount(); $i++) {
$fld = $rs->FetchField($i);
$aRet[$lngCountFields] = $fld->name;
$lngCountFields++;
}
}
$rs->Close();
$rs = null;
return $aRet;
}
Edit: just to point out that, as I say, I've stripped out some extra stuff, and the EOF check is therefore no longer necessary in the above, reduced version.
I initally tried to use MetaColumnNames, but it gave differing results in VisualPHPUnit and actual site, while running from the same server, so eventually
I ended up doing something like this:
$sql = "select column_name, column_key, column_default, data_type, table_name, table_schema from information_schema.columns";
$sql .= ' where table_name="'.$table.'" and table_schema="'.$database_name.'"';
$result = $conn->Execute($sql);
while($row = $result->fetchRow()) {
$out[] = strToUpper($row['column_name']);
}
I think it should work with mysql, mssql and postgres.
The benefit of doing it like this, is that you can get the column names, even if a query from a table returns an empty set.
If you need the Coloumn names even for empty tables or for joins about multiple tables use this:
$db->Execute("SELECT .......");
// FieldTypesArray - Reads ColoumnInfo from Result, even for Joins
$colInfo = $res->FieldTypesArray();
$colNames = array();
foreach($colInfo as $info) $colNames[] = $info->name;
The OP is asking for a list of fieldnames that would result of executing an sql statement stored in $query.
Using $result->fetchRow(), even with fetch mode set to associative, will return nothing if no records match the criteria set by $query. The $result->fields array would also be empty and would give no information for getting the fieldnames list.
Actually, we don't know what's inside the $query statement. Besides, setting limit to 1 may not compatible with all database drivers supported by PHP ADOdb.
Answer by Radon8472 is the right one, but the correct code could be:
$result = $db->Execute($query);
// FieldTypesArray - an array of ADOFieldObject Objects
// read from $result, even for empty sets or when
// using * as field list.
$colInfo = [];
if (is_subclass_of($result, 'ADORecordSet')){
foreach ($result->FieldTypesArray() as $info) {
$colInfo[] = $info->name;
}
}
I have the habit of checking the class name of $result, for as PHP ADOdb will return false if execution fails.

how to identify the source table of fields from a mysql query

I have two dynamic tables (tabx and taby) which are created and maintained through a php interface where columns can be added, deleted, renamed etc.
I want to read all columns simulataneously from the two tables like so;-
select * from tabx,taby where ... ;
I want to be able to tell from the result of the query whether each column came from either tabx or taby - is there a way to force mysql to return fully qualified column names e.g. tabx.col1, tabx.col2, taby.coln etc?
In PHP, you can get the field information from the result, like so (stolen from a project I wrote long ago):
/*
Similar to mysql_fetch_assoc(), this function returns an associative array
given a mysql resource, but prepends the table name (or table alias, if
used in the query) to the column name, effectively namespacing the column
names and allowing SELECTS for column names that would otherwise have collided
when building a row's associative array.
*/
function mysql_fetch_assoc_with_table_names($resource) {
// get a numerically indexed row, which includes all fields, even if their names collide
$row = mysql_fetch_row($resource);
if( ! $row)
return $row;
$result = array();
$size = count($row);
for($i = 0; $i < $size; $i++) {
// now fetch the field information
$info = mysql_fetch_field($resource, $i);
$table = $info->table;
$name = $info->name;
// and make an associative array, where the key is $table.$name
$result["$table.$name"] = $row[$i]; // e.g. $result["user.name"] = "Joe Schmoe";
}
return $result;
}
Then you can use it like this:
$resource = mysql_query("SELECT * FROM user JOIN question USING (user_id)");
while($row = mysql_fetch_assoc_with_table_names($resource)) {
echo $row['question.title'] . ' Asked by ' . $row['user.name'] . "\n";
}
So to answer your question directly, the table name data is always sent by MySQL -- It's up to the client to tell you where each column came from. If you really want MySQL to return each column name unambiguously, you will need to modify your queries to do the aliasing explicitly, like #Shabbyrobe suggested.
select * from tabx tx, taby ty where ... ;
Does:
SELECT tabx.*, taby.* FROM tabx, taby WHERE ...
work?
I'm left wondering what you are trying to accomplish. First of all, adding and removing columns from a table is a strange practice; it implies that the schema of your data is changing at run-time.
Furthermore, to query from the two tables at the same time, there should be some kind of relationship between them. Rows in one table should be correlated in some way with rows of the other table. If this is not the case, you're better off doing two separate SELECT queries.
The answer to your question has already been given: SELECT tablename.* to retrieve all the columns from the given table. This may or may not work correctly if there are columns with the same name in both tables; you should look that up in the documentation.
Could you give us more information on the problem you're trying to solve? I think there's a good chance you're going about this the wrong way.
Leaving aside any questions about why you might want to do this, and why you would want to do a cross join here at all, here's the best way I can come up with off the top of my head.
You could try doing an EXPLAIN on each table and build the select statement programatically from the result. Here's a poor example of a script which will give you a dynamically generated field list with aliases. This will increase the number of queries you perform though as each table in the dynamically generated query will cause an EXPLAIN query to be fired (although this could be mitigated with caching fairly easily).
<?php
$pdo = new PDO($dsn, $user, $pass, array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION));
function aliasFields($pdo, $table, $delim='__') {
$fields = array();
// gotta sanitise the table name - can't do it with prepared statement
$table = preg_replace('/[^A-z0-9_]/', "", $table);
foreach ($pdo->query("EXPLAIN `".$table."`") as $row) {
$fields[] = $table.'.'.$row['Field'].' as '.$table.$delim.$row['Field'];
}
return $fields;
}
$fieldAliases = array_merge(aliasFields($pdo, 'artist'), aliasFields($pdo, 'event'));
$query = 'SELECT '.implode(', ', $fieldAliases).' FROM artist, event';
echo $query;
The result is a query that looks like this, with the table and column name separated by two underscores (or whatever delimeter you like, see the third parameter to aliasFields()):
// ABOVE PROGRAM'S OUTPUT (assuming database exists)
SELECT artist__artist_id, artist__event_id, artist__artist_name, event__event_id, event__event_name FROM artist, event
From there, when you iterate over the results, you can just do an explode on each field name with the same delimeter to get the table name and field name.
John Douthat's answer is much better than the above. It would only be useful if the field metadata was not returned by the database, as PDO threatens may be the case with some drivers.
Here is a simple snippet for how to do what John suggetsted using PDO instead of mysql_*():
<?php
$pdo = new PDO($dsn, $user, $pass, array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION));
$query = 'SELECT artist.*, eventartist.* FROM artist, eventartist LIMIT 1';
$stmt = $pdo->prepare($query);
$stmt->execute();
while ($row = $stmt->fetch()) {
foreach ($row as $key=>$value) {
if (is_int($key)) {
$meta = $stmt->getColumnMeta($key);
echo $meta['table'].".".$meta['name']."<br />";
}
}
}

Categories