Video in TIB AV-Portal: Shabang

Formal Metadata

Title of Series
Number of Parts
CC Attribution - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this license.
Release Date
Production Place
Ottawa, Canada

Content Metadata

Subject Area
Scripting with Postgres Sometimes bash is just the way to go! This talk will cover tips and techniques for effective bash scripting with PostgreSQL. Sometimes bash is just the way to go! This talk will cover tips and techniques for effective bash scripting with PostgreSQL. It will include guidance about: Pros/cons of shell scripts Function library creation and use Executing SQL Set/get PostgreSQL data from/into script variables Keeping PostgreSQL functions in sync with scripts Locking Doing work in parallel Ensuring cleanup This is a source-code heavy talk. Moderate experience with both bash scripting and PostgreSQL is needed to get the most out of it.

Related Material

Ocean current Email Context awareness Functional (mathematics) Scripting language Ferry Corsten Code Multiplication sign Source code Function (mathematics) Average Mereology Computer programming Portable communications device Power (physics) Revision control Sign (mathematics) Goodness of fit Synchronization Term (mathematics) Different (Kate Ryan album) Gastropod shell Utility software Software testing Error message Task (computing) Physical system Scripting language Metropolitan area network Standard deviation Stapeldatei Code Database Bit Extreme programming Directory service Variable (mathematics) System call Type theory Computer animation Personal digital assistant System programming Revision control Statement (computer science) Task (computing) Library (computing) Asynchronous Transfer Mode
Email Context awareness Presentation of a group Scripting language Logarithm Multiplication sign Equaliser (mathematics) Source code Bell and Howell Function (mathematics) Client (computing) Parameter (computer programming) Mereology Different (Kate Ryan album) Set (mathematics) Information Descriptive statistics Scripting language Metropolitan area network Block (periodic table) Information systems Computer file Bit Variable (mathematics) Radical (chemistry) Process (computing) Data logger Right angle Ideal (ethics) Quicksort Block (periodic table) Standard error Slide rule Functional (mathematics) Sequel Computer file Real number Directory service Revision control Standard deviation Database Grand Unified Theory Directory service Binary file Density of states Timestamp System call Mathematics Uniform resource locator Word Bootstrap aggregating Computer animation Personal digital assistant Query language Function (mathematics) String (computer science) Video game Library (computing)
Metropolitan area network Touchscreen Electronic mailing list Grand Unified Theory Hand fan Front and back ends Population density Computer animation String (computer science) Statement (computer science) Integrated development environment Key (cryptography) Error message
Building Structural load Decision theory Set (mathematics) Mereology IP address Storage area network Sign (mathematics) Different (Kate Ryan album) Set (mathematics) Information Error message Scripting language Metropolitan area network Database transaction Port scanner Flow separation Connected space Order (biology) Normal (geometry) Software testing Right angle Quicksort Escape character Row (database) Slide rule Socket-Schnittstelle Functional (mathematics) Sequel Computer file Virtual machine Maxima and minima Hand fan Field (computer science) Value-added network Revision control String (computer science) Gamma function Traffic reporting Multiplication Key (cryptography) Information State of matter Database Grand Unified Theory Directory service Computer animation Personal digital assistant Query language String (computer science) Statement (computer science) Key (cryptography) Library (computing)
Metropolitan area network Scripting language Computer animation Software testing Key (cryptography) Figurate number Gamma function Hand fan Form (programming)
Context awareness Presentation of a group Group action Building Dynamical system Scripting language Structural load Multiplication sign Equaliser (mathematics) Mathematical singularity Thermal expansion Parameter (computer programming) Mereology Sign (mathematics) Scalar field Single-precision floating-point format Error message Physical system Scripting language Metropolitan area network Computer file Electronic mailing list Variable (mathematics) Process (computing) Oval Order (biology) Software testing Right angle Resultant Row (database) Ocean current Point (geometry) Functional (mathematics) Sequel Computer file Maxima and minima Drop (liquid) Revision control Natural number String (computer science) Operator (mathematics) Gamma function Multiplication Inheritance (object-oriented programming) Haar measure State of matter Database Line (geometry) Computer animation Integrated development environment Query language Personal digital assistant String (computer science) Revision control Statement (computer science) Gastropod shell
Group action Scripting language Equaliser (mathematics) Source code Bit error rate Numbering scheme Water vapor Software bug Medical imaging Set (mathematics) Information security Error message Physical system Intelligent Network Metropolitan area network Trail Structural load Electronic mailing list Sound effect Bit Instance (computer science) Electronic signature Data management Process (computing) Order (biology) Buffer solution System programming Figurate number Quicksort Point (geometry) Vacuum Slide rule Sequel Computer file Maxima and minima Canonical ensemble Product (business) Element (mathematics) Number Frequency Thetafunktion Flock (web browser) Stapeldatei Standard deviation Matching (graph theory) Server (computing) BEEP Weight Counting Grand Unified Theory Line (geometry) Causality Word Integrated development environment Software Query language Function (mathematics) Statement (computer science) Table (information) Force Building Structural load Length State of matter Multiplication sign Combinational logic 1 (number) EPROM Function (mathematics) Counting Mereology Replication (computing) Word Dedekind cut Synchronization Scripting language Area Software bug File format Real number Temporal logic Computer file Price index Flow separation Type theory Website Right angle Block (periodic table) Task (computing) Resultant Reverse engineering Row (database) Asynchronous Transfer Mode Functional (mathematics) Statistics Table (information) Gene cluster Discrete element method Graph coloring Hand fan 2 (number) Revision control Flow separation Causality Operator (mathematics) Software testing Gamma function Task (computing) Multiplication Red Hat Mathematical analysis Database Library catalog Human migration Exclusive or Film editing Computer animation Factory (trading post) Partial derivative
Metropolitan area network Table (information) Computer animation Information systems Maxima and minima Gamma function Hand fan Force Value-added network
Point (geometry) Area Metropolitan area network Functional (mathematics) Distribution (mathematics) Poisson-Klammer Parameter (computer programming) Mereology Code Food energy Computer animation Integrated development environment Average Different (Kate Ryan album) Compiler Software testing Office suite Table (information) Row (database) Library (computing) Form (programming)
came up with a way to ensure that that that happened reliably dominance just general techniques that can be useful when working with a database for all other things locking doing stuff in parallel and making sure that cleanup happens so what are some of the pros on you batch scripting is pretty easy to learn its ubiquitous it's all over the place that Unix Linux systems that is really is good for automating tasks but you know you can reasonably budget and and there's a lot of tools I think a lot of existing programs other people written kind in the in the way that people than UNIX using Unix and Linux 4 years you can rest on the shoulders of everyone that's gone before you there's so many useful utilities out there and you can just can't combine them all together and I have to rewrite what's that by using best fixed kinds are that you know it's not that good if you got really complex task to do and depending on your definition of slow it's relatively slow for a lot of things it's perfectly adequate but it's not super fast so you have to be careful if you wanna make your scriptural bust so and all the stuff that you see that's been scripted tends not to be all that robust and are as I just said there's some portability issues between different systems different versions of the show all different types of shells so all those things if you need to be portable you have to worry about so 1st what when scripting alike to have a common library that I'm going so I can reuse the stuff and not have to have the same function written over and over again and you don't want that for the all the obvious reason you don't wanna with the same version of a function in 18 different bash scripts it and then try to keep them in sync becomes impossible but it's it's good for version controls for testing and it's just a place to aggregate so in terms of the power function library that I like to use this is kind where I start out and some of these things we should talk about so set minus u is going to throw an error basically any time a script variable is has not been initialized you may or may not want this the other way to do this is within the call to each variable you can put a question mark at the end of it and then throw Arafat 1 doesn't exist I can like to make sure that all my my variables have been defined you can combine that actually with set minus the which also which says that the script should exit immediately if there's a but again depending on your context you know some places and then they don't like to see this in some places it's considered good practice to exit as soon as you have set plus x i minus X is going to turn on basically debugging it gives you fixed extreme of verbose output of everything that's going on in the shell and so you might you don't want that on all time certainly but by having it in here you can just kind of flip that to a minus sign and going into a debug mode and the other thing that is so over most that you don't always want so I often will have if statements around various parts of the code that relies on a variable called debugging so you can flip it in 1 place and then get some extra output debug output this stands here the reason I'm doing this is that you often will need to have a base name of the program trying and the base directory of a program that's running but sometimes when you're testing a developing it's kind a convenient to take this common library source you're open and so I if that's the case depending on the shelf you might get strange-looking values from a standard base directory so this bit here allows you to do some testing if you're resources thing into your and your current shelf verses when executing within some scripted you so this is pretty straightforward basins the command line program will take the of the dollar sign 0 is the name of the program is executing this is going to the basement of it is really a batch M is going to give me the canonical link so that of could pass so if someone's call it as dot slash whatever you like with the dot slash you can actually get expanded expanded directory 0 and the reason I only set from minus the if this is the case is because it if I'm running at the command-line shell and you turn on that minus C and then an error occurs which closest you show which is gonna inconvenient I
often will need some kind of an output directory so I usually will specify that is something under the base directory obviously this is going to be some place that you want to be and you know always was similar already exist so you might want to scream forcibly sending these examples I'm going to have some sequel files on doing the same thing for director called sequel there and then here you can see a set these variables as only sort of effectively treating these likening him and so again in my example later on on unlocking I'm going to use these as unlocked no wait and block as an anion would define and here in the common has no thing they often do is you want to create some kind of a log you wanna create some kind of an output and you want a timestamp on are often believe that we're running this thing over and over again you want to sort correctly when you list a directory of so this is just a frequently used this is something that appended the name of the output based on a date time and then this part what what this is going to do is is if you want all of your output everything that would go to standard out or standard error to the terminal you also want captured to a log file you basically turn this on myself that 1 and then this p is gonna output will to the terminal and the log file so again it's some places I've seen where everything just gets sent to log file but then when you're running the script on the command line it's not very convenient because you not seeing all that which are also telling log which of course you can do but just less convenient that now no you know this is a bit of the data function and I in another context monotonous slide deck but in other contexts had of the function that would do exactly and in this case for others to it for these examples each script is going include this common once and so the timestamp at the beginning of the run is more or less appropriate but it you could definitely put functions so then after all that stuff at the top of the common library that's when all functions will be defined I'm going to go through some of those as you go through the presentation so now every time you write a script that uses the common library the 1st thing it is kind of bootstrap to use the common library so this is my shebang right here but you normally it's good practice for some kind of a description of what this particular script is supposed to do because of loading this thing in our I'm often loading from the same director descriptors in you might have a standard location that you wanna use for that is in which case you would need to do this but my search at least in this example 1 again grabbing what is the what is the full path of the base directory that in and I'm going to make the assumption that that common libraries in there and the sources and the difference between sourcing at and running user command is that it's basically gets included in this script in life and it's a versus actually starting another process of running it return so this case I want all that stuff available for the rest of my scripts from the source of the other way to do that of course you can just forgot that of the word source and then if you can't find it obviously 1 Bell OK so now this is the 1st of the pose threats examples in our since this is a proestrus talk 1st anyone ability was executed query from your battery operated so there's a whole bunch of different ways you could probably do this in fact in real common library that I created for this client there were probably 6 or 7 different versions of this so exact sequel or the equal 1 but what I like to do is I like to make them flexible so I have a separate those caught database name posters uses the limited so that I can point to set essentially anywhere and and I'm gonna have this sequel strain is also going it passed as an argument and I've got this kind of standard way that I'm now going to call that's equal strength so this is this is that part of the that last part right I'm going to go through some explanation on these things the 1st thing here that you know some piping the sequel to the sequel rather than using Darcy and actually that goes back to the discussion I have
on the list with the palm
actually I think it was only 1 answer my my question but if you're using density that whole string of it's got multiple statements that are delimited by semicolons a whole string it's passed back to the back end and then if there's an error somewhere and it just halts whereas if you were trying to do something like that where you've got you know a like off the screen is a ball over so
the like this where you don't know in all of the January inserting something a began you're asserting a value committing then you're gonna do another row commit so long as you would expect that each 1 of those things would happen independently right because you've got wrapped but if you use and their city and there's an error so in this case I've got a primary key I don't end up with that 3rd commit ever happen whereas if you use reviews the piping again you'll see you do get both that's because each of those statements is being executed as an independent execution the back and right from the days when eyes the part of all part of the it it it's part of the that I would guess so because that would be the same thing as
basically feeding file physical so in in this particular case I'm actually setting up specifically on Aristotle believed to be on so it's not make a difference really here but if you want and this is 1 of the things considered you want your script to stop with an error if 1 of the statements in a multi statement string is errors outward you want to continue that's really decision you gotta make in this particular script said that I wanted to stop with an error of an errors this up my situate the idea quiet online couples only so basically that's going to give me back just the the data and not all the decoration around that that the sequel normally creates so that I could do something usually I wanna do something with that data I don't wanna just display and then the delimiter allows to specify specifically what the field separators gonna be in most cases I would just use a space but in some cases you might want you might wanna use something else an example that is used this sort of thing to run a query and build like an analyst but as for another sequel statement that I'm kind of building know 1 execute yet you can you can do but I don't know if I think later on I have example of it but in the end of it is actually what you can do is you can say a dollar sign of single-quote backslash to single over and that will specify that that's slashed you should be considered as an escape and of course this is that the normal connection info but I'm going to use 1 of the the yeah think thanks reminding that actually watery eyes as they said I had like 5 or 6 different versions of the same and the other common library that did 1 of them uses your arises it was added in PostgreSQL 9 2 9 3 so as a like 9 2 or 9 3 you can actually build the connection string it looks just like it would for JDBC centrally and you can pass that as as the connection string is set as having separate host port user in database name use avatars your eyes and you can pass it as 1 basically pass that is if it were the database that but I'll show that here I have an example here but I have done that the cases this is an example of now using that function but I'm gonna take it so in order to present on the slide ahead have economic low that ugly but of a set of posts the poor and by the way this is the way of of you know this but if you want to use the connection on your local machine using sockets so TCP IP we can basically specify the soccer directory as if it were the host so that doesn't have to be an IP address you need the for our and and I knew that I wouldn't go from playing with my machines they typically have post was set up to run and all different versions of the reports of what so on set up my my connection's string MI delimiter and that write queries basically looking for work connections are idle and transaction and now I can just simply say execs equal and get a result sorry
alarm that z figure after seeing the bad news is that the CEO of the form that I get the data back in is is relatively is and I got more examples of how it actually does get
used so this is another
version of this is more or less the same thing except this time going take of file name as an argument so it's pretty much exactly the same but this is useful if you need persistence for your sequel falsely there you wanna have that single file defined in advance so maybe you can keep version control I've used it for things like that that originally I actually want to add to his presentation another example about a script that would control access to a database which is specified a list of users who should be allowed and everyone else would get locked out and 1 of these I found when I was developing that scrapped was that if you try something like revoking connect access the database you can't that doesn't work but super user that we sit in on older versions of post of someone told me at some point the thought that the nature the old what I ended up doing is is basically for all of the logged users but I don't want to be a log I just alter those users and they turn them into groups essentially so now they can log anymore but because of that I have to generate a list of current users sequel statement from the list the current users that I wanted blocked out but I needed to know who those users were in order to unlock them later on and there there's always the possibility that a new user would get created or 1 of the existing users would get deleted in between when I locked and when mark and so I would build basically using all this dynamics equal stuff would build sequel statements by the amount to file and would execute the sequel statement using this version of of the function that was also by the way how I figured out that problem with the dash because I had a bunch of statements that were altering users and in this environment part of 1 of their operators ended up dropping some users so they would lock the system using the scrapped and then part of the upgrade drop the user somewhere along the line and then and then they we're trying to unlock and in that list of things that we're getting executed it was trying to unlock a user that no longer existed through an error we have people on what was what he had in this is a bit contrived because is just an example for this presentation but at another day as described there are cases where I was dynamically building seek what I wanted out file and I wanted that filed time stamp them all kinds of other stuff right so that yeah you definitely don't need that in this particular case but that's just to demonstrate that that's so as great OK archaic and I can run a query can get data back I'll actually assigned that 2 variables while if you got basically as a scalar value a single scalar value that's pretty straightforward again that this method of calling out basically executing another process the dollar sign friends and brand so what that does that executes this in another context just as if you'd use backticks so that kind of traditional way to do that was with backticks this is the more modern way backticks I think actually supposedly even deprecated and although much will ever really go away but what this will do is it will run that function with this query and then since there's just a single result it just gets assigned write to that variable and then you can occur without their works great what happens if you've got multiple rows and mobile so got multiple rows multiple columns then you can use this is something that's called a here string anyone ever heard of weaker string was people broader here docks but what this does is it it executes that's equal and assigns it to these 2 variables in the lab and so if I go out to
fair use you have 1st example just step back the answer but now I can actually interact with those 2 variables in rows and columns has an element under
the part where I'm going to talk about some managing functions that you're trying to use because it your building these scripts that are called sickle all times its you're better off if you can kind of wrap a bunch of the functionality you try do in the database inside of sequel function so you just calling basically select some simple function in order to do the work but if you do that you might end up as your maintaining both the function and the script they could get out of sync so what this function is going do this particular function just takes a schema name of founding a list of operates in and you 5 and it just tries to do well a look up in the system catalog to see if this particular function already exists and the M 5 matches which means the the source of the of the function matches and then executes step query so you may or may not be familiar with this the combination scheme the functioning of the archetypes is actually the function signature that so posters figures out which specific function you're trying to execute and then by taking the this PG get function f of the all idea that function feeding it and the 5 year essentially getting the signature on the actual source code of that function so that there's another another batch function that you need to support this is basically this is a function that's going to check that signature see if that exact match exists if array does exist it does nothing ever doesn't exist it does a crater replace to replace it in lines before so that before you use it you can ensure that the correct version of your function already exist so at the beginning of this thing is taking basically a defined the the function name to include the schema the function name or that the file name I should say that includes the scheme of the function name and dash and then they are types and this is the causal that out so these 3 things you just taken sequel farming and using cut to pull out pieces of it and then it 5 some of the actual sequel file and so the rest of this is going use that with the function we just talked about looking up for a match and so if it doesn't find a match just executes the file with the with the File Execution function that we talked about that's going to do a career replaced so now there is 1 more piece that make you would makes is easier to use if you're creating a function like this this is a trivial and again contrived but example but if you if you execute this to create a function and use that to get function that it actually cannot formats in a specific way a little bit nicer but if you're trying to match and and the 5 work so once you created the function the database have manually this script will take you will find that function and exported to the sequel file in a way that it will exactly match the M D 5 that comes from running 5 on the get function that output that make sense so now finally what you got all that in place you know you've got a script that's going to be using this function you specify what's what's the sequel file that I want to match against and images policy serious equal fun and it's going to do that check so if the function already exists in the the 5 matches it does not essentially but if it doesn't match it'll take that file simple founders do the crater replaced and now when I'm using that function I can be sure that the function exists and post president match the why expect your best this analysis some more general stuff that you know as you not specific the PostgreSQL of the examples you are using it would pose if you wanted you concur execution lock you there may be you know you may want that because you've got something that's gonna run for a long time user water resources you don't want to people manually starting up at the same time and end of work for a 3 maybe running our crime job it runs every 5 minutes and something happens and it gets they could get stacked up so you will have a way to lock the use of scripts only 1 time we can only run once said about essentially and some examples of that area know if you're doing a forced factory in more and this is actually alive example that that I had in the environment I was working in but it was kind of a mixed them 0 LTP and data that was coming from legacy systems and getting Boca loaded into the production systems and the people who were doing the data movement didn't wanna be bothered with running back injury thing like that after they've both loaded and much of many people you're familiar with this but when you bulk load data it's a good practice to run a vacuum on the table were vacuum analyze on the table 1 update your statistics and to also set all that and that's because otherwise the 1st time a rocket's red after it's been loaded this can be actual right there will go on that you may find it surprising so this function is going to make use of the Linux canonical F locked I set this up so that it can be blocking or non-blocking again I've got in the interest of time I think I'm gonna skip trying around it but I have got a scripts in that did repo that demonstrates the use of this thing so you can call it the the immediately exist if it can't get a lock or you can call to block the can get Pollock and then the other half of that is you might wanna unlocked so if you're doing some kind along operation you might wanna locks up locked for some period of time and then unlock explicitly so this is the function of the example function of calling it skinhead attempt the gravel locking up this no way is telling it basically not to block so it doesn't get right away in no way it's Cisco
fall action blocked this next thing you might wanna do some is parallel work and that you know course you doing something like that a again realize scenario we same environment work was clusters and they want to be able to do color snapshot back of a slowly cluster and a way to restore to some point in time for testing purposes and so big because not all the tables were all TPA only all LTP tables essentially participating in the replication of slowly the Olkiluoto tables role being loaded on all 3 sites independently so we need to be actually able to load tables at 3 different sites in some ways and a fairly large you want really do them all the same time you don't want do 1 site sit there and blocking your script involves done after an hour you wanna get all 3 of them that our so the example script and guy's going around 3 queries as separate background tasks batch actually has a weight commands of you launch 3 sub-processes that are asynchronous and then say wait bill sit there and wait for all 3 of them the French so it's kind of a nice way to do asynchronous parallel so this particular scrapped its basic out of times 5 seconds sleep and without a parallelism it would take 15 seconds but it's going to take about 5 seconds because it's going to of the 1st kind a simple method to do this is just the simply background the execution so you can do that right within your best and and that some process will background in his runs asynchronously and then the weights statement will sit there and wait until those 3 things that such a problem with that is that you can capture the results of that so if you wanted to capture the results this method doesn't basically put those processes up to your Standard out there so you don't get that result user would gather that innumerable the 1 that is another way to do it using cynical co-prime but co Proc has some bugs and I was going through the slides there is some research and it looks like the blogging coproduct is acknowledging has been there for at least several years and hasn't been fixed but what I found was that if I wanted only capture the output of these 3 executions I needed a 4th 1 which was kind of a dummy because whatever 1 was last never got hooked up to to the standard out and so you couldn't get that result so by having the 4th 1 here it's sorta works around that bargain cope Brock and let me read that result back into the buffer it also has an issue in that it it xt it outputs these warnings of that you're trying to do stuff in parallel which makes no sense because it actually works you can see that this thing executed in 5 seconds got all 3 results just like I expect that 1 of the ones that all the people of the and that's important safety tip I suppose if you're doing stuff on the same database that could be a there could be an issue that in most of the instances where I've done this sort of thing has been because of been trying to do something in parallel across multiple host but surely would be valid that you might be trying to do something in parallel on the same world with it again are so finally ends in of cleaning up in often in these scripts you're going to create some sort of files us temp files you may not well even laying around you there for security reasons adjusts cleanliness reasons but you might have a script that is doing things as you go along and then if there's an error you don't want to leave things in service partially executed states what below on a role some of the effects of what you've done and you can also use it and I have used it in fact reduce the scripts that were being used for a fairly lengthy of migration that was going on and because of the length of the migration and some issues on the network and the number of times that we're having to do it we're finding that occasionally the thing would bomb out because of a network issue written the script and we want to be it was something that would take hours and we wanted to build a just start right back up where we were and so you can use you can actually use a trap to to write out to file an indication of where you were in that scrapped so that when you gotta run at another time you restart it it just goes right to where you want to start at picture right back up so that the way to make it easier to do that actually create this function cleanup of what is going to do it evaluate the elements of an array this is so I can and does it in reverse order so mentoring backwards there that's so that as I'm using this thing I can basically stacked undue tasks onto a q essentially popping them on the top for push among the top and then popping them back off as the trap executes at the end so these examples here this and I'm going to set up sequel it truncates table T 1 and to create this element which is just the and the echo what I'm doing and I'm gonna use that executes equal function to execute that specific sequel understand that said that Israel railman 0 and then this sequels going to insert values in this table T 2 so the user is basically the the things I want do if this particular script errors out these this is what I want you to clean up and then finally once built that array with these 2 tasks I just set a trap trap clean up and say I wanna run that trapped on either city or error so error is is going to be you basically any time descriptors as again is going to be of someone word got impatient hit Ctrl-C worse so until the right so that the rest of descriptors for demonstration purposes gonna in certain values of the T T was the truncated to the show the count of the records in those tables and I've put in there the ability to have a thing sleep so they could have time to hit Ctrl-C and see the effect of the of the trap executing without 1 of them
so they can see that my trap executed I inserted back into the 2 and truncated T 1 and actually if I go to here
you can see that might have the chance to
use it he was back to the rows and T 2 is for some i trap successfully reset the table and this this
just show you what I just showed you basically energy letter complete successfully them throws don't get on model such that any questions on the the collection over but here is in the form of the course I agree again the double brackets is is the considered to be the more modern way to do the of test think there is a technical difference in the wake of sexually double brackets are actually built into bestial where is the old single brackets were because some symlink to the test function is that correct all of them you're right so you know that everything irony I read you seem to recommend that you use the double brackets now when you don't know what that by all and there is yeah there's some more functionality that comes with a lot of work that we use the ISO the old 1 the old style might be built in but it still compatible with the original semantic analysis of all take that under consideration the fact that uh that that's a good point and actually in the environment I working they had no official coding guidelines which said you should do that and it's it's a good idea I think but you know 1 thing is if you are building stuff in a library and then averages using those functions that's kind of getting abstracted away for them anyway so I I tend to be you are not a very good typist so I'm lazy when it comes to that so I can use the short arguments so you you you you insist on what was in the middle of the of of this so is part of what you have to use the whole dead in fact in in in this area where I was doing this week we had exactly that and all that stuff was getting pushed office Splunk so again you can definitely definitely do all of over you in the course of the work of the 3 quarters of the year all it the all the all of the so I I think we're actually couple minutes over so that any other questions please find me this between now and the related if