Is there functions in coldfusion to get just 2 lines of text from a string? - function

I know this works in other languages, but wanted to see if there is existing code/functions.
This string can be populated from numerous different queries, but they need to be all displayed the same way, same length etc.
I have a function, to control string length by word count, but I would prefer to make sure that I have at least 2 sentences or 2 lines of text at most.
Thanks

I had a similar task at my job and you have to pick an arbitrary number, and it looks like you've chosen 190. That being said, you can't just hope that the characters/words returned are relevant. You have to ensure that they are if its something you care about, which is seems like you do looking at your comments.
Try to find the keyword in the string and use the mid() function to get a certain number of characters on either side of the keyword:
<cfscript>
max_chars = 190;
full_article = #the full article#;
keyword_position = find(keyword, full_article);
if( keyword_position != 0 ) {
excerpt = mid(full_article,
keyword_position - max_chars / 2 - len(keyword_position) / 2,
max_chars);
}
</cfscript>
...or something like that. I'll leave it to you to make sure that you're not trying to get characters before the start of the full_article, or after the end of it, and adding ellipses and stuff.

Try something like fullLeft or dig through the other string manipulation UDFs at CFLib. If you're looking for something more specific could you show us a comparable function in another language and we'd be better able to point you to something similar.

_TestString = "I know this works in other languages, but wanted to see if there is existing code/functions. This string can be populated from numerous different queries, but they need to be";
if ( len(_TestString) GT 190)
{
_TestString = Left(_TestString,190) & "...";
}
That will output:
I know this works in other languages, but wanted to see if there is existing code/functions. This string can be populated from numerous different queries, but they need to be all displayed t...
You probably don't want to do anything more than that, string manipulation can get expensive for no reason, you shouldn't waste processing on the display layer unless you have to.

CFLIB has plenty of string manipulation functions on offer. You may find abbreviate() is useful, especially for search results: http://cflib.org/udf/abbreviate
<cfscript>
/**
* Abbreviates a given string to roughly the given length, stripping any tags, making sure the ending doesn't chop a word in two, and adding an ellipsis character at the end.
* Fix by Patrick McElhaney
* v3 by Ken Fricklas kenf#accessnet.net, takes care of too many spaces in text.
*
* #param string String to use. (Required)
* #param len Length to use. (Required)
* #return Returns a string.
* #author Gyrus (kenf#accessnet.netgyrus#norlonto.net)
* #version 3, September 6, 2005
*/
function abbreviate(string,len) {
var newString = REReplace(string, "<[^>]*>", " ", "ALL");
var lastSpace = 0;
newString = REReplace(newString, " \s*", " ", "ALL");
if lenn(newString) gt len) {
newString = left(newString, len-2);
lastSpace = find(" ", reverse(newString));
lastSpace = len(newString) - lastSpace;
newString = left(newString, lastSpace) & " &##8230;";
}
return newString;
}
</cfscript>

Related

How to replace numbered list elements with an identifier containing the number

I have gotten amazing help here today!
I'm trying to do something else. I have a numbered list of questions in a Google Doc, and I'd like to replace the numbers with something else.
For example, I'd like to replace the numbers in a list such as:
The Earth is closest to the Sun in which month of the year?
~July
~June
=January
~March
~September
In Australia (in the Southern Hemisphere), when are the days the shortest and the nights the longest?
~in late December
~in late March
=in late June
~in late April
~days and nights are pretty much the same length throughout the year in Australia
With:
::Q09:: The Earth is closest to the Sun in which month of the year?
~July
~June
=January
~March
~September
::Q11:: In Australia (in the Southern Hemisphere), when are the days the shortest and the nights the longest?
~in late December
~in late March
=in late June
~in late April
~days and nights are pretty much the same length throughout the year in Australia
I've tried using suggestions from previous posts but have come up only with things such as the following, which doesn't seem to work.
Thank you for being here!!!
function questionName2(){
var body = DocumentApp.getActiveDocument().getBody();
var text = body.editAsText();
var pattern = "^[1-9]";
var found = body.findText(pattern);
var matchPosition = found.getStartOffset();
while(found){
text.insertText(matchPosition,'::Q0');
found = body.findText(pattern, found);
}
}
Regular expressions
Text.findText(searchPattern) uses a string that will be parsed as a regular expression using Google's RE2 library for the searchPattern. Using a string in this way requires we add an extra backslash whenever we are removing special meaning from a character, such as matching the period after the question number, or using a character matching set like \d for digits.
^\\s*\\d+?\\. will match a set of digits, of any non-zero length, that begin a line, with any length (including zero) of leading white space. \d is for digits, + is one or more, and the combination +? makes the match lazy. The lazy part is not required here, but it's my habit to default to lazy to avoid bugs. An alternative would be \d{1,2} to specifically match 1 to 2 digits.
To extract just the digits from the matched text, we can use a JavaScript RegExp object. Unlike the Doc regular expression, this regular expression will not require extra backslashes and will allow us to use capture groups using parentheses.
^\s*(\d+?)\. is almost the same as above, except no extraneous slashes and we will now "save" the digits so we can use them in our replacement string. We mark what we want to save using parentheses. Because this will be a normal JavaScript regular expression literal, we will wrap the whole thing in slashes: /^\s*(\d+?)\./, but the starting and ending / are just to indicate this is a RegExp literal.
text elements and text strings
Text.findText can return more than just the exact match we asked for: it returns the entire element that contains the text plus indices for what the regular expression matched. In order to perform search and replace with capture groups, we have to use the indices to delete the old text and then insert the new text.
The following assignments get us all the data we need to do the search and replace: first the element, then the start & stop indices, and finally extracting the matched text string using slice (note that slice uses an exclusive end, whereas the Doc API uses an inclusive end, hence the +1).
var found = DocumentApp.getActiveDocument().getBody().findText(pattern);
var matchStart = found.getStartOffset();
var matchEnd = found.getEndOffsetInclusive();
var matchElement = found.getElement().asText();
var matchText = matchElement.getText().slice(matchStart, matchEnd + 1);
Caveats
As Tanaike pointed out in the comments, this assumes the numbering is not List Items, which automatically generates numbers, but numbers you typed in manually. If you are using an automatically generated list of numbers, the API does not allow you to edit the format of the numbering.
This answer also assumes that in the example, when you mapped "9." to "::Q09::" and "10." to "::Q11::", that the mapping of 10 to 11 was a typo. If this was intended, please update the question to clarify the rules for why the numbering might change.
Also assumed is that the numbers are supposed to be less than 100, given the example zero padding of "Q09". The example should be flexible enough to allow you to update this to a different padding scheme if needed.
Full example
Since the question did not use any V8 features, this assumes the older Rhino environment.
/**
* Replaces "1." with "::Q01::"
*/
function updateQuestionNumbering(){
var text = DocumentApp.getActiveDocument().getBody();
var pattern = "^\\s*\\d+?\\.";
var found = text.findText(pattern);
while(found){
var matchStart = found.getStartOffset();
var matchEnd = found.getEndOffsetInclusive();
var matchElement = found.getElement().asText();
var matchText = matchElement.getText().slice(matchStart, matchEnd + 1);
matchElement.deleteText(matchStart, matchEnd);
matchElement.insertText(matchStart, matchText.replace(/^\s*(\d+?)\./, replacer));
found = text.findText(pattern, found);
}
/**
* #param {string} _ - full match (ignored)
* #param {string} number - the sequence of digits matched
*/
function replacer(_, number) {
return "::Q" + padStart(number, 2, "0") + "::";
}
// use String.prototype.padStart() in V8 environment
// above usage would become `number.padStart(2, "0")`
function padStart(string, targetLength, padString) {
while (string.length < targetLength) string = padString + string;
return string;
}
}

Where to store SQL commands for execution

We face code quality issues because of inline mysql queries. Having self-written mysql queries really clutters the code and also increases code base etc.
Our code is cluttered with stuff like
/* beautify ignore:start */
/* jshint ignore:start */
var sql = "SELECT *"
+" ,DATE_ADD(sc.created_at,INTERVAL 14 DAY) AS duedate"
+" ,distance_mail(?,?,lat,lon) as distance,count(pks.skill_id) c1"
+" ,count(ps.profile_id) c2"
+" FROM TABLE sc"
+" JOIN "
+" PACKAGE_V psc on sc.id = psc.s_id "
+" JOIN "
+" PACKAGE_SKILL pks on pks.package_id = psc.package_id "
+" LEFT JOIN PROFILE_SKILL ps on ps.skill_id = pks.skill_id and ps.profile_id = ?"
+" WHERE sc.type in "
+" ('a',"
+" 'b',"
+" 'c' ,"
+" 'd',"
+" 'e',"
+" 'f',"
+" 'g',"
+" 'h')"
+" AND sc.status = 'open'"
+" AND sc.crowd_type = ?"
+" AND sc.created_at < DATE_SUB(NOW(),INTERVAL 10 MINUTE) "
+" AND sc.created_at > DATE_SUB(NOW(),INTERVAL 14 DAY)"
+" AND distance_mail(?, ?,lat,lon) < 500"
+" GROUP BY sc.id"
+" HAVING c1 = c2 "
+" ORDER BY distance;";
/* jshint ignore:end */
/* beautify ignore:end */
I had to blur the code a little bit.
As you can see, having this repeatedly in your code is just unreadable. Also because atm we can not go to ES6, which would at least pretty the string a little bit thanks to multi-line strings.
The question now is, is there a way to store that SQL procedures in one place? As additional information, we use node (~0.12) and express to expose an API, accessing a MySQL db.
I already thought about, using a JSON, which will result in an even bigger mess. Plus it may not even be possible since the charset for JSON is a little bit strict and the JSON will probably not like having multi line strings too.
Then I came up with the idea to store the SQL in a file and load at startup of the node app. This is at the moment my best shot to get the SQL queries at ONE place and offering them to the rest of the node modules.
Question here is, use ONE file? Use one file per query? Use one file per database table?
Any help is appreciated, I can not be the first on the planet solving this so maybe someone has a working, nice solution!
PS: I tried using libs like squel but that does not really help, since our queries are complex as you can see. It is mainly about getting OUR queries into a "query central".
I prefer putting every bigger query in one file. This way you can have syntax highlighting and it's easy to load on server start. To structure this, i usually have one folder for all queries and inside that one folder for each model.
# queries/mymodel/select.mymodel.sql
SELECT * FROM mymodel;
// in mymodel.js
const fs = require('fs');
const queries = {
select: fs.readFileSync(__dirname + '/queries/mymodel/select.mymodel.sql', 'utf8')
};
I suggest you store your queries in .sql files away from your js code. This will separate the concerns and make both code & queries much more readable. You should have different directories with nested structure based on your business.
eg:
queries
├── global.sql
├── products
│ └── select.sql
└── users
└── select.sql
Now, you just need to require all these files at application startup. You can either do it manually or use some logic. The code below will read all the files (sync) and produce an object with the same hierarchy as the folder above
var glob = require('glob')
var _ = require('lodash')
var fs = require('fs')
// directory containing all queries (in nested folders)
var queriesDirectory = 'queries'
// get all sql files in dir and sub dirs
var files = glob.sync(queriesDirectory + '/**/*.sql', {})
// create object to store all queries
var queries = {}
_.each(files, function(file){
// 1. read file text
var queryText = fs.readFileSync(__dirname + '/' + file, 'utf8')
// 2. store into object
// create regex for directory name
var directoryNameReg = new RegExp("^" + queriesDirectory + "/")
// get the property path to set in the final object, eg: model.queryName
var queryPath = file
// remove directory name
.replace(directoryNameReg,'')
// remove extension
.replace(/\.sql/,'')
// replace '/' with '.'
.replace(/\//g, '.')
// use lodash to set the nested properties
_.set(queries, queryPath, queryText)
})
// final object with all queries according to nested folder structure
console.log(queries)
log output
{
global: '-- global query if needed\n',
products: {
select: 'select * from products\n'
},
users: {
select: 'select * from users\n'
}
}
so you can access all queries like this queries.users.select
Put your query into database procedure and call procedure in the code, when it is needed.
create procedure sp_query()
select * from table1;
There are a few things you want to do. First, you want to store multi-line without ES6. You can take advantage of toString of a function.
var getComment = function(fx) {
var str = fx.toString();
return str.substring(str.indexOf('/*') + 2, str.indexOf('*/'));
},
queryA = function() {
/*
select blah
from tableA
where whatever = condition
*/
}
console.log(getComment(queryA));
You can now create a module and store lots of these functions. For example:
//Name it something like salesQry.js under the root directory of your node project.
var getComment = function(fx) {
var str = fx.toString();
return str.substring(str.indexOf('/*') + 2, str.indexOf('*/'));
},
query = {};
query.template = getComment(function() { /*Put query here*/ });
query.b = getComment(function() {
/*
SELECT *
,DATE_ADD(sc.created_at,INTERVAL 14 DAY) AS duedate
,distance_mail(?,?,lat,lon) as distance,count(pks.skill_id) c1
,count(ps.profile_id) c2
FROM TABLE sc
JOIN PACKAGE_V psc on sc.id = psc.s_id
JOIN PACKAGE_SKILL pks on pks.package_id = psc.package_id
LEFT JOIN PROFILE_SKILL ps on ps.skill_id = pks.skill_id AND ps.profile_id = ?
WHERE sc.type in ('a','b','c','d','e','f','g','h')
AND sc.status = 'open'
AND sc.crowd_type = ?
AND sc.created_at < DATE_SUB(NOW(),INTERVAL 10 MINUTE)
AND sc.created_at > DATE_SUB(NOW(),INTERVAL 14 DAY)
AND distance_mail(?, ?,lat,lon) < 500
GROUP BY sc.id
HAVING c1 = c2
ORDER BY distance;
*/
});
//Debug
console.log(query.template);
console.log(query.b);
//module.exports.query = query //Uncomment this.
You can require the necessary packages and build your logic right in this module or build a generic wrapper module for better OO design.
//Name it something like SQL.js. in the root directory of your node project.
var mysql = require('mysql'),
connection = mysql.createConnection({
host: 'localhost',
user: 'me',
password: 'secret',
database: 'my_db'
});
module.exports.load = function(moduleName) {
var SQL = require(moduleName);
return {
query: function(statement, param, callback) {
connection.connect();
connection.query(SQL[statement], param, function(err, results) {
connection.end();
callback(err, result);
});
}
});
To use it, you do something like:
var Sql = require ('./SQL.js').load('./SalesQry.js');
Sql.query('b', param, function (err, results) {
...
});
I come from different platform, so I'm not sure if this is what you are looking for. like your application, we had many template queries and we don't like having it hard-coded in the application.
We created a table in MySQL, allowing to save Template_Name (unique), Template_SQL.
We then wrote a small function within our application that returns the SQL template.
something like this:
SQL = fn_get_template_sql(Template_name);
we then process the SQL something like this:
pseudo:
if SQL is not empty
SQL = replace all parameters// use escape mysql strings from your parameter
execute the SQL
or you could read the SQL, create connection and add parameters using your safest way.
This allows you to edit the template query where and whenever. You can create an audit table for the template table capturing all previous changes to revert back to previous template if needed. You can extend the table and capture who and when was the SQL last edited.
from performance point of view, this would work as on-the-fly plus you don't have to read any files or restart server when you are depending on starting-server process when adding new templates.
You could create a completely new npm module let's assume the custom-queries module and put all your complex queries in there.
Then you can categorize all your queries by resource and by action. For example, the dir structure can be:
/index.js -> it will bootstrap all the resources
/queries
/queries/sc (random name)
/queries/psc (random name)
/queries/complex (random name)
The following query can live under the /queries/complex directory in its own file and the file will have a descriptive name (let's assume retrieveDistance)
// You can define some placeholders within this var because possibly you would like to be a bit configurable and reuseable in different parts of your code.
/* jshint ignore:start */
var sql = "SELECT *"
+" ,DATE_ADD(sc.created_at,INTERVAL 14 DAY) AS duedate"
+" ,distance_mail(?,?,lat,lon) as distance,count(pks.skill_id) c1"
+" ,count(ps.profile_id) c2"
+" FROM TABLE sc"
+" JOIN "
+" PACKAGE_V psc on sc.id = psc.s_id "
+" JOIN "
+" PACKAGE_SKILL pks on pks.package_id = psc.package_id "
+" LEFT JOIN PROFILE_SKILL ps on ps.skill_id = pks.skill_id and ps.profile_id = ?"
+" WHERE sc.type in "
+" ('a',"
+" 'b',"
+" 'c' ,"
+" 'd',"
+" 'e',"
+" 'f',"
+" 'g',"
+" 'h')"
+" AND sc.status = 'open'"
+" AND sc.crowd_type = ?"
+" AND sc.created_at < DATE_SUB(NOW(),INTERVAL 10 MINUTE) "
+" AND sc.created_at > DATE_SUB(NOW(),INTERVAL 14 DAY)"
+" AND distance_mail(?, ?,lat,lon) < 500"
+" GROUP BY sc.id"
+" HAVING c1 = c2 "
+" ORDER BY distance;";
/* jshint ignore:end */
module.exports = sql;
The top level index.js will export an object with all the complex queries. An example can be:
var sc = require('./queries/sc');
var psc = require('./queries/psc');
var complex = require('./queries/complex');
// Quite important because you want to ensure that no one will touch the queries outside of
// the scope of this module. Be careful, because the Object.freeze is freezing only the top
// level elements of the object and it is not recursively freezing the nested objects.
var queries = Object.freeze({
sc: sc,
psc: psc,
complex: complex
});
module.exports = queries;
Finally, on your main code you can use the module like that:
var cq = require('custom-queries');
var retrieveDistanceQuery = cq.complex.retrieveDistance;
// #todo: replace the placeholders if they exist
Doing something like that you will move all the noise of the string concatenation to another place that you would expect and you will be able to find quite easily in one place all your complex queries.
This is no doubt a million dollar question, and I think the right solution depends always on the case.
Here goes my thoughts. Hope could help:
One simple trick (which, in fact, I read that it is surprisingly more efficient than joining strings with "+") is to use arrays of strings for each row and join them.
It continues being a mess but, at least for me, a bit clearer (specially when using, as I do, "\n" as separator instead of spaces, to make resulting strings more readable when printed out for debugging).
Example:
var sql = [
"select foo.bar",
"from baz",
"join foo on (",
" foo.bazId = baz.id",
")", // I always leave the last comma to avoid errors on possible query grow.
].join("\n"); // or .join(" ") if you prefer.
As a hint, I use that syntax in my own SQL "building" library. It may not work in too complex queries but, if you have cases in which provided parameters could vary, it is very helpful to avoid (also subotptimal) "coalesce" messes by fully removing unneeded query parts. It is also on GitHub, (and it isn't too complex code), so you can extend it if you feel it useful.
If you prefer separate files:
About having single or multiple files, having multiple files is less efficient from the point of view of reading efficiency (more file open/close overhead and harder OS level caching). But, if you load all of them single time at startup, it is not in fact a hardly noticeable difference.
So, the only drawback (for me) is that it is too hard to have a "global glance" of your query collection. Even, if you have very huge amount of queries, I think it is better to mix both approaches. That is: group related queries in the same file so you have single file per each module, submodel or whatever criteria you chosen.
Of course: Single file would result in relatively "huge" file, also difficult to handle "at first". But I (hardly) use vim's marker based folding (foldmethod=marker) which is very helpfull to handle that files.
Of course: if you don't (yet) use vim (truly??), you wouldn't have that option, but sure there is another alternative in your editor. If not, you always can use syntax folding and something like "function (my_tag) {" as markers.
For example:
---(Query 1)---------------------/*{{{*/
select foo from bar;
---------------------------------/*}}}*/
---(Query 2)---------------------/*{{{*/
select foo.baz
from foo
join bar using (foobar)
---------------------------------/*}}}*/
...when folded, I see it as:
+-- 3 línies: ---(Query 1)------------------------------------------------
+-- 5 línies: ---(Query 2)------------------------------------------------
Which, using properly selected labels, is much more handy to manage and, from the parsing point of view, is not difficult to parse the whole file splitting queries by that separation rows and using labels as keys to index the queries.
Dirty example:
#!/usr/bin/env node
"use strict";
var Fs = require("fs");
var src = Fs.readFileSync("./test.sql");
var queries = {};
var label = false;
String(src).split("\n").map(function(row){
var m = row.match(/^-+\((.*?)\)-+[/*{]*$/);
if (m) return queries[label = m[1].replace(" ", "_").toLowerCase()] = "";
if(row.match(/^-+[/*}]*$/)) return label = false;
if (label) queries[label] += row+"\n";
});
console.log(queries);
// { query_1: 'select foo from bar;\n',
// query_2: 'select foo.baz \nfrom foo\njoin bar using (foobar)\n' }
console.log(queries["query_1"]);
// select foo from bar;
console.log(queries["query_2"]);
// select foo.baz
// from foo
// join bar using (foobar)
Finally (idea), if you do as much effort, wouldn't be a bad idea to add some boolean mark together with each query label telling if that query is intended to be used frequently or only occasionally. Then you can use that information to prepare those statements at application startup or only when they are going to be used more than single time.
Can you create a view which that query.
Then select from the view
I don't see any parameters in the query so I suppose view creation is possible.
Create store procedures for all queries, and replace the var sql = "SELECT..." for calling the procedures like var sql = "CALL usp_get_packages".
This is the best for performance and no dependency breaks on the application. Depending on the number of queries may be a huge task, but for every aspect (maintainability, performance, dependencies, etc) is the best solution.
I'm late to the party, but if you want to store related queries in a single file, YAML is a good fit because it handles arbitrary whitespace better than pretty much any other data serialization format, and it has some other nice features like comments:
someQuery: |-
SELECT *
,DATE_ADD(sc.created_at,INTERVAL 14 DAY) AS duedate
,distance_mail(?,?,lat,lon) as distance,count(pks.skill_id) c1
,count(ps.profile_id) c2
FROM TABLE sc
-- ...
# Here's a comment explaining the following query
someOtherQuery: |-
SELECT 1;
This way, using a module like js-yaml you can easily load all of the queries into an object at startup and access each by a sensible name:
const fs = require('fs');
const jsyaml = require('js-yaml');
export default jsyaml.load(fs.readFileSync('queries.yml'));
Here's a snippet of it in action (using a template string instead of a file):
const yml =
`someQuery: |-
SELECT *
FROM TABLE sc;
someOtherQuery: |-
SELECT 1;`;
const queries = jsyaml.load(yml);
console.dir(queries);
console.log(queries.someQuery);
<script src="https://unpkg.com/js-yaml#3.8.1/dist/js-yaml.min.js"></script>
Another approach with separate files by using ES6 string templates.
Of course, this doesn't answer the original question because it requires ES6, but there is already an accepted answer which I'm not intending to replace. I simply thought that it is interesting from the point of view of the discussion about query storage and management alternatives.
// myQuery.sql.js
"use strict";
var p = module.parent;
var someVar = p ? '$1' : ':someVar'; // Comments if needed...
var someOtherVar = p ? '$2' : ':someOtherVar';
module.exports = `
--##sql##
select foo from bar
where x = ${someVar} and y = ${someOtherVar}
--##/sql##
`;
module.parent || console.log(module.exports);
// (or simply "p || console.log(module.exports);")
NOTE: This is the original (basic) approach. I
later evolved it adding some interesting improvements
(BONUS, BONUS 2 and FINAL EDIT sections). See the bottom of
this post for a full-featured snipet.
The advantages of this approach are:
Is very readable, even the little javascript overhead.
It also can be properly syntax higlighted (at least in Vim) both javascript and SQL sections.
Parameters are placed as readable variable names instead of silly "$1, $2", etc... and explicitly declared at the top of the file so it's simple to check in which order they must be provided.
Can be required as myQuery = require("path/to/myQuery.sql.js") obtaining valid query string with $1, $2, etc... positional parameters in the specified order.
But, also, can be directly executed with node path/to/myQuery.sql.js obtaining valid SQL to be executed in a sql interpreter
This way you can avoid the mess of copying forth and back the query and replace parameter specification (or values) each time from query testing environments to application code: Simply use the same file.
Note: I used PostgreSQL syntax for variable names. But with other databases, if different, it's pretty simple to adapt.
More than that: with a few more tweaks (see BONUS section), you can turn it in a viable console testing tool and:
Generate yet parametized sql by executing something like node myQueryFile.sql.js parameter1 parameter2 [...].
...or directly execute it by piping to your database console. Ex: node myQueryFile.sql.js some_parameter | psql -U myUser -h db_host db_name.
Even more: You also can tweak the query making it to behave slightly different when executed from console (see BONUS 2 section) avoiding to waste space displaying large but no meaningful data while keeping it when the query is read by the application that needs it.
And, of course: you can pipe it again to less -S to avoid line wrapping and be able to easily explore data by scrolling it both in horizontal and vertical directions.
Example:
(
echo "\set someVar 3"
echo "\set someOtherVar 'foo'"
node path/to/myQuery.sql.js
) | psql dbName
NOTES:
'##sql##' and '##/sql##' (or similar) labels are fully optional,
but very useful for proper syntax highlighting, at least in Vim.
This extra-plumbing is no more necessary (see BONUS section).
In fact, I actually doesn't write below (...) | psql... code directly to console but simply (in a vim buffer):
echo "\set someVar 3"
echo "\set someOtherVar 'foo'"
node path/to/myQuery.sql.js
...as many times as test conditions I want to test and execute them by visually selecting desired block and typing :!bash | psql ...
BONUS: (edit)
I ended up using this approach in many projects with just a simple modification that consist in changing last row(s):
module.parent || console.log(module.exports);
// (or simply "p || console.log(module.exports);")
...by:
p || console.log(
`
\\set someVar '''${process.argv[2]}'''
\\set someOtherVar '''${process.argv[3]}'''
`
+ module.exports
);
This way I can generate yet parametized queries from command line just by passing parameters normally as position arguments. Example:
myUser#myHost:~$ node myQuery.sql.js foo bar
\set someVar '''foo'''
\set someOtherVar '''bar'''
--##sql##
select foo from bar
where x = ${someVar} and y = ${someOtherVar}
--##/sql##
...and, better than that: I can pipe it to postgres (or any other database) console just like this:
myUser#myHost:~$ node myQuery.sql.js foo bar | psql -h dbHost -u dbUser dbName
foo
------
100
200
300
(3 rows)
This approach make it much more easy to test multiple values because you can simply use command line history to recover previous commands and just edit whatever you want.
BONUS 2:
Two few more tricks:
1. Sometimes we need to retrieve some columns with binary and/or large data that make it difficult to read from console and, in fact, we probaby even don't need to see them at all while testing the query.
In this cases we can take advantadge of the p variable to alter the output of the query and shorten, format more properly, or simply remove that column from the projection.
Examples:
Format: ${p ? jsonb_column : "jsonb_pretty("+jsonb_column+")"},
Shorten: ${p ? long_text : "substring("+long_text+")"},
Remove: ${p ? binary_data + "," : "" (notice that, in this case, I moved the comma inside the exprssion due to be able to avoid it in console version.
2. Not a trick in fact but just a reminder: We all know that to deal with large output in the console, we only need to pipe it to less command.
But, at least me, often forgive that, when ouput is table-aligned and too wide to fit in our terminal, there is the -S modifier to instruct less not to wrap and instead let us scroll text also in horizontal direction to explore the data.
Here full version of the original snipped with this change applied:
// myQuery.sql.js
"use strict";
var p = module.parent;
var someVar = p ? '$1' : ':someVar'; // Comments if needed...
var someOtherVar = p ? '$2' : ':someOtherVar';
module.exports = `
--##sql##
select
foo
, bar
, ${p ? baz : "jsonb_pretty("+baz+")"}
${p ? ", " + long_hash : ""}
from bar
where x = ${someVar} and y = ${someOtherVar}
--##/sql##
`;
p || console.log(
`
\\set someVar '''${process.argv[2]}'''
\\set someOtherVar '''${process.argv[3]}'''
`
+ module.exports
);
FINAL EDIT:
I have been evolving a lot more this concept until it became too wide to be strictly manually handled approach.
Finally, taking advantage of the great ES6+ Tagged Templates i implemented a much simpler library driven approach.
So, in case anyone could be interested in it, here it is: SQLTT
Call procedure in the code after putting query into the db procedure. #paval also already answered
you may also refer here.
create procedure sp_query()
select * from table1;

Split long string to obtain multiple values/strings - google spreadsheet

I have complex string in which I need to pull single words and/or multiple words.
Here is the string:
<query xmlns:yahoo="http://www.yahooapis.com/v1/base.rng" yahoo:count="5" yahoo:created="2013-07-28T18:37:23Z" yahoo:lang="en-US"><diagnostics><publiclyCallable>true</publiclyCallable><user-time>145</user-time><service-time>141</service-time><build-version>38483</build-version></diagnostics><results><Result xmlns="urn:yahoo:cate">**RED**</Result><Result xmlns="urn:yahoo:cate">**GREEN**</Result><Result xmlns="urn:yahoo:cate">**BLUE**</Result><Result xmlns="urn:yahoo:cate">**A, E, I, O, U **</Result><Result xmlns="urn:yahoo:cate">**SOMETIMES Y**</Result></results></query><!-- total: 145 -->
(I really wish that wouldn't scroll, since it makes it difficult to see the entire picture)
Anyway, I need to be able to pull out the:
RED
GREEN
BLUE
A, E, I, O, U
SOMETIMES Y
++++ btw, I tried to make those values BOLD in the big string, but they show up with asteriks instead. Disredard the asterisks. They are not part of the string. However I'm leaving them in there since it makes them easier to find when you look at the entire string)
++++
My goal is to turn that complex string into this:
RED|GREEN|BLUE|A, E, I, O, U|SOMETIMES Y
My preference is to do this on the sheet level using a single nested function (or a combination of multiple functions if necessary).
Failing that, a script version would be preferable to nothing.
I've been at this for hours using SPLIT, FIND, SUBSTITUTE, and a few other things that I tried on a whim - just to try everything. But I've now reached the saturation point of thinking clearly on this, and I'm hoping that someone can put me on a path for how to attack this logically.
I'm truly stumped (and frustrated).
==========================================
I said that I'd post the solution if I figured out the sheet-level solution, so this is it:
=mid(substitute(substitute(regexreplace(mid(A1,find("<Result",A1),find("</query",A1)-find("<Result",A1)),"<.*?>+","-"),"--","|"),"-","|"),2,len(substitute(substitute(regexreplace(mid(A1,find("<Result",A1),find("</query",A1)-find("<Result",A1)),"<.*?>+","-"),"--","|"),"-","|"))-2)
Have you considered using XmlService Services? https://developers.google.com/apps-script/reference/xml-service
Simple example:
/* CODE FOR DEMONSTRATION PURPOSES */
function testXML() {
var result = [];
var document = XmlService.parse('<query xmlns:yahoo="http://www.yahooapis.com/v1/base.rng" yahoo:count="5" yahoo:created="2013-07-28T18:37:23Z" yahoo:lang="en-US"><diagnostics><publiclyCallable>true</publiclyCallable><user-time>145</user-time><service-time>141</service-time><build-version>38483</build-version></diagnostics><results><Result xmlns="urn:yahoo:cate">RED</Result><Result xmlns="urn:yahoo:cate">GREEN</Result><Result xmlns="urn:yahoo:cate">BLUE</Result><Result xmlns="urn:yahoo:cate">A, E, I, O, U</Result><Result xmlns="urn:yahoo:cate">SOMETIMES Y</Result></results></query><!-- total: 145 -->');
var entries = document.getRootElement().getChildren('results')[0].getChildren();
for (var i = 0, len = entries.length; i < len; ++i)
result.push(entries[i].getText());
Logger.log(result.join('|'));
}

Randomly selecting an object property

I guess a step back is in order. My original question is at the bottom of this post for reference.
I am writing a word guessing game and wanted a way to:
1. Given a word length of 2 - 10 characters, randomly generate a valid english word to guess
2.given a 2 - 10 character guess, ensure that it is a valid english word.
I created a vector of 9 objects, one for each word length and dynamically created 172000
property/ value pairs using the words from a word list to name the properties and setting their value to true. The inner loop is:
for (i = 0; i < _WordCount[wordLength] - 2; i)
{
_WordsList[wordLength]["" + _WordsVector[wordLength][i++]] = true;
}
To validate a word , the following lookup returns true if valid:
function Validate(key:String):Boolean
{
return _WordsList[key.length - 2][key]
}
I transferred them from a vector to objects to take advantage of the hash take lookup of the properties. Haven't looked at how much memory this all takes but it's been a useful learning exercise.
I just wasn't sure how best to randomly choose a property from one of the objects. I was thinking of validating whatever method I chose by generating 1000 000 words and analyzing the statistics of the distribution.
So I suppose my question should really first be am I better off using some other approach such as keeping the lists in vectors and doing a search each time ?
Original question
Newbie first question:
I read a thread that said that traversal order in a for.. in is determined by a hash table and appears random.
I'm looking for a good way to randomly select a property in an object. Would the first element in a for .. in traversing the properties, or perhaps the random nth element in the iteration be truly random. I'd like to ensure that there is approximately an equal probability of accessing a given property. The Objects have between approximately 100 and 20000 properties. Other approaches ?
thanks.
Looking at the scenario you described in your edited question, I'd suggest using a Vector.<String> and your map object.
You can store all your keys in the vector and map them in the object, then you can select a random numeric key in the vector and use the result as a key in the map object.
To make it clear, take a look at this simple example:
var keys:Vector.<String> = new Vector.<String>();
var map:Object = { };
function add(key:String, value:*):void
{
keys.push(key);
map[key] = value;
}
function getRandom():*
{
var randomKey = keys[int(Math.random() * keys.length)];
return map[randomKey];
}
And you can use it like this:
add("a", "x");
add("b", "y");
add("c", "z");
var radomValue:* = getRandom();
Using Object instead of String
Instead of storing the strings you can store objects that have the string inside of them,
something like:
public class Word
{
public var value:String;
public var length:int;
public function Word(value:String)
{
this.value = value;
this.length = value.length;
}
}
Use this object as value instead of the string, but you need to change your map object to be a Dictionary:
var map:Dictionary = new Dictionary();
function add(key:Word, value:*):void
{
keys.push(key);
map[key] = value;
}
This way you won't duplicate every word (but will have a little class overhead).

How to sort var length ids (composite string + numeric)?

I have a MySQL database whose keys are of this type:
A_10
A_10A
A_10B
A_101
QAb801
QAc5
QAc25
QAd2993
I would like them to sort first by the alpha portion, then by the numeric portion, just like above. I would like this to be the default sorting of this column.
1) how can I sort as specified above, i.e. write a MySQL function?
2) how can I set this column to use the sorting routine by default?
some constraints that might be helpful: the numeric portion of my ID's never exceeds 100,000. I use this fact in some javascript code to convert my ID's to strings concatenating the non-numeric portion with the (number + 1,000,000). (At the time I had not noticed the variations/subparts as above such as A_10A, A_10B, so I'll have to revamp that part of my code.)
The best way to achieve what you want is to store each part in its own column, and I would strongly recommend to change table structure. If it's impossible, you can try the following:
Create 3 UDFs which returns prefix, numeric part, and postfix of your string. For a better performance they should be native (Mysql, as any other RDMS, is not really good in complex string parsing). Then you can call these functions in ORDER BY clause or in trigger body which validates your column. In any case, it will work slower than if you create 3 columns.
No simple answer that I know of. I had something similar a while back but had to use jQuery to sort it. So what I did was first get the output into an javascript array. Then you may want to insert a zero padding to your numbers. Separate the Alpha from Nummerics using a regex, then reassemble the array:
var zarr = new Array();
for(var i=0; i<val.length; i++){
var chunk = val[i].match(/(\d+|[^\d]+)/g).join(',');
var chunks = chunk.split(",");
for(var s=0; s<chunks.length; s++){
if(isNaN(chunks[s]) == true)
zarr.push(chunks[s]);
else
zarr.push(zeroPad(chunks[s], 5));
}
}
function zeroPad(num,count){
var numZeropad = num + '';
while(numZeropad.length < count) {
numZeropad = "0" + numZeropad;
}
return numZeropad;
}
You'll end up with an array like this:
A_00100
QAb00801
QAc00005
QAc00025
QAd02993
Then you can do a natural sort. I know you may want to do it through straight MySQL but I am not to sure if it does natural sorting.
Good luck!