Multiple "OR" strings in sSearch - sql

This searches my WPDataTable and filters it to only display rows containing 'apple':
function filterGlobalSearch( $tableDescriptionObj, $tableId , $wpDataTablesObj) {
if( $tableId == 1 ){
$tableDescriptionObj->dataTableParams->oSearch = array(
'bSmart' => false,
'bRegex' => false,
'sSearch' => 'apple'
);
}
return $tableDescriptionObj;
}
add_filter('wpdatatables_filter_table_description','filterGlobalSearch', 10, 3);
Please can you tell me how to search for 'apple' OR 'banana'? (to show rows that contain either word).
I've found similar answers on StackExchange and other forums about multiple OR strings (for example here) but can't seem to get them working.
Have already tried:
'apple|banana'
'apple||banana'
'apple'|'banana'
'apple'||'banana'
'apple' OR 'banana'
array('apple', 'banana')
Grateful for any assistance.

I've been provided a working solution that I'll share here:
'bRegex' => false should be changed to true.
'apple|banana' is the search string.

Related

How to delete items from an array in Vue

I have a function called updateAnswer with multiple dynamic parameters.
updateAnswer(key, answer, array = false) {
if (array) {
if(this.answers.contains.find(element => element === answer)) {
//Delete item from array if already element already exists in this.answers.contains array.
} else {
Vue.set(this.answers, key, [...this.answers.contains, answer]);
}
} else {
Vue.set(this.answers, key, answer);
}
},
I'd like to know how delete an item in the array if the value already exists in the array.
You can use method called splice:
Just reference on your array and set values in the brackets the first is referenced on the position, the second is how many datas you want to splice/delete.
The function looks like this:
this.array.splice(value, value)
Lets see on an example - you have array food= [apple, banana, strawberry] than I'm using this.food.splice(1,1)..
my array looks now like this food = [apple, strawberry] - first value in my brackets are the position, the second one is the amount of "numbers" you want to delete.
Hopefully this helps you out!
I suppose each value in this.answers.contains is unique?
Anyways, if you just want to delete the item if already exists, I suggest filter(). It should look like below:
if(this.answers.contains.find(element => element === answer)) {
this.answers.contains = this.answers.contains.filter(c => c !== answer)
}
Also, the if condition if(this.answers.contains.find(element => element === answer)) could also be replaced by if(this.answers.contains.includes(answer))
Hope that could help you.

Am I overwriting computed property filter in Vue?

I am trying to create a reactive filter for an array in Vue. My starting array comes from an API call which returns this.features (geojson features). I am filtering on a nested array. This works -- but when I enter a search term and then backspace back out to an empty string, and enter another string, I am not filtering the original array but appear to be filtering the already-filtered array. How could I filter again on the original array from the API call?
computed property:
filteredFeatures() {
if (this.searchTerm == '') {
return this.features
}
// filter on nested array
let filtered = this.features.filter(feature => {
feature.properties.site_observations = feature.properties.site_observations.filter(
el => JSON.stringify(el).match(this.searchTerm, 'i')
)
return feature.properties.site_observations.length > 0
})
return filtered
}
I have looked at Vue filtering objects property but I cannot make that code work (it uses Object.assign()). Thanks for any ideas.
Your computed property is mutating feature.properties.site_observations, that's a nono. Computed properties should be read only.
filteredFeatures() {
if (this.searchTerm == '') {
return this.features
}
// filter on nested array
let filtered = this.features.filter(feature => {
const site_observations = feature.properties.site_observations.filter(
el => JSON.stringify(el).match(this.searchTerm, 'i')
)
return site_observations.length > 0
})
return filtered
}
It seems here is your problem:
feature.properties.site_observations = feature.properties.site_observations.filter(
el => JSON.stringify(el).match(this.searchTerm, 'i')
)
Because this code filter feature and alter the proprieties of feature.properties.site_observations. Then, in the next read the value is alter. We say that your function it is not pure, because it alter the state of feature.
So, what you should do is:
let anotherVariable = feature.properties.site_observations.filter(
el => JSON.stringify(el).match(this.searchTerm, 'i')
)
Therefore, on a function, avoid alter state of objects, this lead to bugs.
On further checking, the above answer returns all site_observations, not just the ones that match the search. A much better solution is the following, using map to avoid overwriting the data, and the object spread operator to perform an object assign, and drilling down through the nested objects as follows:
filteredFeatures() {
return this.features
.map(feature => ({
...feature,
properties: {
site_observations: feature.properties.site_observations.filter(
element => {
return JSON.stringify(element).match(new RegExp(this.search, 'i'))
}
)
}
}))
.filter(feature => feature.properties.site_observations.length)
}

Laravel DB::update don't working, doing nothing at all, without any errors

I am learning how to run raw SQL queries and stuck at UPDATE operation.
I have route for INSERT:
Route::get('/insert', function (){
DB::insert('insert into posts (title, content) values (?, ?)', ['PHP with Laravel', 'Just testing']);
return 'after insert';
});
And route for SELECT:
Route::get('/read', function (){
$results = DB::select('select * from posts');
return var_dump($results);
});
After SELECT query I see:
/home/pavel/www_mysite/TestLaravel/routes/web.php:31:
array (size=1)
0 =>
object(stdClass)[239]
public 'id' => int 11
public 'title' => string 'PHP with Laravel' (length=16)
public 'content' => string 'Just testing' (length=12)
public 'created_at' => null
public 'updated_at' => null
public 'is_admin' => int 0
And at least UPDATE query:
Route::get('/update', function (){
DB::update('update posts set title = "Nothing here"');
});
After that query the new SELECT query shows the same data and in PHPPgAdmin I found no changes. I installed LaravelDebugBar and may see it at the bottom of the browser at pages for INSERT and SELECT queries, but don't see it at the page for UPDATE query. I cannot realize, where is the mistake.
try to use where clause.
example :
$affected = DB::update('update users set votes = 100 where name = ?', ['John']);
I tested you code too and it work
see this picture
I run your update code on my local environment (laravel 5.2, mysql 5.1). It's updated OK.
How about your log?
After some extra research I found that PostrgreSQL may store case-sensitive names of tables and columns. For that case you need to take their names in double quotes in your query. I think that when PostrgreSQL found double quotes in the query - it "thinks" that it is table/column name. But there is no column with those name.

Perl SQL::Parser table alias substitution: works for SELECT column names but not for WHERE column names

I'm trying to parse some SQL queries stored in a log database -- I don't want to submit them to a SQL database, just to extract the fields used in the SELECT and WHERE clause.
I've been fiddling with several SQL parsers in Java, Python and Perl. The one that seems to work better for my problem are SQL::Parser and SQL::Statement. With those I was able to write the following code:
#!/usr/bin/perl
use strict;
use SQL::Parser;
use SQL::Statement;
use Data::Dumper;
my $sql = "SELECT sl.plate,sp.fehadop FROM sppLines AS sl ".
"JOIN sppParams AS sp ON sl.specobjid = sp.specobjid ".
"WHERE fehadop < -3.5 ";
my $parser = SQL::Parser->new();
my $stmt = SQL::Statement->new($sql,$parser);
printf("COMMAND [%s]\n",$stmt->command);
printf("COLUMNS \n");
my #columns = #{$stmt->column_defs()};
foreach my $column ( #columns)
{
print " ".$column->{value}."\n";
}
printf("TABLES \n");
my #tables = $stmt->tables();
foreach my $table ( #tables)
{
print " ".$table->{name}."\n";
}
printf("WHERE COLUMNS\n");
my $where_hash = $stmt->where_hash();
print Dumper($where_hash);
Sorry if it is too long, it is the smallest, self-contained example I could devise.
The output of this code is:
COMMAND [SELECT]
COLUMNS
spplines.plate
sppparams.fehadop
TABLES
spplines
sppparams
WHERE COLUMNS
$VAR1 = {
'arg1' => {
'value' => 'fehadop',
'type' => 'column',
'fullorg' => 'fehadop'
},
'op' => '<',
'nots' => {},
'arg2' => {
'str' => '-?0?',
'fullorg' => '-3.5',
'name' => 'numeric_exp',
'value' => [
{
'fullorg' => '3.5',
'value' => '3.5',
'type' => 'number'
}
],
'type' => 'function'
},
'neg' => 0
};
The parser returns the name of columns (obtained through a call to $stmt->column_defs()) already renamed with the real tables names (e.g. spplines.plate instead of s1.plate) -- this is what I want.
I also want the names of the columns used in the WHERE clause.
I already know how to recursively parse the results of $stmt->where_hash() (didn't include the code to make the post clear), but even from dumping its contents I can see that the column names are not associated with the tables.
I would like to ensure that the columns names in the WHERE clause are also preceded by the tables name. After parsing the results of $stmt->where_hash() I would get sppparams.fehadop instead of fehadop.
Is this possible with SQL::Parser?
Thanks
(big edit -- tried to make the question clearer)
Since SQL::Statement has an eval_where, I suspect there might be a better way, but you can try a function like this:
get_column($stmt->column_defs(), $where_hash->{arg1});
sub get_column {
my ($columns, $arg) = #_;
return $arg->{fullorg} if ($arg->{type} ne 'column');
foreach my $col (#$columns) {
return $col->{value} if ($col->{fullorg} eq $arg->{fullorg});
my ($name) = ( $col->{fullorg} =~ /([^.]+)$/);
return $col->{value} if ($name eq $arg->{fullorg});
}
return $arg->{fullorg};
}

Searching with CDbCriteria

Is there any way to make a CDbCriteria search (as in compare()) in the fields I'm selecting, but using the model's search() method instead of having to manually add the compare() conditions?
Note that I'm aiming at a solution that will let me write some fewer lines, nothing more and nothing less. So, if the solution is something really hacky and/or mesy, I'll just go for the "add-a-few-compares()" method.
My current code:
$criteria = new CDbCriteria;
$criteria->with = array('A', 'B', 'C', 'D', 'E');
$criteria->compare("A.field1", "test", false, 'OR');
$criteria->compare("A.field2", "test", false, 'OR');
$criteria->compare("B.field1", "test", false, 'OR');
$criteria->compare("B.field2", "test", false, 'OR');
$dataProvider = new CActiveDataProvider('Z', array(
'criteria'=>$criteria,
//pagination...
//more options...
));
Update: It seems that you are actually looking(from comments below this answer) for partial matches, and for that you will have to pass true to your compare calls:
$criteria->compare("A.field1", "test", true, 'OR');
Even that can be passed to addCondition:
$criteria->addCondition('A.field1 LIKE "%test"','OR');
// or with params as below
$criteria->addCondition('A.field2 LIKE :test','OR');
$criteria->params=array(
':test'=>'%test%',
);
As i have already mentioned in the comments, i don't think it'll be possible to use each model's default search() method. There are other alternatives though, for instance you can use addCondition instead:
$criteria = new CDbCriteria;
$criteria->with = array('A', 'B', 'C', 'D', 'E');
$criteria->together = true; // you'll need together so that the other tables are joined in the same query
$criteria->addCondition('A.field1 = "test"','OR');
$criteria->addCondition('A.field2 = "test"','OR');
// and so on
I would suggest going with the above, because compare (doc-link) should actually be used in cases when you want to "intelligently" determine the operator for comparision, for example: if you are taking the test values from user input and the user is allowed to use operators (<,>,<= etc). After determining the operator to be used in the condition, compare calls other functions accordingly, including addCondition. So using addCondition will atleast avoid those unnecessary checks.
Further if all you have to do is check equality only, i.e if your sql's WHERE is supposed to be:
WHERE A.field1 = "test" OR A.field2 = "test"
then you don't even need addCondition, and you can simply use a more complex condition (doc) :
$criteria->condition='A.field1 = "test" OR A.field2 = "test"';
// or even better if you use params
$criteria->condition='A.field1 =:test1 OR A.field2 =:test2 OR B.field1 =:test3 OR B.field2 =:test3';
$criteria->params=array(
':test1'=>'test',
':test2'=>'anothertest',
'test3'=>'tests' // omitting ':' here for params also works
);