Unable to insert UUID into PostgreSQL 13 database using PHP and PDO - php

I am trying to use UUID's in postgres 13. I enabled the extension using the following code:
CREATE EXTENSION plpgsql;
CREATE EXTENSION "uuid-ossp";
Here is the code to create the table in postgres
CREATE TABLE IF NOT EXISTS customers.customers (
customer_id uuid DEFAULT uuid_generate_v4(),
title VARCHAR(10),
first_name VARCHAR(50) NOT NULL,
middle_name VARCHAR(50),
last_name VARCHAR(50) NOT NULL,
gender CHAR(1) NOT NULL,
date_of_birth date,
role_id INTEGER,
created_ts TIMESTAMP DEFAULT current_timestamp,
created_by VARCHAR(50) DEFAULT current_user,
updated_ts TIMESTAMP,
updated_by VARCHAR(50),
deleted_ts TIMESTAMP,
PRIMARY KEY (customer_id)
)
Here is the code I am using to insert the data into the table:
<?php
$uri = "POSTGRESQL_URI";
//$fields = parse_url($uri);
//echo $fields;
// build the DSN including SSL settings
$conn = "pgsql:";
$conn .= "host=" . '10.0.0.199'; //$fields["host"];
$conn .= ";port=" . '5432'; //$fields["port"];;
$conn .= ";dbname=savvywalletdb";
$conn .= ";sslmode=require"; // verify-ca:";
$conn .= ";sslcert=C:/MyData/Personal/Keys/client.crt";
$conn .= ";sslkey=C:/MyData/Personal/Keys/client.key";
$conn .= ";sslrootcert=C:/MyData/Personal/Keys/root.crt"; //ca.pem";
$db = new PDO($conn, "globoblanco", "Ntpxw!js9"); //$fields["user"], $fields["pass"]);
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
//SELECT * FROM pg_stat_ssl WHERE pid = pg_backend_pid()
foreach ($db->query("SELECT * FROM pg_stat_ssl") as $row) {
echo $row->version . PHP_EOL;
print($row->ssl . PHP_EOL);
}
$query = "SELECT uuid_generate_v4() as uuid";
$stmt = $db->prepare($query);
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_OBJ);
echo $result->uuid;
$title = 'Mr';
$first_name = 'Gabriel';
$middle_name = 'S';
$last_name = 'Lobo-Blanco';
$gender = 'M';
$date_of_birth = '10/14/1961';
$query = "INSERT INTO customers.customers (customer_id, title, first_name, middle_name, last_name, gender, date_of_birth) ";
$query .= " VALUES(':customer_id', ':title', ':first_name', ':middle_name', ':last_name', ':gender', ':date_of_birth')";
$stmt = $db->prepare($query);
$stmt->bindValue(':customer_id', $result->uuid, PDO::PARAM_STR);
$stmt->bindValue(':title', $title, PDO::PARAM_STR);
$stmt->bindValue(':first_name', $first_name, PDO::PARAM_STR);
$stmt->bindValue(':middle_name', $middle_name, PDO::PARAM_STR);
$stmt->bindValue(':last_name', $last_name, PDO::PARAM_STR);
$stmt->bindValue(':gender', $gender, PDO::PARAM_STR);
$stmt->bindValue(':date_of_birth', $date_of_birth, PDO::PARAM_STR);
$result = $stmt->execute();
Executing this code produces the following output:
C:\WampServer\3.3.0\www\mysavvywallet (20230116 -> origin)
λ php test_db.php
TLSv1.3
1
TLSv1.3
1
6bbb3a88-4678-4ba3-aed2-4d18502106bb
Fatal error: Uncaught PDOException: SQLSTATE[HY093]: Invalid parameter number: :customer_id in C:\WampServer\3.3.0\www\mysa
vvywallet\test_db.php on line 49
PDOException: SQLSTATE[HY093]: Invalid parameter number: :customer_id in C:\WampServer\3.3.0\www\mysavvywallet\test_db.php
on line 49
Call Stack:
0.0003 425000 1. {main}() C:\WampServer\3.3.0\www\mysavvywallet\test_db.php:0
0.0304 428824 2. PDOStatement->bindValue($param = ':customer_id', $value = '6bbb3a88-4678-4ba3-aed2-4d18502106bb'
, $type = 2) C:\WampServer\3.3.0\www\mysavvywallet\test_db.php:49
The error in this output points to the following statement:
$stmt->bindValue(':customer_id', $result->uuid, PDO::PARAM_STR);
My assumption is that PHP does not support inserting UUID into postgres as I am not able to find a PDO type value I can use to match the table structure. I believe casting the UUID value generated to STRING type does not work because Postgres will check the value provided must match the column type which will cause the error.
I am thinking of a work around using stored procedures to perform the insert, but I was hoping to get a resolution to this issue without having to create that.
I am using PHP 8.2 and PostgreSQL 13.
Any suggestions anyone?
I tried using a PDO::PARAM_STR type to the bindValue() function but it does not seem to work.
The goal is to be able to execute the script and that it will perform a successful insert into the table.

Related

PDO sqlsrv: right trimming on LIKE on char fields

I noticed that if you open a connection with PDO :: SQLSRV_ATTR_ENCODING = PDO :: SQLSRV_ENCODING_UTF8 (default configuration) there is a problem when using LIKE with named parameters on char fields.
No automatic trim of the padding spaces is performed, an operation that is performed in all other cases.
How to reproduce the problem:
Create a table and insert data in it:
CREATE TABLE testDB.dbo.TEST_TABLE (
ID_FIELD int IDENTITY(1,1) NOT NULL,
CHAR_FIELD char(15) COLLATE Latin1_General_CI_AS DEFAULT ' ' NOT NULL
CONSTRAINT TEST_TABLEK00 PRIMARY KEY (ID_FIELD)
);
INSERT INTO TEST_TABLE (CHAR_FIELD) VALUES ('Test data'), ('MyString'), ('My data 123');
Then on PHP I get this results
$options = array();
$pdo = new PDO("sqlsrv:Server=testServer;Database=testDB", 'test', 'test', $options);
$stmt = $pdo->prepare("SELECT * FROM TEST_TABLE WHERE CHAR_FIELD = 'Test data'");
$stmt->execute();
$results = $stmt->fetchAll(); //Returns 1 row
$stmt = $pdo->prepare("SELECT * FROM TEST_TABLE WHERE CHAR_FIELD LIKE 'Test data'");
$stmt->execute();
$results = $stmt->fetchAll(); //Returns 1 row
$stmt = $pdo->prepare("SELECT * FROM TEST_TABLE WHERE CHAR_FIELD = :CHAR_FIELD");
$value = 'Test data';
$stmt->bindParam('CHAR_FIELD', $value, PDO::PARAM_STR);
$stmt->execute();
$results = $stmt->fetchAll(); //Returns 1 row
$stmt = $pdo->prepare("SELECT * FROM TEST_TABLE WHERE CHAR_FIELD LIKE :CHAR_FIELD");
$value = 'Test data';
$stmt->bindParam('CHAR_FIELD', $value, PDO::PARAM_STR);
$stmt->execute();
$results = $stmt->fetchAll(); //Returns 0 rows
$stmt = $pdo->prepare("SELECT * FROM TEST_TABLE WHERE CHAR_FIELD LIKE :CHAR_FIELD");
$value = 'Test data ';
$stmt->bindParam('CHAR_FIELD', $value, PDO::PARAM_STR);
$stmt->execute();
$results = $stmt->fetchAll(); //Returns 1 row
$options = array(PDO::SQLSRV_ATTR_ENCODING => PDO::SQLSRV_ENCODING_SYSTEM);
$pdo = new PDO("sqlsrv:Server=testServer;Database=testDB", 'test', 'test', $options);
$stmt = $pdo->prepare("SELECT * FROM TEST_TABLE WHERE CHAR_FIELD LIKE :CHAR_FIELD");
$value = 'Test data';
$stmt->bindParam('CHAR_FIELD', $value, PDO::PARAM_STR);
$stmt->execute();
$results = $stmt->fetchAll(); //Returns 1 row
The behavior of the like together with the named parameter, when opening the connection to the DB in UTF8, is not uniform with all the other behaviors.
Only in that case is the field not automatically trimmed while in all other cases it is. Personally, it seems to me more of a bug than a deliberate behavior.
I find myself managing a huge application, developed over 10 years and which can interface with different databases (mysql, postgres, oracle and sqlserver).
Changing the queries one by one is impossible, I would need a solution at the configuration level (some flags to set in the PDO or on SqlSever itself) or at least find a way to normalize this behavior to all the others automatically via code.

Error SQLSTATE[HY093]: Invalid parameter number: in php PDO statement

im a newbie in php and im facing this problem...i get with it 3 days and im going mad... ;). Im trying to implement a table with users of a web application. So i have to check that the user doesnt exist.
My sql table:
DROP TABLE users;
CREATE TABLE users (
idUser INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
mail VARCHAR(45) NOT NULL UNIQUE,
name VARCHAR(45) NOT NULL,
password VARCHAR(255) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
role enum ("admin", "user"),
state BOOLEAN,
forgotpass VARCHAR(32) NOT NULL
);
Also this code works ( test if the user already exists in the table):
//$query="SELECT mail FROM proba.users WHERE mail='{$correu}'";
$sql = 'SELECT * FROM users WHERE mail = :mailparam';
//$sql = 'SELECT * FROM users';
$stmt = $con->prepare($sql);
// 2. execute to insert a row
// with an associative array
$stmt->execute(
array(':mailparam'=>$correuFormulari)
);
// 3. get all rows
$rows = $stmt->fetchAll();
foreach ($rows as $rowActual) {
echo $rowActual['mail'] . "<br>";
echo $rowActual['password'] . "<br>";
}
But following the same logic i cant insert an element:
if(count($rows) > 0){
echo "L'usuari ja existeix";
echo "<p><a href='registreUsuari.php'>Torna</a></p>";
} else{
echo "Usuari no trobat. Passem a insertar";
//INSERT INTO users (mail, password, role, name, created_at,forgotpass) VALUES ("p#gmail.com", "pepe","user", "pepito", current_Time,"forgotpass");
$user="admin";
$sqlinsert = 'INSERT INTO users (mail, password, role, name,forgotpass) VALUES (:mail, :passwordform,:usuari, :nomFormulari,:forgotpass)';
//$sql = 'SELECT * FROM users';
$stmtinsertar = $con->prepare($sqlinsert);
// $stmt = $con->prepare("INSERT INTO users (mail, password, role, name, created_at,forgotpass) VALUES (:mail, :password,:user, :nomFormulari, :data,:forgotpass)");
/* $stmtinsertar->bindParam(':mail', $correuFormulari);
$stmtinsertar->bindParam(':password', $passwordFormulari);
$stmtinsertar->bindParam(':user', $user);
$stmtinsertar->bindParam(':nomFormulari', $nomFormulari);
//$stmt->bindParam(':data', $data);
$stmtinsertar->bindParam(':forgotpass', "forgotpass");
INSERT INTO users (mail, password, role, name,forgotpass) VALUES ("hola#g,aoñ", "pepe","user", "pedro","forgot")
*/
try
{
//$stmtinsertar->execute();
$stmt->execute(
array(':mail'=> "$correuFormulari",
':passwordform'=> "$passwordFormulari",
':usuari'=> "$user",
':nomFormulari'=> "$nomFormulari",
':forgotpass'=> "forgotpass")
);
}
catch(PDOException $e)
{
handle_sql_errors($selectQuery, $e->getMessage());
}
echo "S'ha creat l'usuari";
//header('Location: '.'login.php');
// $stmt->close();
}
I enter in the correct if, but i cant insert into the table....
The error shows something like:
pepekjjp#gamil.comConexio : object(PDO)#2 (0) { } hoola0Usuari no trobat. Passem a insertar
SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens
As you can read in the code i also tried to use bind->Params....
Any help would be apreciated.
Also would like to know, which form of executing PDO is preferred, using bindParameter or using an array.
Thanks in advance

Update a field in a sql table with PHP

I have a table in my database that has the fields id, state, number and date.
What I need is to update the state of the record that matches the id that comes as a parameter.
I am doing the following but there is no result:
static public function mdlUpdateField($table, $id){
$stmt = Conection::conect()->prepare("UPDATE $table SET state = :state WHERE id = :id");
$stmt->bindParam(":state", "OK", PDO::PARAM_STR);
if($stmt -> execute()){
return "ok";
}else{
return "error";
}
$stmt -> close();
$stmt = null;
}
When I do it, I get the following error:
Fatal error: Uncaught Error: Cannot pass parameter 2 by reference
$stmt->bindParam(":state", "OK", PDO::PARAM_STR);
$stmt->bindParam(":id", $id, PDO::PARAM_INT);
and for pass the tale name you need dinamic sql
("UPDATE " . $table . " SET state = :state WHERE id = :id");
In this way you are at risk for sqlinjection ..

SQLite query gives an error

I am running PHP PDO 5.6.29. Here is my code:
$QsoId = $SQLiteData["QsoId"];
$SQLiteData["MyAntenna"] = $ODBCAnt;
$query = sprintf("INSERT INTO Log (QsoId, MyAntenna) VALUES (%s, '%s')",$QsoId, $ODBCAnt);
$qry = $SQLite["connection"]->prepare($query);
/* bind params */
$qry -> bindParam(':QsoId', $QsoId, PDO::PARAM_INT);
$qry -> bindParam(':MyAntenna', $ODBCAnt, PDO::PARAM_STR);
$res = $qry->execute();
I get a PDOException with message "SQLSTATE[HY000]:General error: 25 bind or column index out of range"
I am trying to update the MyAntenna field, but I'm using QSOId as a unique record locator. I know ahead of time this record exists and can be found. I don't want to add a new record. There are 138 fields in the record. Am I exceeding some limit?
From what you have said it looks like you're wanting to update existing record not Insert. The error you're geting is probably because the QsoId field is a primary key field that only allows unique ID's (doing an insert with the same ID would mean two rows with same ID)
To do you would do an UPDATE statement, you would do something like below (untested):
$QsoId = $SQLiteData["QsoId"];
$SQLiteData["MyAntenna"] = $ODBCAnt;
$query = "
UPDATE `Log`
SET `MyAntenna` = :MyAntenna
WHERE `QsoId` = :QsoId ");
$qry = $SQLite["connection"]->prepare($query);
/* bind params */
$qry -> bindParam(':QsoId', $QsoId, PDO::PARAM_INT);
$qry -> bindParam(':MyAntenna', $ODBCAnt, PDO::PARAM_STR);
$res = $qry->execute();

store the local time of the client in mysql table

I am trying to store the local time zone of the client on the hosting home page ut I am getting this error in my android Logcat You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 7 How can I do that? I tried it with date_default_timezone_set
I appreaciate any help.
<?php
$data = json_decode ( file_get_contents ( 'php://input', true ) );
$mac = $data->{'mac'};
$latitude = $data->{'latitude'};
$longitude = $data->{'longitude'};
$route = $data->{'route'};
$created_at = date_default_timezone_set("Europe/Berlin");
$con = new mysqli ( "domin.com", "username", "password", "ddatabase" );
// check whether route's table exist.
$results = $con->query ( "SHOW TABLES like 'bus' " ) or die ( mysqli_error () );
if (($results->num_rows) == 1) {$sql = "REPLACE INTO bus(mac, route, latitude, longitude, created_at)
VALUES( ?, ?, ? , ?, ? )";
$stmt = $con->prepare($sql);
if(false === $stmt){
echo "prepare() failed: ";
}
$rc = $stmt->bind_param("sssss",$mac,$route, $latitude,$longitude, $created_at );
echo $rc;
if ( false===$rc ) {
echo "bind_param() failed: ";
}
$rc = $stmt->execute();
if ( false===$rc ) {
echo "execute failed.";
}
$stmt->close();
} else {
$create = "CREATE TABLE bus
(id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
mac VARCHAR(30) NOT NULL UNIQUE,
route int(11) ,
latitude FLOAT(10,6) NOT NULL ,
longitude FLOAT(10,6) NOT NULL,
created_at TIMESTAMP NOT NULL" ;
$stmt = $con->prepare($create) or die ( $con->error );
$stmt->execute();
$stmt->close();
}
date_default_timezone_set returns a bool, not a date. You can use date without specifying a timestamp parameter to get the current client time. Make sure that the format of the date matches what your table expects.

Categories