Get the SQL for a Doctrine 2 entity insert - doctrine-orm

Is it possible to get the SQL for a Doctrine 2 entity insert?
For example, let's say I have this:
$foo = new Foo();
$foo->setName('bar');
$em->persist($foo);
$em->flush();
Is there a way to get the SQL for the INSERT statement there? If so, how?

You could try the SQL-Logger:
$em->flush(); // to write cached stuff down and isolate the following
// activate logger
$em->getConnection()
->getConfiguration()
->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger());
$foo = new Foo();
$foo->setName('bar');
$em->persist($foo);
$em->flush();
// disable logger
$em->getConnection()
->getConfiguration()
->setSQLLogger(null);
It works with other DBMS than MySQL too. There are also other possibilities to write in files. Look here:
https://www.brunsware.de/blog/symfony/monolog-doctrine-logfile.html
http://vvv.tobiassjosten.net/symfony/logging-doctrine-queries-in-symfony2/

You could activate the query log in your MySQL server (guessing it's it) :
in /etc/mysql/my.ini (usual place) :
[mysqld]
log=/tmp/mysql.log
then read this file where you will find each issued query.

Related

C++ OTL doesn't see external database changes

I have a C++ program that is using OTLv4 to connecto to a database. Everything is working fine. I can both insert data into the database and read data out of the database.
However, if I change data in the database from another program, then this isn't reflected in my C++ program. If I for example remove an entry with MySQL workbench, the C++ program will still see the entry. The data I see is the data as it appeared when the program first logged in to the database.
If I log off and log on each time I do a query then I will get the current value, but that does not seem very efficient. Similarly if I run a query from the C++ program that will modifiy the database then the program will start seeing the current values up until that point.
To me this feels like some sort of over-aggressive caching, but I don't know how that works in OTL, haven't seen any mention of caches other than possibly the stream pooling which I know nothing about.
I'm not doing anything fancy. OTL is compiled with these parameters:
#define OTL_ODBC // Compile OTL 4.0/ODBC
#define OTL_UNICODE // Compile OTL with Unicode
#define OTL_UNICODE_EXCEPTION_AND_RLOGON
#define OTL_UNICODE_STRING_TYPE std::wstring
// The following #define is required with MyODBC 3.51.11 and higher
#define OTL_ODBC_SELECT_STM_EXECUTE_BEFORE_DESCRIBE
The code looks something like this:
otl_connect::otl_initialize(1); // Multithreading
otl_connect database;
database.rlogon(...);
// Make queries with otl_stream and direct_exec
otl_stream stream(50, "select * from ...", database);
database.direct_exec("insert ... into ...", otl_exception::disabled);
database.logoff();
Is there something I have missed, some configuration I need to do? Turn off some sort of cache? Maybe i really do need to login and logoff each time?
I found out what is wrong:
Q. OTL: When I insert a new row into a table in MySQL, I can't SELECT it, what's going on?
If you're using a prepared SELECT statement in an otl_stream, and keep executing / reusing the statement to get new rows, you need to commit (call otl_connect::commit()) after the fetch sequence is exhausted each time. The commit call will let your MySQL Server know that your current read only transaction is finished, and the server can start a new transaction, which will make newly inserted rows to be visible to your SELECT statement. In other words, you need to commit your SELECT statements in order to able to see new rows.
From http://otl.sourceforge.net/otl3_faq.htm
So the problem was that whenever I make a SELECT statement I have to call otl_connect::commit(); or MySQL won't understand that the statement is finished.

Doctrine2 - No Metadata Classes to process

Something is wrong with documentation or me. I do all what documentation says.
When i put in terminal :
$ php vendor/bin/doctrine orm:schema-tool:create
Output is :
No Metadata Classes to process
I read to many posts, and google and try to many examples but nothing.
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/getting-started.html
I think you took the config example from Doctrine2: getting started:
$isDevMode = true;
$config = Setup::createAnnotationMetadataConfiguration([__DIR__."/src"], $isDevMode);
The trick is now that the Setup::createAnnotationMetadataConfiguration method uses a SimpleAnnotationReader by default. You can change this behaviour by changing the fifth parameter to false:
$isDevMode = true;
$config = Setup::createAnnotationMetadataConfiguration([__DIR__."/src"], $isDevMode, null, null, false);
This will force Doctrine to use the not-simple AnnotationReader which can handle your models now!
TL;DR: Make sure the type of metadata you created matches the "create metadata configuration" method you used.
I encountered the same problem while working through the Doctrine "Getting Started" guide. After looking through the Doctrine code a bit I figured out what was going wrong. Basically, the code in the tutorial in the "Obtaining the EntityManager" section is:
$config = Setup::createAnnotationMetadataConfiguration([__DIR__ . "/src"], $isDevMode);
A little further in the tutorial, in the "Starting with the Product" section, it shows us how to set up the metadata, with an example for each of the possible options for this. The tutorial says:
Metadata for entities are configured using a XML, YAML or Docblock Annotations. This Getting Started Guide will show the mappings for all Mapping Drivers. References in the text will be made to the XML mapping.
Because of this statement, I decided to use the XML configuration. Unfortunately, the createAnnotationMetadataConfiguration method in the tutorial code did not seem to be using the XML file I had created. (In hindsight, it seems much more obvious that this method is specifically referring to annotation metadata, not XML metadata!)
After I changed it to createXMLMetadataConfiguration instead, it worked as expected. So it looks like one possible source of this problem is that the "create metadata configuration" method you used may not match the type of metadata you created.
Try clearing the cache:
sudo -u www-data php app/console cache:clear --env=dev
Uncomment the one of the following lines in bootstrap.php:
// or if you prefer yaml or XML
//$config = Setup::createXMLMetadataConfiguration(array(__DIR__."/config/xml"), $isDevMode);
//$config = Setup::createYAMLMetadataConfiguration(array(__DIR__."/config/yaml"), $isDevMode);
Which depends if you created yaml or xml meta config files...
Hope this helps.
Had the same issue with custom Doctrine installation. My solution was to re-set metadata driver:
$config->setMetadataDriverImpl(
new Doctrine\ORM\Mapping\Driver\AnnotationDriver(
new Doctrine\Common\Annotations\CachedReader(
new Doctrine\Common\Annotations\AnnotationReader(),
new Doctrine\Common\Cache\ArrayCache()
),
ENTITY_DIR
)
);
Solution from http://support.skipper18.com/1120/how-use-external-tools-generate-doctrine-getters-and-setters?show=1121#a1121
My scenario was generating entities from existing database
The newDefaultAnnotationDriver adds the namespace and the method comments state the following:
If $useSimpleAnnotationReader is true, the notation #Entity will
work, otherwise, the notation #ORM\Entity will be supported.
I had the same problem when creating a new doctrine config in a new ZF2 module.
problem was caused by
'User\Entity' => 'property_entities'
the user part was from the old entity
'Property\Entity' => 'property_entities'
Changing that fixed the issue
If you're using the XML mapping (using Setup::createXMLMetadataConfiguration()), you might want to pay attention to the following:
That your XML mapping files ends by .dcm.xml, not only by .xml.
That your XML file contains the full entity classname, inclusive of the namespace. For example, for a class Company\Solution\Models\User, you must have the Company.Solution.Models.User.dcm.xml mapping file in your XML path.
In my case, the issue was with the number of asterisk used for the annotation
<?php
namespace Models;
use Doctrine\ORM\Annotation\{Id, Column, GeneratedValue, Entity};
/** // I originally used one asterisk here and kept getting the error in question. Error disappeared after doubling the asterisk as it is in this answer
* #Entity(repositoryClass="Doctrine\ORM\Annotation\Id")
*/
class User {
}
?>
you must add the docstring for example:
<?php
// src/User.php
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="users")
*/
class User
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue
*/
private $id;
/**
* #ORM\Column(type="string")
*/
private $name;
}
Try the following command:
php vendor/bin/doctrine-module orm:schema-tool:create

Addressing to temporary table created through CDatabase::ExecuteSQL

Consider following code and advise, why can I not address the temporary table created in the current session.
CDatabase cdb;
CString csConnectionString = "Dsn=prm2;Driver={INFORMIX 3.34 32 BIT};Host=10.XXX.XXX.XXX;Server=SRVNAME;Service=turbo;Protocol=olsoctcp;Database=DBNAME;Uid=user;Pwd=password";
cdb.OpenEx(csConnectionString, CDatabase::noOdbcDialog);
cdb.ExecuteSQL(CString("Set Isolation to Dirty Read"));
...
CString csStatement1 = "SELECT serno FROM TABLE1 into temp ttt_1;"
CString csStatement2 = "DROP TABLE ttt_1";
cdb.ExecuteSQL(csStatement1); // point1
cdb.ExecuteSQL(csStatement2); // point2
...
cdb.Close();
At point1 everything is fine. At point2 I have:
The specified table (ttt_1) is not in the database. State:S0002,Native:-206,Origin:[Informix][Informix ODBC Driver][Informix]
I tried to specify username as prefix (like user.ttt_1 or "user".ttt_1); I tried to create permanent table within respective statement in csStatement1 and every time it failed at point2. But when I tried to create same temporary table twice within csStatement1 I got the message that the temporary table already exists in session.
Please advise: what is wrong and how can I address created temporary tables.
it is all to do with ODBC autocommit mode. By default ODBC uses the option what is defined during the connection, and according to connectionstrings.com the default settings for Informix is commitretain=false.
You have two options: either set it via the connection string (commitretain=true) or (better option) via the ODBC. For a set of statements where you'd like to retain the temp table activate the manual commit mode via SqlSetConnectAttr, then execute a few statements and then call SqlEndTran. Please note, that in manual mode you do not need to call BEGIN TRANSACTION, as it will start automatically (behaviour similar to Oracle)
Please note that ODBC applications should not use Transact-SQL transaction statements such as BEGIN TRANSACTION, COMMIT TRANSACTION, or ROLLBACK TRANSACTION, but use the ODBC commands.

How to set "IN" values with mysql cpp connector

How does one to set the "IN" value for the following SQL statement :
UPDATE `test` SET `test`.`status` = 'foo' WHERE `test`.`id` IN (?);
Is that possible ? I looked in the headers and couldn't find anything related nor did I find anything in google nor stackoverflow.
Should I use the setBlob method ?
There is nothing in MySQL Connector API to handle such case.
But it shouldn't be mind blowing to work it around with a very simple for loop.
either you loop for each id and update atomically.
for each (id in your collection){
UPDATE `test` SET `test`.`status` = 'foo' WHERE `test`.`id` = (?);
}
or you call a direct statement that you custom-build (also with a for loop)...

How to emulate Edit/Update mechanism of ADO for SQLite in C++?

I have a C++ application that uses ADO to talk to an Oracle database. I'm updating the application to support an offline documents. I've decided to implement SQLite for the local side.
I've implemented a wrapper around the ADO classes that will call the appropriate code. However, ADO's way of adding/editing/deleting rows is a bit difficult to implement for SQLite.
For ADO I'd write something like:
CADODatabase db;
CADORecordset rs( &db );
db.Open( "connection string" );
rs.Open( "select * from table1 where table1key=123" );
if (!rs.IsEOF())
{
int value;
rs.GetFieldValue( "field", value );
if (value == 456)
{
rs.Edit();
rs.SetFieldValue( "field", 456 );
rs.Update();
}
}
rs.Close();
db.Close();
For this simple example I realize that I could have just issued an update, but the real code is considerable more complex.
How would I get calls between the Edit() and Update() to actually update the data? My first thought is to have the Edit() construct a separate query and the Update() actually run it, but I'm not sure what fields will be changed nor what keys from the table to limit an update query to.
" but I'm not sure what fields will be changed nor what keys from the table to limit an update query to."
How about just selecting ROWID with the rest of the fields and then building an update based on that ?