Load an image with a relative path using mysql command line - mysql

I'm using Flyway to start MYSQL script at the start of my spring project but i'm currently having a problem because i want to load an image into my database using a relative path because my project will be on another server and i want to load the file from Flyway.
The problem is that i can't use the LOAD_FILE function from mysql since it only uses a absolute path.
UPDATE table
SET image = LOAD_FILE('/path/to/folder/image.jpg')
WHERE id=1;
I'm currently looking for another way to do it, if you have any advice i would greatly appreciate it

As advised by Jones, i used a Java Based Migration by creating a folder db/migration in my Java folder.
Inside this folder i have a migration with :
public void migrate(final Context context) throws Exception {
Connection con = context.getConnection();
InputStream image = new ClassPathResource("image/image.jpg").getInputStream();
String requestUpdate = "UPDATE table SET image = ? WHERE id=?";
PreparedStatement preparedStatementUpdate = con.prepareStatement(requestUpdate);
preparedStatementUpdate.setBlob(1, image );
preparedStatementUpdate.setString(2, "1");
preparedStatementUpdate.execute();
}

Related

Create a folder if it doesn't exist

Create a folder if it doesn't exist in Magento, I don't want to use mkdir(). Is there any way to do this ? May be core_file_uploader can work out, but its throwing error.
Magento has Varien_Io_File class for quite many filesystem works.
So instead of using PHP's vanilla mkdir() function, you can use the Magento's way:
$io = new Varien_Io_File();
$io->mkdir(your_path_to_dir);
Or you can also check if the directory does not exist right before creating it
$io = new Varien_Io_File();
if (!$io->fileExists(your_path_to_dir, false)) {
$io->mkdir(your_path_to_dir);
}

How to SET LOCKMODE SESSION WHERE LEVEL = MVCC on Ingres connection via SSIS

Can anyone please provide advice on how to enlist in an MVCC session from SSIS?
Reading from an Ingres DB, we have a requirement to enable MVCC and specify the isolation level from within an SSIS 2008 R2 package.
An existing application exists over this database, that DOES NOT use MVCC, and hence it is not appropriate to simply enable MVCC on the existing DBMS. The reason we want our reads to enlist in MVCC is to ensure we do not cause locks and break this existing application (as is currently periodically happening when we do not use MVCC to perform these reads).
DB version is Ingres II 10.0.0 (su9.us5/132)
ADO.NET driver version is Ingres.Client.IngresConnection, Ingres.Client, Version=2.1.0.0 driver,
We have a similar requirement to do so programmatically from within Tibco BusinessWorks, and interactively via eg SQL Squirrel, and meet this need by issuing the following commands via direct SQL execution (via JDBC):
SET LOCKMODE SESSION WHERE LEVEL = MVCC;
SET SESSION ISOLATION LEVEL READ COMMITTED;
In SSIS we can set the session isolation level using the IsolationLevel property of the task/sequence. But I can find no means of issuing the MVCC command directly.
I have attempted to issue the command via an Exceute SQL Task step, but I encounter the following error:
Syntax error on line 1. Last symbol read was: 'SET LOCKMODE'
What I've tried, to no avail:
With or without the terminating ;
Execute step placed within or outside of a sequence
Enabled the DelayValidation property, at both the sequence and step level
Various TransactionOption settings at the sequence and task level (in case they mattered!)
Setting the lockmode via a windows environment variable ING_SET = "SET LOCKMODE SESSION WHERE LEVEL = MVCC". But my testing shows this is not honoured by the ADO.NET driver we're using in SSIS (nor, incidentally, is it honoured by the JDBC driver we use for SQL Squirrel or Tibco). I believe this is probably an ODBC feature.
Issuing the command from within an ADO.NET source step within a dataflow. Same syntax error.
[UPDATE] Had also tried wrapping the SET ... commands in an Ingres procedure, but this resulted in syntax errors suggesting the SET ... command is not valid anywhere within a procedure.
Can anyone please provide advice on how to enlist in an MVCC session from SSIS?
At this stage (I believe) we're constrained to the ADO.NET driver, but if there's no other option that to go with ODBC then so be it.
Answering my own question here.
Two possible approaches were conceived.
1. Use a Script Component (within a Data Flow step)
From within a script component, I was able to issue the SET ... commands directly via ADO.NET.
The problem with this approach was that I wasn't able to retain the connection on which these commands had been run, for subsequent (or parallel, within the same dataflow) ADO.NET source components.
Attempting to work via a specific connection via transactions was no good, because these commands must be issued outside of an ongoing transaction.
So ultimately I had to also issue the source select from within this component, which even then is less than ideal as the subsequent destination insert operation could then not enlist in the same transaction as the source select.
The solution using this approach ended up being:
- Using MVCC, copy the data from a source view, into a temp staging table on the source system.
- Then using a transaction, read from the source staging table into the destination system.
Code looks something like this (NB had to explicitly add a reference to Ingres .NET Data Provider\v2.1\Ingres.Client.dll
/* Microsoft SQL Server Integration Services Script Component
* Write scripts using Microsoft Visual C# 2008.
* ScriptMain is the entry point class of the script.*/
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using Ingres.Client;
using System.Collections.Generic;
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
private bool debug = true;
private IDTSConnectionManager100 cm;
private IngresConnection conn;
public override void AcquireConnections(object Transaction)
{
// The connection manager used here must be configured in the Script Component editor's "Connection Managers" page.
// "Connection" is the (default) strongly typed name for the first connection added.
// In this case, it needs to be a reference to the xxxxx connection manager (by convention it should be "xxxxx_ADONET").
cm = this.Connections.Connection;
conn = (IngresConnection)cm.AcquireConnection(Transaction);
}
public override void PreExecute()
{
debugMessage("PreExecute", "Started");
base.PreExecute();
string viewName = Variables.vViewName;
IngresCommand cmdSetSessionLockMode = conn.CreateCommand();
IngresCommand cmdSetSessionIsolationLevel = conn.CreateCommand();
IngresCommand cmdReaderQuery = conn.CreateCommand();
List<string> sqlCommandStrings = new List<string>();
if (Variables.vUseIngresMVCC)
{
sqlCommandStrings.Add("SET LOCKMODE SESSION WHERE LEVEL = MVCC");
}
sqlCommandStrings.Add("SET SESSION ISOLATION LEVEL READ COMMITTED");
sqlCommandStrings.Add(String.Format("MODIFY {0}_STAGING TO TRUNCATED", viewName));
sqlCommandStrings.Add(String.Format("INSERT INTO {0}_STAGING SELECT * FROM {0}", viewName));
foreach (string sqlCommandString in sqlCommandStrings)
{
debugMessage("PreExecute", "Executing: '{0}'", sqlCommandString);
IngresCommand command = conn.CreateCommand();
command.CommandText = sqlCommandString;
int rowsAffected = command.ExecuteNonQuery();
string rowsAffectedString = rowsAffected >= 0 ? rowsAffected.ToString() : "No";
debugMessage("PreExecute", "Command executed OK, {0} rows affected.", rowsAffectedString);
}
debugMessage("PreExecute", "Finished");
}
public override void CreateNewOutputRows()
{
// SSIS requires that we output at least one row from this source script.
Output0Buffer.AddRow();
Output0Buffer.CompletedOK = true;
}
public override void PostExecute()
{
base.PostExecute();
// NB While it is "best practice" to release the connection here, doing so with an Ingres connection will cause a COM exception.
// This exception kills the SSIS BIDS designer such that you'll be unable to edit this code through that tool.
// Re-enable the following line at your own peril.
//cm.ReleaseConnection(conn);
}
private void debugMessage(string method, string messageFormat, params object[] messageArgs)
{
if (this.debug)
{
string message = string.Format(messageFormat, messageArgs);
string description = string.Format("{0}: {1}", method, message);
bool fireAgain = true;
this.ComponentMetaData.FireInformation(0, this.ComponentMetaData.Name, description, "", 0, ref fireAgain);
}
}
}
Answering my own question here.
Two possible approaches were conceived.
2. Set up a dedicated MVCC-enabled process of the Ingres DBMS over the existing database, and connect via this
This is the approach we're currently pursuing (as it is supported, and ideally transparent). I will update with details once they are known.

Couchbase lite rename database

How can I rename an existing couchbase lite database (I'd like to avoid creating a new db and having to copy the contents over if possible). Is this the same as replicate to a database locally that has the same name?
Since you map your local database to a remote couchbase bucket using the CBLReplication classes, I can't see any reason why renaming the database shouldn't work.
Just make sure you close your CBLDatabase first:
database.close()
And use the NSFileManager to move the database mydb.cblite from within the CBLManager.sharedInstance().directory as you like:
let databaseManager = CBLManager.sharedInstance()
let fileManager = NSFileManager.defaultManager()
let sourceName = "\(database.name).cblite"
let targetName = "my-new-name.cblite"
if let sourcePath = NSURL(databaseManager.directory,isDirectory:true).URLbyAppendingURLComponent(sourceName).path,
let targetPath = NSURL(databaseManager.directory,isDirectory:true).URLbyAppendingURLComponent(targetName).path{
fileManager.moveItemAtPath(sourcePath,atPath: targetPath)
}
And afterwards reopen the connection to the database with the same CBLReplication settings as before:
let database = databaseManager.databaseNamed("my-new-name")
Please keep in mind you might also move the mydb attachments directory first. And after reopening the connection making sure all of your code is using the new reference for querying etc.
PS: The code used here is written from memory, so it may not work copied 1:1 - but you should get the idea.

EntityFramework on MySql changing connection string does not change results data

I'm working with EntityFramework 5.0 and MySql. I have generated model from database, and my application now have to connect on multiple database with same structred data.
So i have to dynamic change connection string based on some info.
I try to change database name even from config section of connection string, and with EntityConnectionStringBuilder, but i had the same result: my new connection is stored correctly, but data returned are of the first database.
From WebConfig:
add name="dbIncassiEntities" connectionString="metadata=res:///DAL.Modelincassi.csdl|res:///DAL.Modelincassi.ssdl|res://*/DAL.Modelincassi.msl;provider=Devart.Data.MySql;provider connection string="user id=root ... database=dbname2"" providerName="System.Data.EntityClient" />
From code:
EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
entityBuilder.Provider = providerName;
entityBuilder.ProviderConnectionString = "user id=...database=dbname2";
entityBuilder.Metadata = #"res://*/DAL.Modelincassi.csdl|res://*/DAL.Modelincassi.ssdl|res://*/DAL.Modelincassi.msl";
var context = new dbIncassiEntities(entityBuilder.ToString());
My constructor:
public dbIncassiEntities(string conn)
: base(conn)
{
}
What am i missing?
UPDATE
I can see that calling a query directly from SqlQuery, results returned are correct,
while using the generated entities i retrieve wrong data.
var test = context.Database.SqlQuery<string>(
"SELECT cognomenome FROM addetto limit 0,1").ToList();
But calling..
var oAddetto = from c in context.addettoes select c;
So my problem is only on the model itsself, and manually changing the generated schema
<EntitySet Name="addetto" EntityType="dbIncassiModel.Store.addetto" store:Type="Tables" Schema="dbname2" />
..i'll get the right information.
My question now is: how can i change in code these informations??
Any help is really appreciated!!
Thanks, David
Ok, i've found a workaround for now.
I simply clear the shema name on the designer, and now i can call the generated entities succesfully. Hope this can help anyone else.
David
While I could not remove the Schema in the designer, I removed it directly in the .edmx file. Do a full text search for Schema="YourSchema" in an XML editor of your choice and remove the entries. After that, changing the connection string is enough.
Downside is, the Visual Studio designer and mapping explorer won't work properly anymore.
This seems to be more of a dotConnect issue rather than MySQL, since the problem also exists for the Oracle adapter:
http://forums.devart.com/viewtopic.php?t=17427

Upload image directly through mySQL Command Line

I have a certain table in mySQL which has a field called "image" with a datatype of "BLOB". I was wondering if it is possible to upload an image in that field directly from the Command Line Client rather than doing it through php...If it is possible, then where exactly should I place my image files?
Try using the LOAD_FILE() function.
UPDATE `certain_table`
SET image = LOAD_FILE('/full/path/to/new/image.jpg')
WHERE id = 1234;
See the manual for requirements about the path to the filename, privileges, etc.
LOAD_FILE works only with certain privileges and if the file is on the server. I've found out a way to make it work completely client side:
mysql -e "update mytable set image=FROM_BASE64('`base64 -i image.png`')" DBNAME
The idea is to encode the image to base64 on the fly and let then MySql decode it.
This is a variation on Teudimundo's answer that works with older MySQL versions, where Base64 functions are not available:
mysql -e "update mytable set col = x'$(xxd -p image.png | tr -d \\n)' where ..."
The trick is to use xxd -p to convert a binary file to a plain hexdump:
$ xxd -p /usr/share/font-manager/data/blank.png
89504e470d0a1a0a0000000d4948445200000040000000400806000000aa
6971de000000274944415478daedc1010d000000c220fba77e0e37600000
00000000000000000000000000c0bd0040400001ee1dbb2f000000004945
4e44ae426082
then using tr -d \\n to remove the newlines, and finally embedding the result into a MySQL-specific hexdump string literal: x'...'
I recommend you to never upload images directly in a database, it's quite inefficient. It's better to simply store the location and name of the image and store those images in a folder somewhere.
and if you want to "upload" via the commandline, you can just do an:
insert into table(image_loc) values('/images/random/cool.jpg') where id=1;
and depending on your environment you can use shell access to move images around. I'm not quite sure what you are trying to do with these images or how your system is setup. You'll probably need to clarify on that.
It is more preferable to build a sample application and then insert the values in the database. For instance this method could be used to enter a BLOB datatype into the database...
[WebMethod]
public string sendDataToMySql(string get_name, byte[] buffer)
{
string MyConString = "SERVER=localhost;" +
"DATABASE=test;" +
"UID=root;" +
"PASSWORD=admin;";
MySqlConnection connection = new MySqlConnection(MyConString);
connection.Open();
MySqlCommand command = new MySqlCommand("", connection);
command.CommandText = "insert into testImage(name, image) values(#name, #image);";
MySqlParameter oParam1 = command.Parameters.Add("#name", MySqlDbType.VarChar, 50);
oParam1.Value = get_name;
MySqlParameter oParam2 = command.Parameters.Add("#image", MySqlDbType.Blob);
oParam2.Value = buffer;
command.ExecuteNonQuery();
connection.Close();
return "Data was inserted successfully!";
}
Sometimes we try to upload file using loadfile but file is not loaded or file path in formatted text is stored in BLOB field. This is because of access issues. If you are facing such condition, instead of loading file from any location, try to load it from data path of mysql preferably like :
INSERT INTO `srms`.`images` (`ID`, `Image`) VALUES ('5', load_file('C:\ProgramData\MySQL\MySQL Server 5.7\Uploads\test.jpg'));