xmldb_field Moodle change column type - php

I'm trying to change the column type from a character varying (10) to that of a date.
I can run it individually like so:
ALTER TABLE "tbl_name" ALTER "col_name" TYPE timestamp USING (col_name ::timestamp);
But after throwing this into the upgrade.php script, it barfs on me and requires the USING clause which I can't seem to get to work. Or if there even is a way...
Here's my upgrade.php script:
$table = new xmldb_table('tbl_name');
$field = new xmldb_field('col_name', XMLDB_TYPE_DATETIME);
if ($dbman->field_exists($table, $field)) {
$dbman->change_field_notnull($table, $field);
}
When logging into the Moodle admin and running the update, I get the following error:
ERROR: column "col_name" cannot be cast automatically to type timestamp without time zone HINT: You might need to specify "USING col_name::timestamp without time zone".
Any ideas?
Thanks!

As noted in the Moodle docs (https://docs.moodle.org/dev/XMLDB_column_types) you should avoid using datetime fields - all timestamps in Moodle are declared as integer(10).
If you're using the XMLDB Editor built into Moodle to generate your database table definitions (and you really should do that), then it does not give the option of using the datetime field type.

Related

PHP Phalcon. Use postgres nextval(sequence) in model

I have a table in Postgres with DDL like this one:
CREATE TABLE robots(
robot_id INTEGER NOT NULL CONSTRAINT robot_id_pkey PRIMARY KEY,
name TEXT
);
I know I can insert a record with following SQL statement:
INSERT INTO robots (robot_id, name) VALUES (nextval('robots_seq'), 'WALL-E');
I need to make CRUD operations in Phalcon for this table. Also I want to use ORM features.
So I do:
$robot = new Robots();
$robot->setRobotId(new \Phalcon\Db\RawValue("nextval('robots_seq')"));
$robot->setName('WALL-E');
$robot->save();
And get the following exception:
Uncaught PDOException: SQLSTATE[22P02]: Invalid text representation:
7 ERROR: invalid input syntax for integer: 'nextval('robots_seq')';
Is there any way to accomplish this ?
To tell Phalcon what is name of your model sequence use function getSequenceName:
public function getSequenceName() {
return 'category_id_seq';
}
Phalcon assumes that your models with serial (auto increment) columns will have a sequence named [table_name]_[column_name]_seq.
In your case, in order to make Phalcon take care of handling auto increment columns you should have a sequence named robots_robot_id_seq instead of robots_seq for the column robot_id (which I'd call just "id", by the way).
This way you do not have to worry about setting the id when creating an object and after saving Phalcon will fill that field automatically for you:
CREATE TABLE robots(
robot_id SERIAL PRIMARY KEY NOT NULL,
name TEXT
);
$robot = new Robots();
$robot->setName('WALL-E');
$robot->save();
$robot->getRobotId(); // Should return last "nextval()" sequence
Hope it helps.

how could I change the type of column in redbeanphp?

I am using the RedBeanPHP, I have a string of numbers, is it possible to store it like the string, not a double type? My example is next, and it doesn't work:
$participant = R::dispense('participants');
$participant->setMeta("participants.number","string");
$participant->number = $number;
R::store($participant);
Redbean check attribute given value to set the right type for the column, I would recommend you to work with freeze option off every time, but, when you need to change something, you just turn it on. I mean, just turn freeze on when you really need to perform some change on you table, for ex:
// the false param will disable db changes
R::setup('dns', 'user', 'pass', false);changes (freeze option)
//...
//... let's imagine you have some code here
//...
R::freeze(false);
$participant = R::dispense('participants');
$participant->number = 'intert any string'; // need to set field to string type
R::store($participant);
R::freeze(true);
$participant->number = '99.99';
R::store($participant);
I know it is not the best thing ever, but you just have to turn it on when you need to change something on DB structure. Essentially, in production environment you should always turn it off
RedBean will automatically try to guess the right column type for the data you provide. However, it will never shrink a column, (for example from TEXT to INTEGER), only widen (for example from INTEGER to TEXT).
If it's important for you that the database column is TEXT during development, you could therefore insert a string and delete it again to "trick" RedBean into making the column type TEXT.
For example, put this code snippet into some type of initialization script:
$participant = R::dispense('participants');
$participant->number = 'not a number';
R::store($participant);
R::trash($participant);
// Column 'participants.number' is now of type TEXT
As I mentioned earlier, RedBean will never shrink the column to INTEGER even if you never insert anything else than number strings again.
On the other hand, if it's not critical to you during development, you could just freeze the database before deploying to production and manually change the column type to TEXT in your database manager.

Insert current time to MySQL table using CDbMigration

How should I use MySQL's FROM UNIXTIME correctly in CDbMigration in Yii 1.x?
I have borrowed solution of converting current time given as timestamp, to MySQL's DateTime field from this answer and when just printing it:
echo 'FROM_UNIXTIME('.$base.')'."\n";
echo 'FROM_UNIXTIME('.$sixDaysLater.')'."\n";
everything seems fine:
FROM_UNIXTIME(1418223600)
FROM_UNIXTIME(1418742000)
But, when I'm trying to use the same technique as a part of my migration:
$this->insert('contents', array
(
'author_id'=>1,
'type'=>5,
'status'=>1,
'category'=>1,
'title'=>'title',
'body'=>'body',
'creation_date'=>'FROM_UNIXTIME('.$base.')',
'modification_date'=>'FROM_UNIXTIME('.$base.')',
'availability_date'=>'FROM_UNIXTIME('.$sixDaysLater.')',
'short'=>'short'
));
This fails -- that is, migration goes fine, but I can see in phpMyAdmin, that related fields for this record has been populated with zeros (0000-00-00 00:00:00), not with the expected value.
What am I missing? Is it, because values in insert are being encoded / escaped?
You can use CDBExpression instead:
new CDbExpression("NOW()");
I mean:
'creation_date'=>new CDbExpression("NOW()")
Or if you want to use FROM UNIXTIME you can do the same.
CDbExpression represents a DB expression that does not need escaping.

Cassandra / PHPCassa: How do I select all composite columns with a UUID1 after a certain time?

I have a column family in cassandra which records all the events emitted by a particular user over a specified time period.
I'm using a composite column consisting of a UUID1 and a UTF8 string. I'd like to select all the columns after a paticular time.
// Code to create the column family.
use phpcassa\SystemManager;
$sys = new SystemManager('127.0.0.1');
$sys->create_column_family($keyspace, 'UserActivity', array(
"comparator_type" => "CompositeType(LexicalUUIDType, UTF8Type)",
"key_validation_class" => "UTF8Type"
));
In the code below I try to read the data. Initially I tried creating an array with just the event type set at the 1 index, however although this seemed to work I got lots of errors in the log. Now, I'm trying to set a timestamp in the past and base a UUID1 on it. No errors - but no data either.
// Code to read data
$activityFam = new ColumnFamily($this->pool, 'UserActivity');
$activityFam->insert_format = ColumnFamily::ARRAY_FORMAT;
$activityFam->return_format = ColumnFamily::ARRAY_FORMAT;
$fiveMinPrev = $this->dateFactory->getDateTime();
$fiveMinPrev->sub(new \DateInterval("PT5M"));
$uuid = \phpcassa\UUID::uuid1(null, $fiveMinPrev->getTimestamp());
// Get the most recent SESSION event from the users activity log.
$slice = new ColumnSlice(array(0 => $uuid, 1=>self::EVENT_SESSION));
$columns = $activityFam->get($someUserId, $slice);
How do I achieve selecting columns from a specified time onwards?
Thanks,
Bah!
I realised this is exactly the correct approach to take however it seems I wasn't using a timestamp generated by my 'DateFactory' (which allows me to freeze and manipulate time during testing) to base the timestamp on when I actually inserted the record.
Thus producing incorrect results!

Incorrect Data Format using Redbean PHP and dates - stored as VARCHAR(255)

I'm connecting to MySQL with Redbean PHP and both date and date_deux come through as varchar(255).
I assume I'm in fluid mode by default. How can I correct the problem?
require('rb.php');
R::setup('my connection info',$username, $password);
$book = R::dispense( 'book' );
$book->title = 'Boost development with RedBeanPHP';
$book->author = 'Charles Xavier';
$book->date = '2010-07-08';
$book->date_deux = '08/07/2010';
$id = R::store($book);
echo $id;
UPDATE:
I guess specifically I'm looking forward to the correct way to do this before version 3.0?
Documentation not clear on what to do prior to version 3.0.
In RedBeanPHP versions older than 3 you can use an optimizer: http://www.redbeanphp.com/extra/optimizer It basically changes columns afterwards if possible.
You have to attach the optimizer yourself as a listener. Because I have seen people struggle with this I removed this system and replaced it for a more native approach. You can now just assign SQL formatted date or date-time values and the column will be created using the right data type. However if the column has already been used to store other data, the column will not change (this is to preserve the data already in the column).

Categories