Yii2: How to set db console migration parameter as array - yii2

I want to migrate my test database using the command migrate/fresh --db=array as stated by the help:
--db: Connection|array|string
the DB connection object or the application component ID of the DB connection to use
when applying migrations. Starting from version 2.0.3, this can also be a configuration array
for creating the object.
but I don't know how to specify an array in the command line.
I have tried the following command:
php yii migrate/fresh --db="dns=sqlite:#app/runtime/test.db"
but I get
Exception 'yii\base\UnknownPropertyException' with message 'Setting unknown property: yii\db\Connection::0'
Having a look at console/Controller/runAction:
if (in_array($name, $options, true)) {
$default = $this->$name;
if (is_array($default)) {
$this->$name = preg_split('/\s*,\s*(?![^()]*\))/', $value);
} elseif ($default !== null) {
settype($value, gettype($default));
$this->$name = $value;
} else {
$this->$name = $value;
}
It looks like $this->db should be initaliced as an array if I want to be able to pass an array from the command line.
However, even if I set it as an array, the preg_split command indexes the configuracion array for the connection by number, not by an string key, so this array can not create a db connection.

You can't configure it from console in this way. This description comes from $db property documentation, which is valid (MigrateController will handle array with configuration or Connection instance), but it is possible to define these formats only from PHP - from console you can pass only string.
If you really need to define connection dynamically from PHP, you can override MigrateController::beforeAction() and parse string in $db and convert it to array with Connection configuration - MigrateController will be able to handle it.

Related

Post input from http request needs to be passed as a variable to AZ module

I have a powershell based http trigger azure function that uses the Az module to call get-azvm. It get's it's data from a logic-app POST. The output looks correct and it's type shows as string but the cmdlet does not like the variable. The function looks like this:
Write-Host "PowerShell HTTP trigger function processed a request."
$sub = $Request.Body.subject | Out-String
write-host "sub:" $sub
$split = $sub -split "[/]"
write-host "split:" $split
$avd = $split[8] | Out-string
Write-Host "avd" $avd
$rgName_avd = 'rg-azgroup'
Get-AzVM -Name $avd -ResourceGroupName $rgName_avd
The post input looks like:
/subscriptions/xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx/resourcegroups/rg-azgroup/providers/Microsoft.Compute/virtualMachines/myvmname-0
The error in the logs starts as:
[Error] ERROR: Unexpected character encountered while parsing value: <. Path '', line 0, position 0.Exception :Type : Newtonsoft.Json.JsonReaderExceptionTargetSite :Name : ParseValueDeclaringType : Newtonsoft.Json.JsonTextReaderMemberType
It feels like it's an issue with the input type but using ConvertFrom-Json does not seem to work. Any ideas what I'm doing wrong? If I hard code the VM name or define a variable locally and use it the command executes.
The AZ module versions being used in requirements.psd1:
#{
'Az.Accounts' = '2.7.6'
'Az.Compute' = '4.26.0'
}
Here are the few workarounds that you can try:
Solution 1:
You might not be passing JSON to DeserializeObject.
It looks like that type of tmpfile from File.WriteAllText(tmpfile,... is string that contain file path. JsonConvert.DeserializeObject takes JSON value rather than the file path, it fails trying to convert something like #"c:\temp\fooo" - which is not JSON.
Solution 2:
Check that is the file containing JSON string has BOM.
Once u remove BOM the problem may get resolved.
Solution 3:
For a Web API action that was binding to a string instead to an object or a JObject when JSON was correct, but the binder tried to obtain a string from the JSON structure and failed.
So, instead of:
[HttpPost("[action]")]
public object Search([FromBody] string data)
Try this:
[HttpPost("[action]")]
public object Search([FromBody] JObject data)
References:
Unexpected character encountered while parsing value
Unexpected character encountered while parsing value ASP.NET Core and Newtonsoft

In Spark JobServer. How to pass a json formated string on the input.string?

Im trying to execute the following curl command to run a job:
curl -k --basic --user 'user:psw' -d 'input.string= {"user":13}' 'https://localhost:8090/jobs?appName=test&classPath=test.ImportCSVFiles&context=import&sync=true'
But I get the following error:
"com.typesafe.config.ConfigException$WrongType: String: 1: input.string has type OBJECT rather than STRING"
My idea is to pass more than one parameter like an sql query. A json format to easy handling on my submitted jar.
I'm on the right way or there is another way?
Copying it from comment.
Issue was json was trying to read it not as string but as object directly because of string starting with braces "{".
Correct input 'input.string= \"{\"user\":13}\" '
input.string is not a reserved keyword -- in fact, you can name the parameters arbitrarily. Let say, you POST two parameterss foo.string and foo.number. You then read the parameters in your SJS job, like this:
// run is the starting point of a SJS job (also see validate function)
override def runJob(sc: SparkContext, config: Config): Any = {
val cmd = config.getString("input.cmd")
val fooString = config.getString("foo.bar")
val fooNum = config.getInt("foo.number")
Just in case you plan to execute SJS jobs from Scala/Java:
Apache Commons Lang (org.apache.commons.lang3) comes with a very helpful class to escape JSON: StringEscapeUtils
I use it to escape inputs from my Scala application that I need to pass to SparkJobServer jobs, like this:
input.schema=\"" + StringEscapeUtils.escapeJson(referenceSchema)+"\""
referenceSchema is a JSON document (in my case a JSON array)
input.schema is then one of many comma-separated parameters in the body of HTTP post from Scala...

Accessing value from mongodb with Scala

After executing a MongoDB query my result is of type : res = Seq[Document]
To access the BsonString I use : res (0).get("n"))
Which returns :
Some(BsonString{value='value'})
How can I access the value value from the BsonString as a String ?
Accessing the value of Some(BsonString{value='value'}) returns BsonString{value='value'} do I need to convert BsonString{value='value'} to a Scala object using a library (for example Jackson) and then access the value ?
I suppose you are using the mongo scala driver (and not ReactiveMongo).
In that case, the returned BsonString is a java object; here is the scaladoc that points to the javadoc.
And you can access the value via the getValue method.
As you are getting back Option objects, I would recommend to use proper for comprehension to avoid runtime exceptions; something like:
val optionalResult = for {
doc <- res.headOption
element <- doc.get[BsonString]("n")
} yield (element.getValue)
optionalResult will be of type Option[String].
You can then check if you have a value and use it; via map, flatMap, foreach or even if (optionalResult.isDefined).

PowerShell changes return object's type

I am using PowerShell v3 and the Windows PowerShell ISE. I have the following function that works fine:
function Get-XmlNode([xml]$XmlDocument, [string]$NodePath, [string]$NamespaceURI = "", [string]$NodeSeparatorCharacter = '.')
{
# If a Namespace URI was not given, use the Xml document's default namespace.
if ([string]::IsNullOrEmpty($NamespaceURI)) { $NamespaceURI = $XmlDocument.DocumentElement.NamespaceURI }
# In order for SelectSingleNode() to actually work, we need to use the fully qualified node path along with an Xml Namespace Manager, so set them up.
[System.Xml.XmlNamespaceManager]$xmlNsManager = New-Object System.Xml.XmlNamespaceManager($XmlDocument.NameTable)
$xmlNsManager.AddNamespace("ns", $NamespaceURI)
[string]$fullyQualifiedNodePath = Get-FullyQualifiedXmlNodePath -NodePath $NodePath -NodeSeparatorCharacter $NodeSeparatorCharacter
# Try and get the node, then return it. Returns $null if the node was not found.
$node = $XmlDocument.SelectSingleNode($fullyQualifiedNodePath, $xmlNsManager)
return $node
}
Now, I will be creating a few similar functions, so I want to break the first 3 lines out into a new function so that I don't have to copy-paste them everywhere, so I have done this:
function Get-XmlNamespaceManager([xml]$XmlDocument, [string]$NamespaceURI = "")
{
# If a Namespace URI was not given, use the Xml document's default namespace.
if ([string]::IsNullOrEmpty($NamespaceURI)) { $NamespaceURI = $XmlDocument.DocumentElement.NamespaceURI }
# In order for SelectSingleNode() to actually work, we need to use the fully qualified node path along with an Xml Namespace Manager, so set them up.
[System.Xml.XmlNamespaceManager]$xmlNsManager = New-Object System.Xml.XmlNamespaceManager($XmlDocument.NameTable)
$xmlNsManager.AddNamespace("ns", $NamespaceURI)
return $xmlNsManager
}
function Get-XmlNode([xml]$XmlDocument, [string]$NodePath, [string]$NamespaceURI = "", [string]$NodeSeparatorCharacter = '.')
{
[System.Xml.XmlNamespaceManager]$xmlNsManager = Get-XmlNamespaceManager -XmlDocument $XmlDocument -NamespaceURI $NamespaceURI
[string]$fullyQualifiedNodePath = Get-FullyQualifiedXmlNodePath -NodePath $NodePath -NodeSeparatorCharacter $NodeSeparatorCharacter
# Try and get the node, then return it. Returns $null if the node was not found.
$node = $XmlDocument.SelectSingleNode($fullyQualifiedNodePath, $xmlNsManager)
return $node
}
The problem is that when "return $xmlNsManager" executes the following error is thrown:
Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.Xml.XmlNamespaceManager".
So even though I have explicitly cast my $xmlNsManager variables to be of type System.Xml.XmlNamespaceManager, when it gets returned from the Get-XmlNamespaceManager function PowerShell is converting it to an Object array.
If I don't explicitly cast the value returned from the Get-XmlNamespaceManager function to System.Xml.XmlNamespaceManager, then the following error is thrown from the .SelectSingleNode() function because the wrong data type is being passed into the function's 2nd parameter.
Cannot find an overload for "SelectSingleNode" and the argument count: "2".
So for some reason PowerShell is not maintaining the data type of the return variable. I would really like to get this working from a function so that I don't have to copy-paste those 3 lines all over the place. Any suggestions are appreciated. Thanks.
What's happening is PowerShell is converting your namespace manager object to a string array.
I think it has to do with PowerShell's nature of "unrolling" collections when sending objects down the pipeline. I think PowerShell will do this for any type implementing IEnumerable (has a GetEnumerator method).
As a work around you can use the comma trick to prevent this behavior and send the object as a whole collection.
function Get-XmlNamespaceManager([xml]$XmlDocument, [string]$NamespaceURI = "")
{
...
$xmlNsManager.AddNamespace("ns", $NamespaceURI)
return ,$xmlNsManager
}
More specifically, what is happening here is that your coding habit of strongly typing $fullyQualifiedModePath is trying to turn the result of the Get (which is a list of objects) into a string.
[string]$foo
will constrain the variable $foo to only be a string, no matter what came back. In this case, your type constraint is what is subtly screwing up the return and making it Object[]
Also, looking at your code, I would personally recommend you use Select-Xml (built into V2 and later), rather than do a lot of hand-coded XML unrolling. You can do namespace queries in Select-Xml with -Namespace #{x="..."}.

Data type conversion issues in Powershell

I'm writing a Powershell script that will extract a set of data files from a ZIP file and will then attach them to a server. I've written a function that takes care of the unzip and since I need to grab all of the files so that I know what I'm attaching I return that from the function:
function Unzip-Files
{
param([string]$zip_path, [string]$zip_filename, [string]$target_path, [string]$filename_pattern)
# Append a \ if the path doesn't already end with one
if (!$zip_path.EndsWith("\")) {$zip_path = $zip_path + "\"}
if (!$target_path.EndsWith("\")) {$target_path = $target_path + "\"}
# We'll need a string collection to return the files that were extracted
$extracted_file_names = New-Object System.Collections.Specialized.StringCollection
# We'll need a Shell Application for some file movement
$shell_application = New-Object -com shell.Application
# Get a handle for the target folder
$target_folder = $shell_application.NameSpace($target_path)
$zip_full_path = $zip_path + $zip_filename
if (Test-Path($zip_full_path))
{
$target_folder = $shell_application.NameSpace($target_path)
$zip_folder = $shell_application.NameSpace($zip_full_path)
foreach ($zipped_file in $zip_folder.Items() | Where {$_.Name -like $filename_pattern})
{
$extracted_file_names.Add($zipped_file.Name) | Out-Null
$target_folder.CopyHere($zipped_file, 16)
}
}
$extracted_file_names
}
I then call another function to actually attach the database (I've removed some code that checks for existence of the database, but that shouldn't affect things here):
function Attach-Database
{
param([object]$server, [string]$database_name, [object]$datafile_names)
$database = $server.Databases[$database_name]
$server.AttachDatabase($database_name, $datafile_names)
$database = $server.Databases[$database_name]
Return $database
}
I keep getting an error though, "Cannot convert argument "1", with value: "System.Object[]", for "AttachDatabase" to type "System.Collections.Specialized.StringCollection"".
I've tried declaring the data types explicitly at various points, but that just changes the location where I get the error (or one similar to it). I've also changed the parameter declaration to use the string collection instead of object with no luck.
I'm starting with a string collection and ultimately want to consume a string collection. I just don't seem to be able to get Powershell to stop trying to convert it to a generic Object at some point.
Any suggestions?
Thanks!
It looks like you should return the names using the comma operator:
...
, $extracted_file_names
}
to avoid "unrolling" the collection to its items and to preserve the original collection object.
There were several questions like this, here is just a couple:
Strange behavior in PowerShell function returning DataSet/DataTable
Loading a serialized DataTable in PowerShell - Gives back array of DataRows not a DataTable
UPDATE:
This similar code works:
Add-Type #'
using System;
using System.Collections.Specialized;
public static class TestClass
{
public static string TestMethod(StringCollection data)
{
string result = "";
foreach (string s in data)
result += s;
return result;
}
}
'#
function Unzip-Files
{
$extracted_file_names = New-Object System.Collections.Specialized.StringCollection
foreach ($zipped_file in 'xxx', 'yyy', 'zzz')
{
$extracted_file_names.Add($zipped_file) | Out-Null
}
, $extracted_file_names
}
function Attach-Database
{
param([object]$datafile_names)
# write the result
Write-Host ([TestClass]::TestMethod($datafile_names))
}
# get the collection
$names = Unzip-Files
# write its type
Write-Host $names.GetType()
# pass it in the function
Attach-Database $names
As expected, its output is:
System.Collections.Specialized.StringCollection
xxxyyyzzz
If I remove the suggested comma, then we get:
System.Object[]
Cannot convert argument "0", with value: "System.Object[]",
for "TestMethod" to type "System.Collections.Specialized.StringCollection"...
The symptoms look the same, so the solution presumably should work, too, if there are no other unwanted conversions/unrolling in the omitted code between Unzip-Files and Attach-Database calls.