Why does Doctrine generate different constraint names? - php

I am using Symfony2 with Doctrine to generate my MySQL tables. Usually, Doctrine is able to update the database quite easily.
The MySQL server is on a linux machine. There is also an Apache running which hosts my Symfony application. When running php app/console doctrine:schema:update --dump-sql on the Linux machine Doctrine tells me that my database is up to date.
However, when running this command on Windows on the exact same Symfony application and connecting to the MySQL server on the Windows machine, Doctrine wants to change quite a few of the constraint names. It seems that it wants to rename all the indices:
DROP INDEX idx_2d91b64f56629d6d ON table1;
CREATE INDEX IDX_13241BA356629D6D ON table1 (col1_id);
DROP INDEX idx_2d91b64fbad26311 ON table1;
CREATE INDEX IDX_13241BA3BAD26311 ON table1 (col2_id);
DROP INDEX idx_bc100bf27dc308 ON table2;
CREATE INDEX IDX_8C245317DC308 ON table2 (col3_id);
// some more similar lines omitted
Why does this happen? I had a look at how Symfony generates the constraint names and it is using dechex and crc32, both of which should be platform-independent.

This may not be the cause, but it does look like a possible cause:
http://php.net/manual/en/function.crc32.php
In the red section, it states that crc32 can return negative or positive values depending on 32 or 64 bit systems.
This is because of the range of a 32 signed integer: −2,147,483,648 to 2,147,483,647.
If you take from this that crc32 assumes to work with unsigned bytes, any value it produces over 2,147,483,647 will become negative.
Then dechex will produce a hexadecimal value based on the decimal value, negative or possible.

Related

How to prevent two user get same unique key?

I am creating a system to generate unique keys. It works for now. But, I haven't tested it with many users. Users may click a button and then get his unique number, as simple as that.
But, How to prevent multiple users getting the same unique keys,if they press the button exactly in the same time (even in ms scale)? The button is on client side, so I must do something in the back end.
This is the unique key looks like:
19/XXXXXX-ABC/XYZ
The XXXXXX is auto increment number from 000001 to 999999. I have this code but didn't know if it's reliable enough to handle my issue.
$autoinc = $this->MPenomoran->get_surat($f_nomor)->jumlah_no+1; //count data in table and added 1
$no_1 = date('y')+2;
$no_2 = str_pad($autoinc, 6, '0', STR_PAD_LEFT);
$no_3 = "-ABC/XYZ";
$nomor = $no_1."/".$no_2.$no_3;
$returned_nomor = $nomor;
$success = array ('nomor' => $returned_nomor); //sent unique keys to user's view
It seems like you don't want to come out and tell us what the platform is for this, or what the limitations to that platform are.
The first thing that jumps out is that your format is limited by year, to 999999 total unique keys. Very odd, but presumably you understand that limit, and would need to put in some code to deal with hitting the maximum number.
Approaches
REDIS based
This would be very simple with a REDIS server using the INCR. Since INCR is atomic, you essentially have a solution just by creating a key named for your year + 2, should it not exist, and using INCR on it from there on out.
You would need to utilize some php redis client, and there are a variety of them with strengths and weaknesses to each that I'm not going to go into.
Redis is also great for caching, so if at all possible that is the first thing I would look into.
MySQL Based
There are a few different solutions using mysql. They are involved, so I'll just outline them because I don't want to spend time writing a novel.
Note: You will need to translate these into the appropriate PHP code (mysqli or PDO) where as noted, parameters are passed, transactions started etc.
MySQL - create your own sequence generator
Create a table named "Sequence" with this basic structure:
name varchar(2) PK
nextval unsigned int default 1
engine=InnoDB
The underlying query would be something like this:
BEGIN_TRANS;
SELECT nextval FROM Sequence WHERE name = '$no_1' FOR UPDATE;
UPDATE Sequence SET nextval = nextval + 1;
END_TRANS;
This code emulates a serialized Oracle style sequence. It is safe from a concurrency standpoint, because MySQL will lock the row briefly, then increment it upon completion.
MySQL - Autoincrement on multi-value PK
This comes with some caveats.
It is generally incompatible with replication.
The underlying table must be myisam
name varchar(2) PK
lastval unsigned int AUTO_INCREMENT PK
engine=MyISAM
Your underlying query would be:
INSERT INTO Sequence (name) VALUES ('$no_1')
This depends on mysql supporting a multi-column key where the 2nd column is an AUTO_INCREMENT. It's behavior is such that it acts like a sequence for each unique name.
You would then use the relevant api's built-in approach to getting the mysql LAST_INSERT_ID(). For example with PDO
Other alternatives
You could also use semaphores, files with locking, and all sorts of other ideas to create a sequence generator that would work well in a monolithic (one server for everything) environment. MySQL and Redis would serve a cluster, so those are more robust options from that standpoint.
The important thing is that whatever you do, you test it out using a load tester like siege or Boom to generate multiple requests at your web level.

PostgreSQL database doesn't seem to work with GeoServer

I've downloaded a project from internet, that is supposed to let me draw some polygons, points and so on on the map, then save it on the PostgreSQL database. You can also upload KML files to show already drawn points,polygons, etc - that doesn't work as well.
The project is using PostGis + GeoServer.
The problem is, I don't know how to enable database in it to save the coordinates.
So far I did:
1)Install PostgreSQL
2)Install PostGis
3)Install GeoServer
4)Install WAMP
5)Create database called 'parking'
6) In the 'parking' I've run SQL queries like this :
-- After creating database
CREATE EXTENSION postgis;
-- CREATE SEQUENCE FOR TABLE parking_spaces
CREATE SEQUENCE public.sq_parking_spaces
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
-- TABLE parking_spaces
CREATE TABLE public.parking_spaces
(
id integer NOT NULL DEFAULT nextval('sq_parking_spaces'::regclass),
name character varying(80),
paid boolean,
spaces integer,
geometry geometry(Polygon,3857),
CONSTRAINT parking_spaces_pkey PRIMARY KEY (id)
)
-- CREATE SEQUENCE FOR TABLE parking_meters
CREATE SEQUENCE public.sq_parking_meters
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
-- TABLE parking_meter
CREATE TABLE public.parking_meters
(
id integer NOT NULL DEFAULT nextval('sq_parking_meters'::regclass),
name character varying(80),
geometry geometry(Point,3857),
CONSTRAINT parking_meters_pkey PRIMARY KEY (id)
)
What should be my next goal? How do I check the tables, using PgAdmin?
EDIT:
The question is how to properly connect PostgreSQL database to GeoServer? And how to give GeoServer full write access to layers?
In continuation to the links shared above, here are the generic steps to ensure that the configuration works well:
Make sure that WAMP is installed successfully and is working.
PostgreSQL is installed successfully and that you're able to run the queries using an admin interface.
Create a new user (who doesn't necessarily have to be a superuser):
https://www.postgresql.org/docs/9.1/static/app-createuser.html
GRANTpermissions for SELECT, INSERT, UPDATE and DELETE for this new user on your database: https://www.postgresql.org/docs/9.0/static/sql-grant.html
In the context of this particular problem, add Service Level Security for the application: http://docs.geoserver.org/stable/en/user/security/service.html
Ensure that you have the write access for the Layers. In loose terms, there will have to be one layer in Geoservices per table in the DB: http://docs.geoserver.org/stable/en/user/security/layer.html
Finally, when attempting to invoke WFS calls to the Services, the parameters in your jQuery must be set as described at the following link: https://gis.stackexchange.com/questions/21251/how-to-initialize-a-wfs-layer
Hope that helps.
From your commands above it doesn't appear as if you have added the geometry column to the geometry_columns table - use the AddGeometryColumn statement to do this.
The next thing to try is to work through the GeoServer tutorial on PostGIS.

Symfony 2.8 with Oracle Database - Identifier is too long

I'm trying to configure phpcr_odm with Symfony 2.8 using Oracle database from
this link. When I'm trying to run php app/console doctrine:schema:create my console returns error
[Doctrine\DBAL\Exception\DriverException]
An exception occurred while executing 'CREATE UNIQUE INDEX UNIQ_37E65615460D9FD7413BC13C1AC10DC4E7087E10 ON phpc
r_binarydata (node_id, property_name, workspace_name, idx)':
ORA-00972: identifier is too long
[Doctrine\DBAL\Driver\OCI8\OCI8Exception]
ORA-00972: identifier is too long
I know that Oracle SQL limits unique indexes for 30 chars but I don't know how to limit unique indexes before they are executed in symfony. Can somebody please tell me how to fix this issue ?
Best Regards
If you declare the unique constraint on your entity yourself you can set its name manually:
#ORM\Table(name="phpcr_binarydata", uniqueConstraints={#ORM\UniqueConstraint(name="SMALL_KEY_NAME_HERE", columns={"node_id", "property_name", "workspace_name", "idx"})})
If the database creation is not under your control the maximum identifier length is configured in Doctrine\DBAL\Schema\SchemaConfig::$maxIdentifierLength which you could try to extend and override.
In SQL-92 the later version of the standard appears to optionally allow for 128 character names. Otherwise this would be the solution: https://github.com/doctrine/dbal/blob/master/lib/Doctrine/DBAL/Schema/AbstractAsset.php#L219

How can PDO not return a row which pg_query() does?

I had a table with a bigserial PK, one character varying FK and a bigint FK and a unique constraint on these FKs, a character varying NOT NULL and two nullable smallints.
All of this was running in a VM with Ubuntu 14.04.2 LTS, PHP 5.5.9 and PostgreSQL 9.3 and all other packages from the distribution.
I did
$pdo->query("SELECT * FROM table")->fetchAll(PDO::FETCH_ASSOC)
and
$r = pg_query($db, "SELECT * FROM table");
pg_fetch_all($r)
The latter returned all rows while the former returned all rows except for one.
I tried to select that very row as well, and while the pg_*() functions worked as expected, PDO did not return any row.
To make it even stranger, the discrepancy only emerged in PHP-FPM with lighttpd 1.4.33, but not when run with PHP CLI in a shell.
How can that be?
Did anyone else encounter a similar situation?
And how can I be sure that PDO will not fail me again?
I even tried rebooting the VM and restarted PostgreSQL, but the results did not change.
Sadly, I do not have a backup of this stuff because I had to get things working ASAP, so I deleted that mysterious row and replaced it with a new one, identical in all columns except for the PK.
The new row was returned properly by both.
Turns out, PostgreSQL may yield confusing and inconsistent results when its index gets corrupted.
In this case, just recreate the index and check if it fixes your problem.

PHP mysql bigint issue

I have two tables with bigint:
table1
id bigint(20) PK autoincrement
name varchar(40),
text
table2
id bigint(20) PK autoincrement
created datetime
text_field
id_table1_ref bigint(20)
After inserting data into table1 and trying to insert table1.id into table2.id_table1_ref,
the number is different, i.e.:
Number 1552545662588 from table1.t1 becomes 1552545662, or even worse, a negative number.
I know this is an issue with settings, but I can't figure out how to manage this.
I tried to set up signed/unasigned values for the fields, but it doesn't work.
This is happening on my UNIX local computer, on the server all is working ok, at least for now.
Any help would be much appreciated.
You need to CONVERT it to a string in SQL before getting it into PHP. In PHP, you can use GMP to handle the number.
MySQL docs on converting: http://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#function_convert
It's also the case that PHP under at least some 64-bit operating systems (eg FreeBSD AMD64) uses an 8-byte int, verifiable by testing with
echo 'Size of int is '.PHP_INT_SIZE ;
So if you're only going to be running a 64-bit operating system, you shouldn't need to manage the BIGINTs as strings in PHP.
I solved this problem by change to another php version,that is changing from 64bit php version to 32bit php version. That really works for me.

Categories