Our base for the week, the Beacon House campsite, a small certificated site listed by the Caravan & Camping Club and only ten minutes walk away from Flamborough village. Directly opposite the campsite is Dane's Dyke, a preserved section of ancient defensive earthworks. Originally over 4 miles in length and completely isolating the headland, this shorter stretch is now open for the public to walk, and leads down to a beautiful white cobbled beach.
Soon after arriving we took a walk to the village, and identified no less than four pubs and restaurants, plus two fish & chip shops! We tried out a couple of them during the week for evening meals. Firstly the Royal Dog and Duck where we had reasonable steaks, but worth noting they only take cash, unusually no card payments. Secondly the Seabirds restaurant, sensibly priced and a more contemporary menu.
Ten minutes drive away from Flamborough is the RSPB visitor centre at Bempton Cliffs. Grandstand views of maybe thousands of seabirds nesting on the steep white cliffs. We even managed to spot some puffins!
A couple of miles drive from Flamborough village takes you to the headland. We explored the area around the lighthouse, and then continued on to North Landing, used for various beach scenes in the recent 'Dad's Army' movie.
We drove to Filey on the Sunday, but we were unable to find anywhere within reasonable distance of the centre to get parked, so we abandoned the visit and went elsewhere. We made a second attempt later in the week, but found it almost as difficult to park as at the weekend. There appeared to be very little to explore in Filey, which seems geared up to beach holidays, so our visit was rather a short and disappointing one.
Beverley, in contrast, is a very pretty market town. Lots to see, all within easy walking distance of the Saturday Market (just the name of the market place – it's there every day!). We returned to Beverley one evening later in the week, for a lovely meal at the Thai Palace restaurant which looks directly on to the market cross.
We always enjoy looking around model villages whenever we find them, and halfway between Flamborough and Bridlington is the Bondville Model Village. Cheap admission, and a pleasant way of whiling away an hour or so.
Bridlington Old Town is about a mile away from the modern centre on the coast, and we enjoyed exploring it in some detail making use of a trail leaflet from the local tourist information office. The High Street was also used as a setting for the Dad's Army movie. When we visited, the Priory Church was featuring a very moving exhibition by the British Legion to commemorate the centenary of the 1918 armistice. Card silhouettes of soldiers filled the pews of the church, with each one bearing the name of a soldier from the town's memorial list also found at the church.
Hull is an unusual place. Lots of new shopping and trendy bars which I'm sure would appeal to a slightly younger audience. A small museum quarter to explore in the old town area. A pleasant enough diversion for a few hours, but not somewhere that captivated our attentions.
Bridlington itself is a lovely seaside resort, with plenty to enjoy for young and old alike. We visited a few times during the week, exploring the 'new' part of town, beach promenade, harbour area and nearby shops.
Sewerby Hall & Gardens is nearby between Bridlington and Flamborough, with amongst other things a beautiful walled garden and rose garden to explore.
There's something very special about British seaside holidays – that first glimpse of the sea, walking barefoot on the sand, the sound of seagulls, fish & chips, ice creams and souvenir shops. The Flamborough coast gave us all and more!
Sometimes life is about seeing new places. Sometimes it's about stepping back and remembering where you've been. My photo diary brings both of these together for me.
Enjoyed your tour of the Flamborough area Stuart. I've been to Flamborough and Bempton but it was a long time ago. I don't know Filey at all but interestingly two people I know both have second homes there and seem to adore the town. I've visited Whitby and Scarborough a bit further north but not Bridlington. I liked the sound of Beverley but haven't been and only to Hull years ago to catch a ferry!
Thanks for the comments Marion. If you should ever visit Bridlington, be sure to take in the old town as well as the seaside bit!


Suv Citroen C3. 2018 citroen c3 aircross compact suv will be launched in europe in second half 2017 then rolled. new citroen c3 aircross suv previewed by concept carbuyer. citroen c3 c aircross concept previews new compact suv performancedrive. citroen c3 aircross will lieber suv als van sein modell kommt im herbst. the new citroen c3 aircross suv takes a bow. 2018 citroen c3 aircross unique suv body styling dzgn design and technology magazine. citroen c3 aircross mini suv unveiled. citroen c3 aircross suv compatto tutti i dettagli foto e video citro n italia. citroen c3 aircross preview french suv we buy any car blog. new citroen c3 xr small suv wears its production outfit. [Revistarms.com].


text:
Joseph A. Ferraro, Jr.
d. October 28, 2011
Joseph A. Ferraro, Jr. of Seyler Terrace, Glasco died Friday, October 28, 2011 at Golden Hill Health Care Facility. He was 83. He was born in Glasco, a son of the late Joseph and Maria Martino Ferraro. Joe served in the US Army during the Korean Conflict. In his younger years Joe worked for both the Washburn and Staples Brickyards. He then worked at I.B.M., Kingston for 30 years. Joe retired in 1987 and belonged to the Quarter Century Club. A member of the Saugerties American Legion, he was an exempt member of the Glasco Fire Company. Beloved husband of Ida Zanni Ferraro who died October 16, 2006, loving father of Maria Riccio and her husband John of Glasco, grandfather of Nicholas and Joseph Riccio, uncle to many nieces and nephews. The youngest of 11, he was predeceased by four brothers Louis "Pee Wee", James "Butzie", Charles and Arthur Ferraro and six sisters Lillian Barilla, Catherine Nardi, Margie Secreto, Rose Tiano, Alvay Cafaldo and Ida Scorzo. Reposing at the Simpson - Gaus Funeral Home, 411 Albany Ave. on Monday from 3:00 - 6:00 PM and Tuesday from 2:00 - 4:00 and 7:00 - 9:00 PM. The funeral procession will form on Wednesday at 9:00 AM from the funeral home. A Funeral Mass will be celebrated at St. Joseph's Church, Glasco at 10;00 AM. Interment will follow in St. Mary of the Snow Cemetery. Memorial contributions may be made to "District 11, Ida Z. Ferraro, RN Nursing Scholarship", c/o Mrs. Dolores Brink, RN, 70 Brink Rd., Saugerties, NY 12477 or "Golden Hill Activities Fund", 99 Golden Hill Dr., Kingston, NY 12401.
To order memorial trees or send flowers to the family in memory of Joseph A. Ferraro, Jr., please visit our flower store.

redpajama_set_name: RedPajamaCommonCrawl


text:
La Fédération de football d'Allemagne du Sud (en Allemand: Süddeutscher Fußball-Verband (ou la SFV) est une fédération régionale de football membre de la DFB.

La SFV couvre un très grand territoire comprenant le Bade-Wurtemberg, la Bavière et la Hesse.

Elle regroupe un petit moins de dix mille clubs pour un total de plus de 3 millions d'affiliés.

En termes de palmarès national et international, la SFV est une des fédérations régionales les plus puissantes.

Histoire

La fondation de la VSFV est entérinée le  dans le restaurant Zum Landsknecht, à Karlsruhe. Les huit membres fondateurs étaient:
 Le Karlsruher Fußball-Verein, représenté par Richard Drach
 Le Fußball-Klub Pforzheim, représenté par Emil Meid
 Le FC Fidelitas Karlsruhe, représenté par E. Dietz
 Le Fußballklub Heilbronn, représenté par A. Meyer
 Le FC Phönix Karlsruhe, représenté par Arthur Beier
 Le Hanauer Fußball-Klub 1893, représenté par W. Guckemus
 Le Mannheimer Fußballgesellschaft 1896, représenté par S. Seiler
 Le Frankfurter FC Germania, représenté par Fritz Seidenfaden
Aucun président n'hémanera de cette assemblée; d'abord, un comité, dirigé dans un premier temps par Richard Drach, puis par Fritz Seidenfaden. Lors de la première journée du football sud-allemand, à Pâques 1898, le président du KFV Friedrich Wilhelm Nohe est élu premier président de la VSFV, et occupera ce poste jusqu'en 1907.

Le développement du football dans les années 1890 en Allemagne du Sud se fait de manière particulièrement lente. En dehors de l'ancien bastion de Karlsruhe, il n'existait que peu d'associations, il n'y avait aucun championnats locaux, et les équipes ne se rencontraient que lors de matchs amicaux. C'est lors de la saison 1897-1898 que la VSFV organise le premier championnat d'Allemagne du Sud. Le premier club à être sacré champion est le Freiburger FC 1897, qui bat en finale le Karlsruher FV, lors d'un match joué à Strasbourg le , sur le score de 2-0.

Il a fallu attendre la saison 1903-1904 pour que la Ligue organise un championnat de poules dans son aire de fonctionnement, qui a été divisée en districts à cet effet. Le District du Nord comprenait la région de l'Ouest du Main (Frankfurt/Wiesbaden et leurs environs), la région de l'Est du Main (Hanau, Offenbach, Darmstadt, Aschaffenburg et leurs environs), et le Palatinat (Mannheim, Heidelberg et leurs environs). Le District du Sud étaient partagées entre les régions du Bade-moyen (Karlsruhe et ses environs), du Rhin-Supérieur (Fribourg, Strasbourg, Mulhouse, et leurs environs) et le pays souabe (Stuttgart et ses environs). Les championnats se faisaient, en fonction du nombre d'équipes disponibles, en deux ou trois séries. En Bavière, il n'y avait pas de championnat organisé jusqu'à la saison 1904-1905 où une division a été créée, et fut intégrée au District du Sud.

Durant les premières années du , le développement du football en Allemagne du sud s'accélère.

Le , la VSVF était représentée lors de la assemblée constitutive de la Deutscher Fussball-Bund (DFB) à Leipzig. La "VSFV" entra vite en conflit avec la DFB quant au jeu et à son organisation. La fédération régionale du Sud se montra très vite un organisme influent.

Le , la fédération régionale changea son nom en Süddeutscher Fußball-Verband (SFV).

Après la Première Guerre mondiale, les clubs alsaciens qui lui étaient affiliés participent pour la plupart à la Division d'Honneur organisée par la Ligue d'Alsace de football. Il s'agit notamment du FC Mulhouse, et de l'AS Strasbourg.

Le , la "SFV " fusionna avec la "Süddeutschen Verband für Leichtathletik" et prit le nom de Süddeutscher Fußball-und Leichtathletik-Verband (SFLV).

Membres fondateurs
 Karlsruher FV
 1. FC Pforzheim
 FC Fidelitas Karlsruhe
 Fußballklub Heilbronn
 Karlsruher FC Phönix
 Hanauer Fußball-Klub 1893
 Mannheimer Fußball-Gesellschaft 1896
 Frankfurter FC Germania 1894

Subdivision de la SFV après 1919
Lors de la première réunion faisant suite à la Première Guerre mondiale, les 30 et , à Heilbronn, la « SFV » réorganisa sa structuration en quatre groupes de neuf districts.

 Nord-Gruppe (« Mittelmain-Kreis », « Westmain-Kreis »)
 Ost-Gruppe (« Kreis Südbayern », « Kreis Nordbayern »)
 Süd-Gruppe (« Kreis Schwaben », « Kreis Baden »)
 West-Gruppe (« Neckar-Kreis », « Rhein-Kreis »)

Comme le Palatinat était occupé par les troupes françaises, il fut décidé, pour faciliter les déplacements de partager le « Rhein-Kreis » en deux districts le « Odenwaldkreis » et le « Pfalzkreis ».

Les dix champions de districts (« Kreismeister ») disputaient un tour final pour désigner le Champion d'Allemagne du Sud. Celui-ci participait à la phase finale du championnat national.

Championnat d'Allemagne du Sud
De 1898 à 1933, la VSFB/SFV organise son propre championnat. Le Champion d'Allemagne du Sud participe au tour final national (à partir de 1925, le vice-champion est aussi qualifié).

Palmarès du Championnat d'Allemagne du Sud
 Verbandes Süddeutscher Fußball-Vereine

 Süddeutschen Fußball-Verbandes

Champions régionaux
Les équipes en lettres grasses furent Champion d'Allemagne du Sud l'année concernée.

1907 à 1919

1920 à 1923

1924 à 1927

1928 à 1933

Dissoute de 1933 à 1949
Le , la fédération régionale fut dissoute. Elle ne reprit ses activités que les , quelques mois après la constitution de la République fédérale et la restauration de la DFB.

Ligues

Contrairement à d'autres fédérations régionales, de nos jours, la SFV n'a plus une ligue supérieure unique (de niveau 5) Mais si de nombreux clubs de la SF V participent à la Regionnalliga Süd.

Clubs phares
Parmi les clubs les plus réputés et les plus titrés de la FRVS, citons:
 FC Bayern München
 1. FC Nürnberg
 Eintracht Frankfurt
 VfB Stuttgart
 Karlsruher SC

Organisation mère
Cette fédération chapeaute cinq autres fédérations régionales ou locales:
 Hessischer Fußball-Verband (HFV)
 Badischer Fußballverband (BFV)
 Südbadischer Fußball-Verband (SBFV)
 Württembergischer Fußball-Verband (WFV)
 Bayerischer Fußball-Verband (BFV)

Articles connexes
 Fédération allemande de football
 Histoire du football allemand

Les autres fédérations régionales
 Fédération de football d'Allemagne du Nord
 Fédération de football et d'athlétisme d'Allemagne occidentale
 Fédération régionale de football du Sud-Ouest de l'Allemagne
 Fédération de football d'Allemagne du Nord-Est

Notes et références

 Hardy Grüne, Enzyklopädie des deutschen Ligafußball. Vom Kronprinzen bis zur Bundesliga, Agon Sportverlag, Kassel 1996, .
 100 Jahre Süddeutscher Fußball-Verband (Festschrift), Vindelica-Verlag, Gersthofen 1997, sans ISBN.

Liens externes
  Website officiel de la Süddeutscher Fussball-Verband
  Site de la Fédération allemande de football
  Archives des ligues allemandes depuis 1903
  Base de données du football allemand

Football à Munich
Organisme fondé en 1897
Football en Hesse

redpajama_set_name: RedPajamaWikipedia


text:
10 ways to learn more about open source software and trends
Open source trends should be on any IT leader's radar screen. Check out these reports, events, courses, and more
By Carla Rudder | September 06, 2018
When Forrester released its 2016 report "Open Source Powers Enterprise Digital Transformation," some people in the open source community were surprised by the results. They weren't surprised that 41 percent of enterprise decision makers called open source a high priority and planned to increase use of open source in their organizations. They were concerned that the other 59 percent didn't seem to understand the role open source would play in the future of the enterprise.
Paul Miller, one of the analysts behind the report, wrote, "The myth that open source software is exclusively written by and for lonely – rather odd – individual geeks remains remarkably prevalent. And yet it's a myth that is almost entirely wrong. Again and again, we encounter executives who do not grasp how much their organization already depends on open source. More importantly, they do not see the key role that open source technologies and thinking will play in enabling their efforts to transform into a customer-obsessed business that really can win, serve, and retain customers."
Fast-forward to today, and open source skills are among the most in-demand: 83 percent of hiring managers surveyed for the 2018 Open Source Jobs report said hiring open source talent was a priority this year, up from 76 percent last year. (More on that report in a minute.) Hiring managers are touting their organization's contribution to open source projects as a recruiting strategy for nabbing top talent. Some of the biggest trends in enterprise IT, such as containers and hybrid cloud, rely on open source technologies including Linux and Kubernetes.
The mindset and narrative around open source have changed. Enterprise IT and business leaders should be able to keep up with IT organizations doing innovative work with open source technologies. We've rounded up some resources to help you get up to speed – and stay there.
[ How is open source fueling breakthroughs in fields ranging from medicine to art? Watch talks and films in Red Hat's Open Source Stories. ]
What Every CIO Must Know About Open-Source Software – If you are starting off with limited knowledge, this might be a good jumping off point for your open source education. This 2017 report from Gartner answers the basic questions around open source technology before diving into more complex CIO questions, like what are the risks, and how to tap into open source's benefits.
The BOSS Index: Tracking the Explosive Growth of Open-Source Software – The landscape of open source technologies is vast – and made up of some strange-sounding names. That's why Battery Ventures created this detailed index to categorize and track some of the most popular open source software projects. Review this list to be versed in the top players and names to know in the world of open source.
Open Source Jobs Report - This 2018 report, conducted by The Linux Foundation and careers site Dice, gives you a clear idea of how enterprise IT is using open source talent, as well as which skills are in highest demand. (Hint: Think containers and cloud.) The report offers valuable background for both hiring managers and job seekers.
Open Source Leadership Summit – This annual Linux Foundation event is geared toward leaders responsible for driving open source strategies and implementation within their organizations. Although the 2018 event already has taken place, you can browse the keynotes for sessions on Kubernetes, blockchain, security, AI, and more, to get a good idea of how other leaders are thinking about open source.
All Things Open – Taking place October 21-23 in Raleigh, NC, All Things Open features 200 sessions, 14 workshops, and conference tracks for on topics including cloud, blockchain, big data, and more. With a mission to help attendees become better at what they do, this conference prides itself on the educational and ROI value of its open source content.
The Architect's Newsletter – Newsletters are a great way to get a steady stream of timely insights and industry news. The InfoQ Architects' Newsletter, a monthly guide for software architects and IT leaders, features a curated collection of links, commentary, news, and case studies. Recent issues have explored chaos engineering and building resilient distributed systems.
Opensource.com – Our companion site, Opensource.com, sends a weekly newsletter highlighting stories from practitioners, experts, and enthusiasts that can help you get a pulse on interesting projects and trends in the world of open source. The site also features an extensive resource library, including cheat sheets on open source technologies and guides on open source alternatives to popular proprietary solutions.
Other ways to learn:
The Changelog – Changelog, another newsletter option for developers, also offers a few podcasts for people who prefer to learn on their morning commute. The Changelog podcast features conversations with leaders, engineers, and innovators in software development. The latest episode highlights the Ballerina programming language for microservices.
How Arduino is open-sourcing imagination – If you are looking for a little inspiration, Massimo Banzi, co-founder of Arduino, has a great TED Talk on the "maker's movement." His point of view: Open source technology is enabling anyone, anywhere to make anything they can imagine. This talk might spark a few ideas for your next hackathon.
Fundamentals of Professional Open Source Management – Finally, if you are ready to roll up your sleeves and get started, The Linux Foundation offers a course overviewing the key phases of developing on open source management program. The course tackles one of the biggest challenges – getting business executives, legal, development and other key stakeholders on the same page.
[ Want to learn more about the past, present, and future of open source? Check out Red Hat's podcast, Command Line Heroes: Catch Season 1 and get a sneak peek at Season 2. ]
Submitted by Patrick Masson (not verified) | September 7, 2018
Thank you for the article. Finding reputable resources can be difficult, and this collection is a great starting point for IT leaders seeking more information about open source software, development and communities, as well as development/technical staff who may need references to advocate for adoption back in the office to leadership.
To round out your references, I'd also recommend IT leaders and advocates familiarize themselves--and partner with--organizations working to promote open source awareness, adoption and development. Joining and supporting free and open source software organizations lifts all boats:
- Engaged businesses gain insights on development and technologies in the works (they can even help to influence such development), they learn best practices, for creating code and community, they may find consultants (even employees) among the dedicated contributors, etc.
- Open source software projects gain industry insights, development and financial support, and most importantly industry acceptance/credibility as more companies, government agencies, technical associations come on board to collaborate and co-create.
- The open source communities of practice gain leadership experience and input from IT leaders working directly with--and relying on-- open source software to deliver value. The organizations gain increased recognition and authority as valued resources through active partnerships with businesses (and other organizations, e.g. government agencies, technical standards bodies, non-profit foundations, etc.).
A few organizations that support free and open source software generally, that IT leaders may want to consider supporting include:
Apache Foundation (apache.org)
Debian (debian.org)
FreeBSD Foundation (freebsdfoundation.org)
Free Software Foundation (fsf.org)
Linux Foundation (linuxfoundation.org)
Mozilla Foundation (mozilla.org)
Open Source Initiative (opensource.org)
Software Freedom Conservancy (sfconservancy.org)
Also, the Open Source Initiative provides a list of organizations (many software specific) at https://opensource.org/affiliates/list Depending on the business, many of these organizations may be providing open source software and resources that directly benefit the company, for example, The Python Software Foundation (python.org).
I would also highly recommend engaging with software communities that develop/support any open source software the business may actually be using/depending on. As business benefits from the use of open source software, I would hope that they choose to re-invest back in the communities that enabled their success.
Thank you again for your good work here,
Patrick Masson
Open Source Initiative


text:
Q: Request for member not a structure or union i got a prob when i tried to set webview property on uiviewcontroller.
here the code:
UIWebView:
@interface mainView : UIWebView {
    int currentPage;
}
@property int currentPage;

and i synthesize on the implementation
UIViewController
(void)loadView {
    webview = [[mainView alloc]init];
    webview.currentPage = 2; // error -> Request for member "currentPage' in something not a structure or union
    self.view=webview;
    [webview release];
}

why i am unable to set the currentPage property?
Anyone know the solution so tat i can set currentPage on UIViewController?
Thanks.

A: Is webview an instance of mainView (incidentally, class names should begin with a capital letter, so it should be MainView), or is it an instance of UIWebView. It looks like you have forgotten to declare webview as the correct class type, as the compiler isn't recognising that it has a property called currentPage.

redpajama_set_name: RedPajamaStackExchange


Did you know your sleep style takes on a personality? Even if you are sleep-deprived, what you do in the hours before bedtime, whether you smoke or drink alcohol, even how much you weigh can all affect how much and how well you sleep.
Power down before bedtime. It can be hard to resist the temptation to check your email one last time. "Computer screens emit a bright light that signals the brain to wake itself up," says Michael Decker, PhD, spokesman for the American Academy of Sleep Medicine. So stop any computer work, emails, and other screen activities at least an hour before bed.
Limit naps. "Naps and sleeping a little longer can help you catch up on the weekend, but that still leaves you sleepy throughout the week," says Russell Rosenberg, PhD, chairman of the National Sleep Foundation.
"These are people trying to cope with very high demands in their life," Rosenberg says. They tend to work the longest hours (often on night or rotating shifts) and get the least sleep.
Stop smoking. Nicotine is a stimulant, notes Decker. It promotes inflammation in the back of the throat, which can lead to snoring or sleep apnea. Sleep apnea, lapses in breathing during sleep, is harmful itself and can lead to insomnia and other health problems.
Lose extra weight. Here's another reason to shed extra pounds:Lack of sleep and obesity can go together. Being sleep deprived can affect your metabolism, and obesity can give you sleep apnea, a cause of insomnia. Working on your weight can pay off with your sleep, Rosenberg says.
Get help for chronic insomnia. If you have difficulty falling or staying asleep three nights a week or more, and that persists even after you change your sleep habits, see your doctor.
These two types of sleepers are least likely to have sleep problems and most likely to get enough -- or more than enough -- sleep. They rarely or never feel tired. If you're a lively lark, you're probably a young, early riser and don't have any medical conditions. If you're a savvy senior, you may be retired, get up later than average, and supplement nighttime sleep with naps.
To keep up the good work, don't take sleep for granted.Keep up good sleep habits, especially as you age. "When you're younger, you may be able to have two pots of coffee in the afternoon and sleep fine, but abuse of stimulants can catch up with you and cause problems later," Rosenberg says.
Michael Decker, PhD, D.ABSM, spokesman, American Academy of Sleep Medicine.


This stunning home is situated in a prime area. Loads of updates and all the modern conveniences lets you just move in. Three bedrooms, three bathrooms over 2300 sq ft two car garage, pool/spa home. Enjoy the sunsets over looking the lake view. If you like to entertain you have plenty of space on the large lanai. Within minutes to Sanibel Island, Fort Myers Beach. Home is sold turnkey. Don't miss this gorgeous home.


Search Results - Found 77 results for luxury.
5 Star Durban is a glossy print tourism magazine & online community promoting the beautiful city of Durban & surrounding KZN to both local and foreign tourists alike, highlighting the best in luxury and quality that "South Africa's Playground" has to offer.
"A Humorous Blog About People Who Take Themselves Too Seriously!"
Combining fashion with functionality our range of leather changing bags have been designed to be practical and stylish making each baby changing bag easy to wear dressed up or casual. The best part is, by simply removing the baby insert our changing bags easily convert to regular leather handbags suitable for any occasion.
Bamboo sheets online offer better, healthier products for your home, that have a low impact on the environment. We have selected bamboo fiber sheets with superior quality & comfort from manufacturers that value your investment. Just let us know how we are doing.
Discover luxury is having alliance with world's finest five star hotels. With the best available rates, excellent customer service and excellent hotel recommendations, Discover Luxury is the web's best choice for online luxury hotel bookings.
British Virgin Islands Charter. Experience the ultimate luxury vacation onboard a private crewed yacht charter. What ever type of charter Caribbean you are after we can accommodate you.
Barrington Hall Yacht Charters is a premier luxury yacht charter broker. We focus our attention on the elite whose mind set that demands the very best in luxury while on board a crewed yacht.
Weblog about Cape Town accommodation and lifestyle.
Deluxe car hire is a great company in the field of car rental London.They can arrange you any car according to your specific need for four vacation or any special event.
Varied blog articles including biographies of people from the world of business, sport and film, reviews of luxury products from fast cars to world-renowned restaurants, plus articles on aspects of the online casino industry.
Discover why Crieff Hydro is Scotland's leading leisure hotel, with 60 indoor and outdoor activities, 5 places to eat, and inclusive childcare.
Cupidspeaks.com is a hip and happening website for the youth that delivers celebrity gossip and youth gossip. It is a youth platform for the young where they can voice their opinions. Cupidspeaks.com has news and views by the youth.
"Dixie Stark is a Seattle based interior designer who enjoys blogging for the design curious and style-savvy reader. She always brings a unique perspective mixing her Southern sophistication and her Pacific Northwest sensibilities."


text:
The Dormant Underground Bagel Brunch Reappears With A New Pop-Up
By Jean Trinh
Published Feb 5, 2015 11:00 PM
Belle's Bagels (Photo via Instagram)
When we attended Belle's Bagel's first underground bagel brunch last year, we knew the guys behind the bready goodness were onto something with their handmade, high-quality bagels and delicious sandwich creations. At the event, which was held in the backyard of the owner's home in Eagle Rock, they had bagels made with Moroccan spice blends and a killer breakfast sandwich with bacon, fine herbes salsa verde, eggs and sheep's milk feta. It's been a little quiet since then on the underground brunches front, so it's nice to see that they're progressing along nicely with some pop-up events in Highland Park starting this weekend.
Eater LA reported that Belle's Bagels, which is now sharing part of the La Perla Bakery's space, will start selling their bagels (with variations between plain and sesame to poppy seed and everything, with cream cheese and possible lox toppings) as part of a pop-up shop there starting this Sunday at 9 a.m., and continue to do so on Mondays, Wednesdays and Fridays from 8 a.m. to 10 a.m., and Sundays from 9 a.m. to noon. It'll be a much more permanent thing on Feb. 15 when the Belle's Bagels owners, Nick Schreiber and J.D. Rocchio, will actually have a dedicated space and counter in La Perla Bakery so they can spread the love of their bagels on a regular basis.
It's a labor of love for the guys, who have been posting mouth-watering photos on their Instagram of their delectable creations and double-dipped bagels being handmade by Schreiber. They even put their signage up in the bakery earlier this week:
A post shared by Belle's Bagels (@bellesbagels)
Belle's Bagels pop-up shop starts this Sunday and is located inside of La Perla Bakery at 6645 N Figueroa St., Highland Park, (323) 208-9408


MARY Kay Beard was once one of the F.B.I's most wanted fugitives, for crimes including cracking safes and armed robberies of banks. The Mafia had also put a contract on her life as she'd ripped them off in a diamond heist.
In 1972 at the age of 27, Mary was sentenced to 21 years in prison. And during five months in solitary confinement she began to remember bible scriptures she'd learned as a child in Sunday school, and she began to attend a Sunday school class in Tutwiler prison in Alabama at 7 Am. It was the only time she was allowed out of her cell.
That scripture was a wake up call for Mary and she returned to the faith of her childhood.
Mary hadn't started out in life bad. She was one of nine children, growing up on a farm with a godly mother and an abusive alcoholic father, so she saw her early life as being a bit schizophrenic. Her mother was taking her and her brothers and sisters to church, but her fathers influence was bad and Mary was very bitter and angry and felt resentment towards him.
Mary graduated from high school at the age of 15, and completed training to be a nurse at 18. Then her life took a bizarre and unexpected turn when she met Paul on a blind date, fell head over heels in love, and married Paul nine days later.
Paul was a music producer, which was fairly respectable, but he was also a bank robber, a master safe-cracker and a gambling addict.
Mary had been married before, but it had only lasted a short time and had ended in divorce. Mary had two children from this first marriage.
Her second marriage to Paul though had brought her into a completely different world. Within a short time she was assisting Paul in his life of crime. First in minor gambling cheats, then safe-cracking, and then in armed robberies of banks. And at one point she even staged a prison break to free Paul.
Paul left Mary though when she was hospitalized with an operable cancer tumour, and Mary felt very hurt, bitter and angry about this and she teamed up with a couple of Pauls old partners in crime, and continued committing serious crimes which led to her being hunted by the F.B.I, who eventually arrested her. She was charged with 11 federal and 35 state counts of grand larceny and armed robbery.
Mary was surprisingly paroled after serving just six years of her 21 year sentence. And because of her success with educational classes in the prison, she won a scholarship to Auburn university and gained a BA and a Masters degree in counselling.
In 1982 Mary was recruited by Chuck Colson, who'd set up the ministry Prison Fellowship and she was asked to set up a Christmas project for inmates. In the six Christmases she'd been behind bars, she'd seen that when the women inmates had been given small gifts of things like toiletries by visiting Christians, the inmates would then pass these small gifts to their children. These women ranged from shoplifters, to prostitutes, to murderers, but they all still had a heart and love for their children, and they would give their children the only presents they could.
So Mary was then inspired to set up the Christian charity Angel Tree. This meant that people could buy presents for the inmates children, so that they would receive presents from their incarcerated parents on Christmas Day. And they were presents the children wanted and were bought from the children's wish list. The whole aim was to make the children feel loved by their parents at Christmas. And from the Christian point of view it helped the children and parents feel the love of Christ during the Christmas period.
The first year that Angel Tree was set up, it was piloted in just one state, and 556 children received gifts that year. The following year it expanded to 12 states and by 2012, 364,198 children had received gifts from Angel Tree in the USA, but also due to Angel Tree spreading globally, more than 6.3 Million children around the world have now received Christmas gifts through the charity.
Mary met a former prisoner, Don Beard, and married him on January 29th, 1984, exchanging vows in a chapel at Tutwiler prison, where she'd previously been locked up.
Mary and Don also founded several other ministries, then Don died in 2006, and Mary died in April 2016. Her legacy though continues. Angel Tree is still thriving and serving inmates children around the world, helping them feel loved by their parents, and helping them feel loved by the saviour Christ.


Brighu Lake is a high altitude lake situated in the district Kullu of the Indian state of Himachal Pradesh. It is about 4235 m above sea level and is close to habitation, yet secluded with surrounding greenery. It lies to the east of Rohtang Pass and the nearest village is Gulaba, which is 6 km away. The lake is visited regularly by people and is held sacred to the sage Brighu, a great Indian saint, one of the Saptarshis and the father of Vedic astrology. He is said to have meditated near the lake while writing Brighu Samhita.
This lake is a perfect weekend getaway for treks with the families. In the summer, the lake is a bright, saturated, forget- me- blue color. During the winter, the lake is completely covered with snow. On a clear day, one can catch glimpses of Pir Pinjal and Dhauladhar ranges, and also of Indrasen, Deo Tibba, and Hanuman Tibba.
While trekking, the lake is usually enveloped with fog, so it's best to hire a guide while exploring the area as it can be difficult to find the trail.


text:
Fallen Angels by Gunnar Staalsen – Book Review
When Bergen PI Varg Veum finds himself at the funeral of a former
classmate on a sleet-grey December afternoon, he's unexpectedly reunited with his old friend Jakob – guitarist of the once-famous 1960s rock band The Harpers – and his estranged wife, Rebecca, Veum's first love.
Their rekindled friendship is thrown into jeopardy by the discovery of a horrific murder, and Veum is forced to dig deep into his own adolescence and his darkest memories, to find a motive … and a killer. Tense, vivid and deeply unsettling, Fallen Angels is the spellbinding, award-winning thriller that secured Gunnar Staalesen's reputation as one of the world's foremost crime writers.
Varg Veum is a PI, attending the funeral of a friend, memories of the past are recalled.
There is a murder to solve in the present day, but Varg's past keeps coming to the fore.
This is a tale of Varg's past, his friendships, love and secrets that have made him the person he is now.
There is an underlying feeling of tension which gives this an unsettling edge as we peer into the darker side of human behaviour.
At times quite harrowing, this emotion packed thriller is a look into the dark underbelly of society, those that live in it and the effect this has on those who deal with the aftermath. Both brutal and melancholy, this dark thriller is utterly compelling.
Thank you to Random Things Tours for the opportunity to be part of this blog tour, for the promotional material and an eARC of Fallen Angels.
Granite Noir fest 2017. Gunnar Staalesen.
One of the fathers of Nordic Noir, Gunnar Staalesen was born in
Bergen, Norway, in 1947. He made his debut at the age of twenty-two with Seasons of Innocence and in 1977 he published the first book in the Varg Veum series. He is the author of over twenty titles, which have been published in twenty-four countries and sold over four million copies. Twelve film adaptations of his Varg Veum crime novels have appeared since 2007, starring the popular Norwegian actor Trond Espen Seim. Staalesen has won three Golden Pistols (including the Prize of Honour) and Where Roses Never Die won the 2017 Petrona Award for Nordic Crime Fiction, and Big Sister was shortlisted in 2019. He lives with his wife in Bergen.
Fallen Angels, Gunnar Staalesen
One response to "Fallen Angels by Gunnar Staalsen – Book Review"
Thanks for supporting the blog tour Lesley x


You know the feeling of the morning phone call, "I'm sick and won't be in today". From the receptionist who won't be answering the phone, to the driver that won't be making deliveries, to the supervisor on a job site, their absence just changed your day!
Profitable business health starts with healthy employees and their families. As an employer, you are well aware that your employees' health can have a major impact on your business' profits and losses.
With 4 convenient locations and over 35 years experience in health and life insurance, Mid-Florida Agencies can help you improve the health of your employees and business.
1. Meet with a Mid-Florida Agencies' expert representative to learn your options.
2. We'll create a proposal to offer a group healthcare plan to your employees.
3. We'll explain the available employer contribution options.
4. If you have a plan, let us review and compare it to see if we can offer better coverage and lower premiums to you and/or your employees.
5. If you do not want to offer a plan, but would like your employees to receive better and affordable healthcare, we can provide a presentation on individual health plans either in a group session or one-to-one.
We are your area agent for Florida Blue – Blue Cross/Blue Shield. Mid-Florida Agencies' professional are located in The Villages, Lady Lake, Eustis and Apopka. We are members of the Chambers of Commerce in Lady Lake, Sumter County, Lake Eustis, Mt. Dora, Taveres, and Apopka.


text:
Gaffe Machine Biden
Sanders: 'I Don't Like This Deportation Thing At All,' Trump Going to Do 'Worse Things'
Sunday on CBS's "Face The Nation," Sen. Bernie Sanders (I-VT) said President Donald Trump's plan for ICE raids and deportations was a "beginning to do worse things to come."
Partial transcript as follows:
SEN. SANDERS: Yeah. But this is a president who also tweeted out last week that he is prepared, I think, to round up millions, was that the word, millions of undocumented people. And that is so horrific and so un-American that it is unacceptable, and I will do everything I can to stop that. Look you've got some 11 million undocumented people in this country. Our job is to pass comprehensive immigration reform and a path toward citizenship. Our job is to give immediate legal status to what Trump took away. And that is the DACA program that protects one point eight million young people.
MARGARET BRENNAN: Both of those ideas have gone nowhere in past administrations.
SEN. SANDERS: Well, now that's not true. DACA was implemented by Obama .
MARGARET BRENNAN: But not legislatively.
SEN. SANDERS: Not legislatively but you have- the president should be able to do that. And I think–
MARGARET BRENNAN: But you need a Democratic controlled Senate and House to be able to do that.
SEN. SANDERS: Not necessarily. I think there are- the answer is that would be very helpful, yes. I agree. But I also think that's what the American people want. The American people do not believe that America is about rounding up men, rounding up millions of people throwing them out of this country. How ugly is that. That's not what the American people want. They do want comprehensive immigration reform and a president that would provide that support could get Republican leadership on that as well.
MARGARET BRENNAN: But specifically on this point the two thousand that are supposed to be targeted haven't shown up for a court date so essentially they're- they're not following the asylum process. The legal standards when they're here. So should they be prosecuted should they be deported?
SEN. SANDERS: I don't- I don't like this deportation thing at all and I think Trump uses this as a beginning to do worse things to come. Once again. We need also a humane policy at the border for people seeking asylum. We need a lot more judges down there and administrative staff as well. So you've got a real problem, but let's deal with it in a humane and serious way not through a demagogic way. And let me tell you what my view is, Trump thinks that he can win re-election. And this is his political game, it's not an accident that he announced this the same time he went through his- his announcement that he was seeking reelection.
MARGARET BRENNAN: You think this is purely politically motivated?
SEN. SANDERS: Yeah, I do. And I think that- look it's not to say that we don't have a serious problem but there are ways for serious people to deal with serious immigration problems. It is a problem. But what he is doing and this is his entire political strategy is to divide the American people up.
2020 ElectionClipsImmigrationBernie SandersDonald Trump
Exclusive–Lara Trump: Results Matter for Women, so Why Are Democrats Trying to Undo the President's Successes?
Democrats Hire Anti-Trump Pastor to Recruit Evangelicals Ahead of 2020
Donald Trump: Democrats Too 'Petrified' to Confront 'Anti-USA, Pro-Terrorist' Squad
Trump Pledges to Look into Google After Peter Thiel Accuses Tech Giant of 'Treason'
Kamala Harris on Reparations: 'Writing a Check' Not 'Gonna Be Enough'
Sen. Joni Ernst Jumps into the Fray, Says Trump's Remarks Were Racist
Fact Check: Dan Crenshaw Echoes Big Business Talking Points on Green Card Giveaway Amid Backlash
Crime Wave UK: Doctors Report Rise in 'Punishment Stabbings'
DOJ Won't Bring Federal Charges Against NYPD Officers Involved in Eric Garner's Death
Netanyahu: Europeans Won't Wake Up Until Iran Nukes Land on Them
U.S. Attorney General William Barr: Antisemitism a 'Cancer'
Ehud Barak Admits to Visiting Jeffrey Epstein's Island But Says He Didn't Attend Parties There


text:
Q: Execute IBAction on a custom event How would I be able to run an IBAction based on another event?  For example I could use a piece of code to run an IBAction.
What I'm trying to do is have two different buttons run one or more IBActions.

A: You can hook multiple buttons up to the same IBAction, so you could do it that way.
But IBActions are just methods. For example, if you have some action doSomething:, you can just call it on an object:
[obj doSomething:nil];

A: An IBAction is just a hint for the Interface Builder. It's actually another way of saying void.
#define IBAction void

So there is nothing special about it.
In Interface Builder, you can connect touch event for different buttons to the same IBAction.
You can also call IBAction methods from another IBAction method. Use the sender argument to identify the source of the event.
For example,
-(IBAction)buttonTapped:(id)sender {
    UIButton *btn = (UIButton *)sender;
    NSLog(@"tapped: %@", btn.titleLabel.text);
    [self anotherIBAction:sender];
}


text:
create function binary_coercible(oid, oid) returns bool as $$
begin
  if $1 = $2 then return true; end if;
  if EXISTS(select 1 from pg_catalog.pg_cast where
            castsource = $1 and casttarget = $2 and
            castmethod = 'b' and castcontext = 'i')
  then return true; end if;
  if $2 = 'pg_catalog.any'::pg_catalog.regtype then return true; end if;
  if $2 = 'pg_catalog.anyarray'::pg_catalog.regtype then
    if EXISTS(select 1 from pg_catalog.pg_type where
              oid = $1 and typelem != 0 and typlen = -1)
    then return true; end if;
  end if;
  if $2 = 'pg_catalog.anyrange'::pg_catalog.regtype then
    if (select typtype from pg_catalog.pg_type where oid = $1) = 'r'
    then return true; end if;
  end if;
  return false;
end
$$ language plpgsql strict stable;

-- This one ignores castcontext, so it will allow cases where an explicit
-- (but still binary) cast would be required to convert the input type.
-- We don't currently use this for any tests in this file, but it is a
-- reasonable alternative definition for some scenarios.
create function explicitly_binary_coercible(oid, oid) returns bool as $$
begin
  if $1 = $2 then return true; end if;
  if EXISTS(select 1 from pg_catalog.pg_cast where
            castsource = $1 and casttarget = $2 and
            castmethod = 'b')
  then return true; end if;
  if $2 = 'pg_catalog.any'::pg_catalog.regtype then return true; end if;
  if $2 = 'pg_catalog.anyarray'::pg_catalog.regtype then
    if EXISTS(select 1 from pg_catalog.pg_type where
              oid = $1 and typelem != 0 and typlen = -1)
    then return true; end if;
  end if;
  if $2 = 'pg_catalog.anyrange'::pg_catalog.regtype then
    if (select typtype from pg_catalog.pg_type where oid = $1) = 'r'
    then return true; end if;
  end if;
  return false;
end
$$ language plpgsql strict stable;

-- **************** pg_proc ****************

-- Look for illegal values in pg_proc fields.

SELECT p1.oid, p1.proname
FROM pg_proc as p1
WHERE p1.prolang = 0 OR p1.prorettype = 0 OR
       p1.pronargs < 0 OR
       p1.pronargdefaults < 0 OR
       p1.pronargdefaults > p1.pronargs OR
       array_lower(p1.proargtypes, 1) != 0 OR
       array_upper(p1.proargtypes, 1) != p1.pronargs-1 OR
       0::oid = ANY (p1.proargtypes) OR
       procost <= 0 OR
       CASE WHEN proretset THEN prorows <= 0 ELSE prorows != 0 END OR
       prokind NOT IN ('f', 'a', 'w', 'p') OR
       provolatile NOT IN ('i', 's', 'v') OR
       proparallel NOT IN ('s', 'r', 'u');

-- prosrc should never be null or empty
SELECT p1.oid, p1.proname
FROM pg_proc as p1
WHERE prosrc IS NULL OR prosrc = '' OR prosrc = '-';

-- proretset should only be set for normal functions
SELECT p1.oid, p1.proname
FROM pg_proc AS p1
WHERE proretset AND prokind != 'f';

-- currently, no built-in functions should be SECURITY DEFINER;
-- this might change in future, but there will probably never be many.
SELECT p1.oid, p1.proname
FROM pg_proc AS p1
WHERE prosecdef
ORDER BY 1;

-- pronargdefaults should be 0 iff proargdefaults is null
SELECT p1.oid, p1.proname
FROM pg_proc AS p1
WHERE (pronargdefaults <> 0) != (proargdefaults IS NOT NULL);

-- probin should be non-empty for C functions, null everywhere else
SELECT p1.oid, p1.proname
FROM pg_proc as p1
WHERE prolang = 13 AND (probin IS NULL OR probin = '' OR probin = '-');

SELECT p1.oid, p1.proname
FROM pg_proc as p1
WHERE prolang != 13 AND probin IS NOT NULL;

-- Look for conflicting proc definitions (same names and input datatypes).
-- (This test should be dead code now that we have the unique index
-- pg_proc_proname_args_nsp_index, but I'll leave it in anyway.)

SELECT p1.oid, p1.proname, p2.oid, p2.proname
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
    p1.proname = p2.proname AND
    p1.pronargs = p2.pronargs AND
    p1.proargtypes = p2.proargtypes;

-- Considering only built-in procs (prolang = 12), look for multiple uses
-- of the same internal function (ie, matching prosrc fields).  It's OK to
-- have several entries with different pronames for the same internal function,
-- but conflicts in the number of arguments and other critical items should
-- be complained of.  (We don't check data types here; see next query.)
-- Note: ignore aggregate functions here, since they all point to the same
-- dummy built-in function.

SELECT p1.oid, p1.proname, p2.oid, p2.proname
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid < p2.oid AND
    p1.prosrc = p2.prosrc AND
    p1.prolang = 12 AND p2.prolang = 12 AND
    (p1.prokind != 'a' OR p2.prokind != 'a') AND
    (p1.prolang != p2.prolang OR
     p1.prokind != p2.prokind OR
     p1.prosecdef != p2.prosecdef OR
     p1.proleakproof != p2.proleakproof OR
     p1.proisstrict != p2.proisstrict OR
     p1.proretset != p2.proretset OR
     p1.provolatile != p2.provolatile OR
     p1.pronargs != p2.pronargs);

-- Look for uses of different type OIDs in the argument/result type fields
-- for different aliases of the same built-in function.
-- This indicates that the types are being presumed to be binary-equivalent,
-- or that the built-in function is prepared to deal with different types.
-- That's not wrong, necessarily, but we make lists of all the types being
-- so treated.  Note that the expected output of this part of the test will
-- need to be modified whenever new pairs of types are made binary-equivalent,
-- or when new polymorphic built-in functions are added!
-- Note: ignore aggregate functions here, since they all point to the same
-- dummy built-in function.  Likewise, ignore range constructor functions.

SELECT DISTINCT p1.prorettype, p2.prorettype
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
    p1.prosrc = p2.prosrc AND
    p1.prolang = 12 AND p2.prolang = 12 AND
    p1.prokind != 'a' AND p2.prokind != 'a' AND
    p1.prosrc NOT LIKE E'range\\_constructor_' AND
    p2.prosrc NOT LIKE E'range\\_constructor_' AND
    (p1.prorettype < p2.prorettype)
    -- int2/int4/int8/float8_matrix_accum functions violate this
    AND p1.proname NOT LIKE E'%_matrix_accum'
    AND p2.proname NOT LIKE E'%_matrix_accum'
ORDER BY 1, 2;

SELECT DISTINCT p1.proargtypes[0], p2.proargtypes[0]
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
    p1.prosrc = p2.prosrc AND
    p1.prolang = 12 AND p2.prolang = 12 AND
    p1.prokind != 'a' AND p2.prokind != 'a' AND
    p1.prosrc NOT LIKE E'range\\_constructor_' AND
    p2.prosrc NOT LIKE E'range\\_constructor_' AND
    (p1.proargtypes[0] < p2.proargtypes[0])
    -- int2/int4/int8/float8_matrix_accum functions violate this
    AND p1.proname NOT LIKE E'%_matrix_accum'
    AND p2.proname NOT LIKE E'%_matrix_accum'
ORDER BY 1, 2;

SELECT DISTINCT p1.proargtypes[1], p2.proargtypes[1]
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
    p1.prosrc = p2.prosrc AND
    p1.prolang = 12 AND p2.prolang = 12 AND
    p1.prokind != 'a' AND p2.prokind != 'a' AND
    p1.prosrc NOT LIKE E'range\\_constructor_' AND
    p2.prosrc NOT LIKE E'range\\_constructor_' AND
    (p1.proargtypes[1] < p2.proargtypes[1])
    -- int2/int4/int8/float8_matrix_accum functions violate this
    AND p1.proname NOT LIKE E'%_matrix_accum'
    AND p2.proname NOT LIKE E'%_matrix_accum'
ORDER BY 1, 2;

SELECT DISTINCT p1.proargtypes[2], p2.proargtypes[2]
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
    p1.prosrc = p2.prosrc AND
    p1.prolang = 12 AND p2.prolang = 12 AND
    p1.prokind != 'a' AND p2.prokind != 'a' AND
    (p1.proargtypes[2] < p2.proargtypes[2])
ORDER BY 1, 2;

SELECT DISTINCT p1.proargtypes[3], p2.proargtypes[3]
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
    p1.prosrc = p2.prosrc AND
    p1.prolang = 12 AND p2.prolang = 12 AND
    p1.prokind != 'a' AND p2.prokind != 'a' AND
    (p1.proargtypes[3] < p2.proargtypes[3])
ORDER BY 1, 2;

SELECT DISTINCT p1.proargtypes[4], p2.proargtypes[4]
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
    p1.prosrc = p2.prosrc AND
    p1.prolang = 12 AND p2.prolang = 12 AND
    p1.prokind != 'a' AND p2.prokind != 'a' AND
    (p1.proargtypes[4] < p2.proargtypes[4])
ORDER BY 1, 2;

SELECT DISTINCT p1.proargtypes[5], p2.proargtypes[5]
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
    p1.prosrc = p2.prosrc AND
    p1.prolang = 12 AND p2.prolang = 12 AND
    p1.prokind != 'a' AND p2.prokind != 'a' AND
    (p1.proargtypes[5] < p2.proargtypes[5])
ORDER BY 1, 2;

SELECT DISTINCT p1.proargtypes[6], p2.proargtypes[6]
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
    p1.prosrc = p2.prosrc AND
    p1.prolang = 12 AND p2.prolang = 12 AND
    p1.prokind != 'a' AND p2.prokind != 'a' AND
    (p1.proargtypes[6] < p2.proargtypes[6])
ORDER BY 1, 2;

SELECT DISTINCT p1.proargtypes[7], p2.proargtypes[7]
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
    p1.prosrc = p2.prosrc AND
    p1.prolang = 12 AND p2.prolang = 12 AND
    p1.prokind != 'a' AND p2.prokind != 'a' AND
    (p1.proargtypes[7] < p2.proargtypes[7])
ORDER BY 1, 2;

-- Look for functions that return type "internal" and do not have any
-- "internal" argument.  Such a function would be a security hole since
-- it might be used to call an internal function from an SQL command.
-- As of 7.3 this query should find only internal_in, which is safe because
-- it always throws an error when called.

SELECT p1.oid, p1.proname
FROM pg_proc as p1
WHERE p1.prorettype = 'internal'::regtype AND NOT
    'internal'::regtype = ANY (p1.proargtypes);

-- Look for functions that return a polymorphic type and do not have any
-- polymorphic argument.  Calls of such functions would be unresolvable
-- at parse time.  As of 9.6 this query should find only some input functions
-- and GiST support functions associated with these pseudotypes.

SELECT p1.oid, p1.proname
FROM pg_proc as p1
WHERE p1.prorettype IN
    ('anyelement'::regtype, 'anyarray'::regtype, 'anynonarray'::regtype,
     'anyenum'::regtype, 'anyrange'::regtype)
  AND NOT
    ('anyelement'::regtype = ANY (p1.proargtypes) OR
     'anyarray'::regtype = ANY (p1.proargtypes) OR
     'anynonarray'::regtype = ANY (p1.proargtypes) OR
     'anyenum'::regtype = ANY (p1.proargtypes) OR
     'anyrange'::regtype = ANY (p1.proargtypes))
ORDER BY 2;

-- Look for functions that accept cstring and are neither datatype input
-- functions nor encoding conversion functions.  It's almost never a good
-- idea to use cstring input for a function meant to be called from SQL;
-- text should be used instead, because cstring lacks suitable casts.
-- As of 9.6 this query should find only cstring_out and cstring_send.
-- However, we must manually exclude shell_in, which might or might not be
-- rejected by the EXISTS clause depending on whether there are currently
-- any shell types.

SELECT p1.oid, p1.proname
FROM pg_proc as p1
WHERE 'cstring'::regtype = ANY (p1.proargtypes)
    AND NOT EXISTS(SELECT 1 FROM pg_type WHERE typinput = p1.oid)
    AND NOT EXISTS(SELECT 1 FROM pg_conversion WHERE conproc = p1.oid)
    AND p1.oid != 'shell_in(cstring)'::regprocedure
ORDER BY 1;

-- Likewise, look for functions that return cstring and aren't datatype output
-- functions nor typmod output functions.
-- As of 9.6 this query should find only cstring_in and cstring_recv.
-- However, we must manually exclude shell_out.

SELECT p1.oid, p1.proname
FROM pg_proc as p1
WHERE  p1.prorettype = 'cstring'::regtype
    AND NOT EXISTS(SELECT 1 FROM pg_type WHERE typoutput = p1.oid)
    AND NOT EXISTS(SELECT 1 FROM pg_type WHERE typmodout = p1.oid)
    AND p1.oid != 'shell_out(opaque)'::regprocedure
ORDER BY 1;

-- Check for length inconsistencies between the various argument-info arrays.

SELECT p1.oid, p1.proname
FROM pg_proc as p1
WHERE proallargtypes IS NOT NULL AND
    array_length(proallargtypes,1) < array_length(proargtypes,1);

SELECT p1.oid, p1.proname
FROM pg_proc as p1
WHERE proargmodes IS NOT NULL AND
    array_length(proargmodes,1) < array_length(proargtypes,1);

SELECT p1.oid, p1.proname
FROM pg_proc as p1
WHERE proargnames IS NOT NULL AND
    array_length(proargnames,1) < array_length(proargtypes,1);

SELECT p1.oid, p1.proname
FROM pg_proc as p1
WHERE proallargtypes IS NOT NULL AND proargmodes IS NOT NULL AND
    array_length(proallargtypes,1) <> array_length(proargmodes,1);

SELECT p1.oid, p1.proname
FROM pg_proc as p1
WHERE proallargtypes IS NOT NULL AND proargnames IS NOT NULL AND
    array_length(proallargtypes,1) <> array_length(proargnames,1);

SELECT p1.oid, p1.proname
FROM pg_proc as p1
WHERE proargmodes IS NOT NULL AND proargnames IS NOT NULL AND
    array_length(proargmodes,1) <> array_length(proargnames,1);

-- Check that proallargtypes matches proargtypes
SELECT p1.oid, p1.proname, p1.proargtypes, p1.proallargtypes, p1.proargmodes
FROM pg_proc as p1
WHERE proallargtypes IS NOT NULL AND
  ARRAY(SELECT unnest(proargtypes)) <>
  ARRAY(SELECT proallargtypes[i]
        FROM generate_series(1, array_length(proallargtypes, 1)) g(i)
        WHERE proargmodes IS NULL OR proargmodes[i] IN ('i', 'b', 'v'));

-- Check for prosupport functions with the wrong signature
SELECT p1.oid, p1.proname, p2.oid, p2.proname
FROM pg_proc AS p1, pg_proc AS p2
WHERE p2.oid = p1.prosupport AND
    (p2.prorettype != 'internal'::regtype OR p2.proretset OR p2.pronargs != 1
     OR p2.proargtypes[0] != 'internal'::regtype);

-- Insist that all built-in pg_proc entries have descriptions
SELECT p1.oid, p1.proname
FROM pg_proc as p1 LEFT JOIN pg_description as d
     ON p1.tableoid = d.classoid and p1.oid = d.objoid and d.objsubid = 0
WHERE d.classoid IS NULL AND p1.oid <= 9999;

-- List of built-in leakproof functions
--
-- Leakproof functions should only be added after carefully
-- scrutinizing all possibly executed codepaths for possible
-- information leaks. Don't add functions here unless you know what a
-- leakproof function is. If unsure, don't mark it as such.

-- temporarily disable fancy output, so catalog changes create less diff noise
\a\t

SELECT p1.oid::regprocedure
FROM pg_proc p1 JOIN pg_namespace pn
     ON pronamespace = pn.oid
WHERE nspname = 'pg_catalog' AND proleakproof
ORDER BY 1;

-- restore normal output mode
\a\t

-- List of functions used by libpq's fe-lobj.c
--
-- If the output of this query changes, you probably broke libpq.
-- lo_initialize() assumes that there will be at most one match for
-- each listed name.
select proname, oid from pg_catalog.pg_proc
where proname in (
  'lo_open',
  'lo_close',
  'lo_creat',
  'lo_create',
  'lo_unlink',
  'lo_lseek',
  'lo_lseek64',
  'lo_tell',
  'lo_tell64',
  'lo_truncate',
  'lo_truncate64',
  'loread',
  'lowrite')
and pronamespace = (select oid from pg_catalog.pg_namespace
                    where nspname = 'pg_catalog')
order by 1;

-- Check that all immutable functions are marked parallel safe
SELECT p1.oid, p1.proname
FROM pg_proc AS p1
WHERE provolatile = 'i' AND proparallel = 'u';

-- **************** pg_cast ****************

-- Catch bogus values in pg_cast columns (other than cases detected by
-- oidjoins test).

SELECT *
FROM pg_cast c
WHERE castsource = 0 OR casttarget = 0 OR castcontext NOT IN ('e', 'a', 'i')
    OR castmethod NOT IN ('f', 'b' ,'i');

-- Check that castfunc is nonzero only for cast methods that need a function,
-- and zero otherwise

SELECT *
FROM pg_cast c
WHERE (castmethod = 'f' AND castfunc = 0)
   OR (castmethod IN ('b', 'i') AND castfunc <> 0);

-- Look for casts to/from the same type that aren't length coercion functions.
-- (We assume they are length coercions if they take multiple arguments.)
-- Such entries are not necessarily harmful, but they are useless.

SELECT *
FROM pg_cast c
WHERE castsource = casttarget AND castfunc = 0;

SELECT c.*
FROM pg_cast c, pg_proc p
WHERE c.castfunc = p.oid AND p.pronargs < 2 AND castsource = casttarget;

-- Look for cast functions that don't have the right signature.  The
-- argument and result types in pg_proc must be the same as, or binary
-- compatible with, what it says in pg_cast.
-- As a special case, we allow casts from CHAR(n) that use functions
-- declared to take TEXT.  This does not pass the binary-coercibility test
-- because CHAR(n)-to-TEXT normally invokes rtrim().  However, the results
-- are the same, so long as the function is one that ignores trailing blanks.

SELECT c.*
FROM pg_cast c, pg_proc p
WHERE c.castfunc = p.oid AND
    (p.pronargs < 1 OR p.pronargs > 3
     OR NOT (binary_coercible(c.castsource, p.proargtypes[0])
             OR (c.castsource = 'character'::regtype AND
                 p.proargtypes[0] = 'text'::regtype))
     OR NOT binary_coercible(p.prorettype, c.casttarget));

SELECT c.*
FROM pg_cast c, pg_proc p
WHERE c.castfunc = p.oid AND
    ((p.pronargs > 1 AND p.proargtypes[1] != 'int4'::regtype) OR
     (p.pronargs > 2 AND p.proargtypes[2] != 'bool'::regtype));

-- Look for binary compatible casts that do not have the reverse
-- direction registered as well, or where the reverse direction is not
-- also binary compatible.  This is legal, but usually not intended.

-- As of 7.4, this finds the casts from text and varchar to bpchar, because
-- those are binary-compatible while the reverse way goes through rtrim().

-- As of 8.2, this finds the cast from cidr to inet, because that is a
-- trivial binary coercion while the other way goes through inet_to_cidr().

-- As of 8.3, this finds the casts from xml to text, varchar, and bpchar,
-- because those are binary-compatible while the reverse goes through
-- texttoxml(), which does an XML syntax check.

-- As of 9.1, this finds the cast from pg_node_tree to text, which we
-- intentionally do not provide a reverse pathway for.

SELECT castsource::regtype, casttarget::regtype, castfunc, castcontext
FROM pg_cast c
WHERE c.castmethod = 'b' AND
    NOT EXISTS (SELECT 1 FROM pg_cast k
                WHERE k.castmethod = 'b' AND
                    k.castsource = c.casttarget AND
                    k.casttarget = c.castsource);

-- **************** pg_conversion ****************

-- Look for illegal values in pg_conversion fields.

SELECT p1.oid, p1.conname
FROM pg_conversion as p1
WHERE p1.conproc = 0 OR
    pg_encoding_to_char(conforencoding) = '' OR
    pg_encoding_to_char(contoencoding) = '';

-- Look for conprocs that don't have the expected signature.

SELECT p.oid, p.proname, c.oid, c.conname
FROM pg_proc p, pg_conversion c
WHERE p.oid = c.conproc AND
    (p.prorettype != 'void'::regtype OR p.proretset OR
     p.pronargs != 5 OR
     p.proargtypes[0] != 'int4'::regtype OR
     p.proargtypes[1] != 'int4'::regtype OR
     p.proargtypes[2] != 'cstring'::regtype OR
     p.proargtypes[3] != 'internal'::regtype OR
     p.proargtypes[4] != 'int4'::regtype);

-- Check for conprocs that don't perform the specific conversion that
-- pg_conversion alleges they do, by trying to invoke each conversion
-- on some simple ASCII data.  (The conproc should throw an error if
-- it doesn't accept the encodings that are passed to it.)
-- Unfortunately, we can't test non-default conprocs this way, because
-- there is no way to ask convert() to invoke them, and we cannot call
-- them directly from SQL.  But there are no non-default built-in
-- conversions anyway.
-- (Similarly, this doesn't cope with any search path issues.)

SELECT p1.oid, p1.conname
FROM pg_conversion as p1
WHERE condefault AND
    convert('ABC'::bytea, pg_encoding_to_char(conforencoding),
            pg_encoding_to_char(contoencoding)) != 'ABC';

-- **************** pg_operator ****************

-- Look for illegal values in pg_operator fields.

SELECT p1.oid, p1.oprname
FROM pg_operator as p1
WHERE (p1.oprkind != 'b' AND p1.oprkind != 'l' AND p1.oprkind != 'r') OR
    p1.oprresult = 0 OR p1.oprcode = 0;

-- Look for missing or unwanted operand types

SELECT p1.oid, p1.oprname
FROM pg_operator as p1
WHERE (p1.oprleft = 0 and p1.oprkind != 'l') OR
    (p1.oprleft != 0 and p1.oprkind = 'l') OR
    (p1.oprright = 0 and p1.oprkind != 'r') OR
    (p1.oprright != 0 and p1.oprkind = 'r');

-- Look for conflicting operator definitions (same names and input datatypes).

SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
FROM pg_operator AS p1, pg_operator AS p2
WHERE p1.oid != p2.oid AND
    p1.oprname = p2.oprname AND
    p1.oprkind = p2.oprkind AND
    p1.oprleft = p2.oprleft AND
    p1.oprright = p2.oprright;

-- Look for commutative operators that don't commute.
-- DEFINITIONAL NOTE: If A.oprcom = B, then x A y has the same result as y B x.
-- We expect that B will always say that B.oprcom = A as well; that's not
-- inherently essential, but it would be inefficient not to mark it so.

SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
FROM pg_operator AS p1, pg_operator AS p2
WHERE p1.oprcom = p2.oid AND
    (p1.oprkind != 'b' OR
     p1.oprleft != p2.oprright OR
     p1.oprright != p2.oprleft OR
     p1.oprresult != p2.oprresult OR
     p1.oid != p2.oprcom);

-- Look for negatory operators that don't agree.
-- DEFINITIONAL NOTE: If A.oprnegate = B, then both A and B must yield
-- boolean results, and (x A y) == ! (x B y), or the equivalent for
-- single-operand operators.
-- We expect that B will always say that B.oprnegate = A as well; that's not
-- inherently essential, but it would be inefficient not to mark it so.
-- Also, A and B had better not be the same operator.

SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
FROM pg_operator AS p1, pg_operator AS p2
WHERE p1.oprnegate = p2.oid AND
    (p1.oprkind != p2.oprkind OR
     p1.oprleft != p2.oprleft OR
     p1.oprright != p2.oprright OR
     p1.oprresult != 'bool'::regtype OR
     p2.oprresult != 'bool'::regtype OR
     p1.oid != p2.oprnegate OR
     p1.oid = p2.oid);

-- Make a list of the names of operators that are claimed to be commutator
-- pairs.  This list will grow over time, but before accepting a new entry
-- make sure you didn't link the wrong operators.

SELECT DISTINCT o1.oprname AS op1, o2.oprname AS op2
FROM pg_operator o1, pg_operator o2
WHERE o1.oprcom = o2.oid AND o1.oprname <= o2.oprname
ORDER BY 1, 2;

-- Likewise for negator pairs.

SELECT DISTINCT o1.oprname AS op1, o2.oprname AS op2
FROM pg_operator o1, pg_operator o2
WHERE o1.oprnegate = o2.oid AND o1.oprname <= o2.oprname
ORDER BY 1, 2;

-- A mergejoinable or hashjoinable operator must be binary, must return
-- boolean, and must have a commutator (itself, unless it's a cross-type
-- operator).

SELECT p1.oid, p1.oprname FROM pg_operator AS p1
WHERE (p1.oprcanmerge OR p1.oprcanhash) AND NOT
    (p1.oprkind = 'b' AND p1.oprresult = 'bool'::regtype AND p1.oprcom != 0);

-- What's more, the commutator had better be mergejoinable/hashjoinable too.

SELECT p1.oid, p1.oprname, p2.oid, p2.oprname
FROM pg_operator AS p1, pg_operator AS p2
WHERE p1.oprcom = p2.oid AND
    (p1.oprcanmerge != p2.oprcanmerge OR
     p1.oprcanhash != p2.oprcanhash);

-- Mergejoinable operators should appear as equality members of btree index
-- opfamilies.

SELECT p1.oid, p1.oprname
FROM pg_operator AS p1
WHERE p1.oprcanmerge AND NOT EXISTS
  (SELECT 1 FROM pg_amop
   WHERE amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree') AND
         amopopr = p1.oid AND amopstrategy = 3);

-- And the converse.

SELECT p1.oid, p1.oprname, p.amopfamily
FROM pg_operator AS p1, pg_amop p
WHERE amopopr = p1.oid
  AND amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree')
  AND amopstrategy = 3
  AND NOT p1.oprcanmerge;

-- Hashable operators should appear as members of hash index opfamilies.

SELECT p1.oid, p1.oprname
FROM pg_operator AS p1
WHERE p1.oprcanhash AND NOT EXISTS
  (SELECT 1 FROM pg_amop
   WHERE amopmethod = (SELECT oid FROM pg_am WHERE amname = 'hash') AND
         amopopr = p1.oid AND amopstrategy = 1);

-- And the converse.

SELECT p1.oid, p1.oprname, p.amopfamily
FROM pg_operator AS p1, pg_amop p
WHERE amopopr = p1.oid
  AND amopmethod = (SELECT oid FROM pg_am WHERE amname = 'hash')
  AND NOT p1.oprcanhash;

-- Check that each operator defined in pg_operator matches its oprcode entry
-- in pg_proc.  Easiest to do this separately for each oprkind.

SELECT p1.oid, p1.oprname, p2.oid, p2.proname
FROM pg_operator AS p1, pg_proc AS p2
WHERE p1.oprcode = p2.oid AND
    p1.oprkind = 'b' AND
    (p2.pronargs != 2
     OR NOT binary_coercible(p2.prorettype, p1.oprresult)
     OR NOT binary_coercible(p1.oprleft, p2.proargtypes[0])
     OR NOT binary_coercible(p1.oprright, p2.proargtypes[1]));

SELECT p1.oid, p1.oprname, p2.oid, p2.proname
FROM pg_operator AS p1, pg_proc AS p2
WHERE p1.oprcode = p2.oid AND
    p1.oprkind = 'l' AND
    (p2.pronargs != 1
     OR NOT binary_coercible(p2.prorettype, p1.oprresult)
     OR NOT binary_coercible(p1.oprright, p2.proargtypes[0])
     OR p1.oprleft != 0);

SELECT p1.oid, p1.oprname, p2.oid, p2.proname
FROM pg_operator AS p1, pg_proc AS p2
WHERE p1.oprcode = p2.oid AND
    p1.oprkind = 'r' AND
    (p2.pronargs != 1
     OR NOT binary_coercible(p2.prorettype, p1.oprresult)
     OR NOT binary_coercible(p1.oprleft, p2.proargtypes[0])
     OR p1.oprright != 0);

-- If the operator is mergejoinable or hashjoinable, its underlying function
-- should not be volatile.

SELECT p1.oid, p1.oprname, p2.oid, p2.proname
FROM pg_operator AS p1, pg_proc AS p2
WHERE p1.oprcode = p2.oid AND
    (p1.oprcanmerge OR p1.oprcanhash) AND
    p2.provolatile = 'v';

-- If oprrest is set, the operator must return boolean,
-- and it must link to a proc with the right signature
-- to be a restriction selectivity estimator.
-- The proc signature we want is: float8 proc(internal, oid, internal, int4)

SELECT p1.oid, p1.oprname, p2.oid, p2.proname
FROM pg_operator AS p1, pg_proc AS p2
WHERE p1.oprrest = p2.oid AND
    (p1.oprresult != 'bool'::regtype OR
     p2.prorettype != 'float8'::regtype OR p2.proretset OR
     p2.pronargs != 4 OR
     p2.proargtypes[0] != 'internal'::regtype OR
     p2.proargtypes[1] != 'oid'::regtype OR
     p2.proargtypes[2] != 'internal'::regtype OR
     p2.proargtypes[3] != 'int4'::regtype);

-- If oprjoin is set, the operator must be a binary boolean op,
-- and it must link to a proc with the right signature
-- to be a join selectivity estimator.
-- The proc signature we want is: float8 proc(internal, oid, internal, int2, internal)
-- (Note: the old signature with only 4 args is still allowed, but no core
-- estimator should be using it.)

SELECT p1.oid, p1.oprname, p2.oid, p2.proname
FROM pg_operator AS p1, pg_proc AS p2
WHERE p1.oprjoin = p2.oid AND
    (p1.oprkind != 'b' OR p1.oprresult != 'bool'::regtype OR
     p2.prorettype != 'float8'::regtype OR p2.proretset OR
     p2.pronargs != 5 OR
     p2.proargtypes[0] != 'internal'::regtype OR
     p2.proargtypes[1] != 'oid'::regtype OR
     p2.proargtypes[2] != 'internal'::regtype OR
     p2.proargtypes[3] != 'int2'::regtype OR
     p2.proargtypes[4] != 'internal'::regtype);

-- Insist that all built-in pg_operator entries have descriptions
SELECT p1.oid, p1.oprname
FROM pg_operator as p1 LEFT JOIN pg_description as d
     ON p1.tableoid = d.classoid and p1.oid = d.objoid and d.objsubid = 0
WHERE d.classoid IS NULL AND p1.oid <= 9999;

-- Check that operators' underlying functions have suitable comments,
-- namely 'implementation of XXX operator'.  (Note: it's not necessary to
-- put such comments into pg_proc.dat; initdb will generate them as needed.)
-- In some cases involving legacy names for operators, there are multiple
-- operators referencing the same pg_proc entry, so ignore operators whose
-- comments say they are deprecated.
-- We also have a few functions that are both operator support and meant to
-- be called directly; those should have comments matching their operator.
WITH funcdescs AS (
  SELECT p.oid as p_oid, proname, o.oid as o_oid,
    pd.description as prodesc,
    'implementation of ' || oprname || ' operator' as expecteddesc,
    od.description as oprdesc
  FROM pg_proc p JOIN pg_operator o ON oprcode = p.oid
       LEFT JOIN pg_description pd ON
         (pd.objoid = p.oid and pd.classoid = p.tableoid and pd.objsubid = 0)
       LEFT JOIN pg_description od ON
         (od.objoid = o.oid and od.classoid = o.tableoid and od.objsubid = 0)
  WHERE o.oid <= 9999
)
SELECT * FROM funcdescs
  WHERE prodesc IS DISTINCT FROM expecteddesc
    AND oprdesc NOT LIKE 'deprecated%'
    AND prodesc IS DISTINCT FROM oprdesc;

-- Show all the operator-implementation functions that have their own
-- comments.  This should happen only in cases where the function and
-- operator syntaxes are both documented at the user level.
-- This should be a pretty short list; it's mostly legacy cases.
WITH funcdescs AS (
  SELECT p.oid as p_oid, proname, o.oid as o_oid,
    pd.description as prodesc,
    'implementation of ' || oprname || ' operator' as expecteddesc,
    od.description as oprdesc
  FROM pg_proc p JOIN pg_operator o ON oprcode = p.oid
       LEFT JOIN pg_description pd ON
         (pd.objoid = p.oid and pd.classoid = p.tableoid and pd.objsubid = 0)
       LEFT JOIN pg_description od ON
         (od.objoid = o.oid and od.classoid = o.tableoid and od.objsubid = 0)
  WHERE o.oid <= 9999
)
SELECT p_oid, proname, prodesc FROM funcdescs
  WHERE prodesc IS DISTINCT FROM expecteddesc
    AND oprdesc NOT LIKE 'deprecated%'
ORDER BY 1;

-- Operators that are commutator pairs should have identical volatility
-- and leakproofness markings on their implementation functions.
SELECT o1.oid, o1.oprcode, o2.oid, o2.oprcode
FROM pg_operator AS o1, pg_operator AS o2, pg_proc AS p1, pg_proc AS p2
WHERE o1.oprcom = o2.oid AND p1.oid = o1.oprcode AND p2.oid = o2.oprcode AND
    (p1.provolatile != p2.provolatile OR
     p1.proleakproof != p2.proleakproof);

-- Likewise for negator pairs.
SELECT o1.oid, o1.oprcode, o2.oid, o2.oprcode
FROM pg_operator AS o1, pg_operator AS o2, pg_proc AS p1, pg_proc AS p2
WHERE o1.oprnegate = o2.oid AND p1.oid = o1.oprcode AND p2.oid = o2.oprcode AND
    (p1.provolatile != p2.provolatile OR
     p1.proleakproof != p2.proleakproof);

-- Btree comparison operators' functions should have the same volatility
-- and leakproofness markings as the associated comparison support function.
-- As of Postgres 12, the only exceptions are that textual equality functions
-- are marked leakproof but textual comparison/inequality functions are not.
SELECT pp.oid::regprocedure as proc, pp.provolatile as vp, pp.proleakproof as lp,
       po.oid::regprocedure as opr, po.provolatile as vo, po.proleakproof as lo
FROM pg_proc pp, pg_proc po, pg_operator o, pg_amproc ap, pg_amop ao
WHERE pp.oid = ap.amproc AND po.oid = o.oprcode AND o.oid = ao.amopopr AND
    ao.amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree') AND
    ao.amopfamily = ap.amprocfamily AND
    ao.amoplefttype = ap.amproclefttype AND
    ao.amoprighttype = ap.amprocrighttype AND
    ap.amprocnum = 1 AND
    (pp.provolatile != po.provolatile OR
     pp.proleakproof != po.proleakproof)
ORDER BY 1;

-- **************** pg_aggregate ****************

-- Look for illegal values in pg_aggregate fields.

SELECT ctid, aggfnoid::oid
FROM pg_aggregate as p1
WHERE aggfnoid = 0 OR aggtransfn = 0 OR
    aggkind NOT IN ('n', 'o', 'h') OR
    aggnumdirectargs < 0 OR
    (aggkind = 'n' AND aggnumdirectargs > 0) OR
    aggfinalmodify NOT IN ('r', 's', 'w') OR
    aggmfinalmodify NOT IN ('r', 's', 'w') OR
    aggtranstype = 0 OR aggtransspace < 0 OR aggmtransspace < 0;

-- Make sure the matching pg_proc entry is sensible, too.

SELECT a.aggfnoid::oid, p.proname
FROM pg_aggregate as a, pg_proc as p
WHERE a.aggfnoid = p.oid AND
    (p.prokind != 'a' OR p.proretset OR p.pronargs < a.aggnumdirectargs);

-- Make sure there are no prokind = PROKIND_AGGREGATE pg_proc entries without matches.

SELECT oid, proname
FROM pg_proc as p
WHERE p.prokind = 'a' AND
    NOT EXISTS (SELECT 1 FROM pg_aggregate a WHERE a.aggfnoid = p.oid);

-- If there is no finalfn then the output type must be the transtype.

SELECT a.aggfnoid::oid, p.proname
FROM pg_aggregate as a, pg_proc as p
WHERE a.aggfnoid = p.oid AND
    a.aggfinalfn = 0 AND p.prorettype != a.aggtranstype;

-- Cross-check transfn against its entry in pg_proc.
SELECT a.aggfnoid::oid, p.proname, ptr.oid, ptr.proname
FROM pg_aggregate AS a, pg_proc AS p, pg_proc AS ptr
WHERE a.aggfnoid = p.oid AND
    a.aggtransfn = ptr.oid AND
    (ptr.proretset
     OR NOT (ptr.pronargs =
             CASE WHEN a.aggkind = 'n' THEN p.pronargs + 1
             ELSE greatest(p.pronargs - a.aggnumdirectargs, 1) + 1 END)
     OR NOT binary_coercible(ptr.prorettype, a.aggtranstype)
     OR NOT binary_coercible(a.aggtranstype, ptr.proargtypes[0])
     OR (p.pronargs > 0 AND
         NOT binary_coercible(p.proargtypes[0], ptr.proargtypes[1]))
     OR (p.pronargs > 1 AND
         NOT binary_coercible(p.proargtypes[1], ptr.proargtypes[2]))
     OR (p.pronargs > 2 AND
         NOT binary_coercible(p.proargtypes[2], ptr.proargtypes[3]))
     -- we could carry the check further, but 3 args is enough for now
     OR (p.pronargs > 3)
    );

-- Cross-check finalfn (if present) against its entry in pg_proc.

SELECT a.aggfnoid::oid, p.proname, pfn.oid, pfn.proname
FROM pg_aggregate AS a, pg_proc AS p, pg_proc AS pfn
WHERE a.aggfnoid = p.oid AND
    a.aggfinalfn = pfn.oid AND
    (pfn.proretset OR
     NOT binary_coercible(pfn.prorettype, p.prorettype) OR
     NOT binary_coercible(a.aggtranstype, pfn.proargtypes[0]) OR
     CASE WHEN a.aggfinalextra THEN pfn.pronargs != p.pronargs + 1
          ELSE pfn.pronargs != a.aggnumdirectargs + 1 END
     OR (pfn.pronargs > 1 AND
         NOT binary_coercible(p.proargtypes[0], pfn.proargtypes[1]))
     OR (pfn.pronargs > 2 AND
         NOT binary_coercible(p.proargtypes[1], pfn.proargtypes[2]))
     OR (pfn.pronargs > 3 AND
         NOT binary_coercible(p.proargtypes[2], pfn.proargtypes[3]))
     -- we could carry the check further, but 4 args is enough for now
     OR (pfn.pronargs > 4)
    );

-- If transfn is strict then either initval should be non-NULL, or
-- input type should match transtype so that the first non-null input
-- can be assigned as the state value.

SELECT a.aggfnoid::oid, p.proname, ptr.oid, ptr.proname
FROM pg_aggregate AS a, pg_proc AS p, pg_proc AS ptr
WHERE a.aggfnoid = p.oid AND
    a.aggtransfn = ptr.oid AND ptr.proisstrict AND
    a.agginitval IS NULL AND
    NOT binary_coercible(p.proargtypes[0], a.aggtranstype);

-- Check for inconsistent specifications of moving-aggregate columns.

SELECT ctid, aggfnoid::oid
FROM pg_aggregate as p1
WHERE aggmtranstype != 0 AND
    (aggmtransfn = 0 OR aggminvtransfn = 0);

SELECT ctid, aggfnoid::oid
FROM pg_aggregate as p1
WHERE aggmtranstype = 0 AND
    (aggmtransfn != 0 OR aggminvtransfn != 0 OR aggmfinalfn != 0 OR
     aggmtransspace != 0 OR aggminitval IS NOT NULL);

-- If there is no mfinalfn then the output type must be the mtranstype.

SELECT a.aggfnoid::oid, p.proname
FROM pg_aggregate as a, pg_proc as p
WHERE a.aggfnoid = p.oid AND
    a.aggmtransfn != 0 AND
    a.aggmfinalfn = 0 AND p.prorettype != a.aggmtranstype;

-- Cross-check mtransfn (if present) against its entry in pg_proc.
SELECT a.aggfnoid::oid, p.proname, ptr.oid, ptr.proname
FROM pg_aggregate AS a, pg_proc AS p, pg_proc AS ptr
WHERE a.aggfnoid = p.oid AND
    a.aggmtransfn = ptr.oid AND
    (ptr.proretset
     OR NOT (ptr.pronargs =
             CASE WHEN a.aggkind = 'n' THEN p.pronargs + 1
             ELSE greatest(p.pronargs - a.aggnumdirectargs, 1) + 1 END)
     OR NOT binary_coercible(ptr.prorettype, a.aggmtranstype)
     OR NOT binary_coercible(a.aggmtranstype, ptr.proargtypes[0])
     OR (p.pronargs > 0 AND
         NOT binary_coercible(p.proargtypes[0], ptr.proargtypes[1]))
     OR (p.pronargs > 1 AND
         NOT binary_coercible(p.proargtypes[1], ptr.proargtypes[2]))
     OR (p.pronargs > 2 AND
         NOT binary_coercible(p.proargtypes[2], ptr.proargtypes[3]))
     -- we could carry the check further, but 3 args is enough for now
     OR (p.pronargs > 3)
    );

-- Cross-check minvtransfn (if present) against its entry in pg_proc.
SELECT a.aggfnoid::oid, p.proname, ptr.oid, ptr.proname
FROM pg_aggregate AS a, pg_proc AS p, pg_proc AS ptr
WHERE a.aggfnoid = p.oid AND
    a.aggminvtransfn = ptr.oid AND
    (ptr.proretset
     OR NOT (ptr.pronargs =
             CASE WHEN a.aggkind = 'n' THEN p.pronargs + 1
             ELSE greatest(p.pronargs - a.aggnumdirectargs, 1) + 1 END)
     OR NOT binary_coercible(ptr.prorettype, a.aggmtranstype)
     OR NOT binary_coercible(a.aggmtranstype, ptr.proargtypes[0])
     OR (p.pronargs > 0 AND
         NOT binary_coercible(p.proargtypes[0], ptr.proargtypes[1]))
     OR (p.pronargs > 1 AND
         NOT binary_coercible(p.proargtypes[1], ptr.proargtypes[2]))
     OR (p.pronargs > 2 AND
         NOT binary_coercible(p.proargtypes[2], ptr.proargtypes[3]))
     -- we could carry the check further, but 3 args is enough for now
     OR (p.pronargs > 3)
    );

-- Cross-check mfinalfn (if present) against its entry in pg_proc.

SELECT a.aggfnoid::oid, p.proname, pfn.oid, pfn.proname
FROM pg_aggregate AS a, pg_proc AS p, pg_proc AS pfn
WHERE a.aggfnoid = p.oid AND
    a.aggmfinalfn = pfn.oid AND
    (pfn.proretset OR
     NOT binary_coercible(pfn.prorettype, p.prorettype) OR
     NOT binary_coercible(a.aggmtranstype, pfn.proargtypes[0]) OR
     CASE WHEN a.aggmfinalextra THEN pfn.pronargs != p.pronargs + 1
          ELSE pfn.pronargs != a.aggnumdirectargs + 1 END
     OR (pfn.pronargs > 1 AND
         NOT binary_coercible(p.proargtypes[0], pfn.proargtypes[1]))
     OR (pfn.pronargs > 2 AND
         NOT binary_coercible(p.proargtypes[1], pfn.proargtypes[2]))
     OR (pfn.pronargs > 3 AND
         NOT binary_coercible(p.proargtypes[2], pfn.proargtypes[3]))
     -- we could carry the check further, but 4 args is enough for now
     OR (pfn.pronargs > 4)
    );

-- If mtransfn is strict then either minitval should be non-NULL, or
-- input type should match mtranstype so that the first non-null input
-- can be assigned as the state value.

SELECT a.aggfnoid::oid, p.proname, ptr.oid, ptr.proname
FROM pg_aggregate AS a, pg_proc AS p, pg_proc AS ptr
WHERE a.aggfnoid = p.oid AND
    a.aggmtransfn = ptr.oid AND ptr.proisstrict AND
    a.aggminitval IS NULL AND
    NOT binary_coercible(p.proargtypes[0], a.aggmtranstype);

-- mtransfn and minvtransfn should have same strictness setting.

SELECT a.aggfnoid::oid, p.proname, ptr.oid, ptr.proname, iptr.oid, iptr.proname
FROM pg_aggregate AS a, pg_proc AS p, pg_proc AS ptr, pg_proc AS iptr
WHERE a.aggfnoid = p.oid AND
    a.aggmtransfn = ptr.oid AND
    a.aggminvtransfn = iptr.oid AND
    ptr.proisstrict != iptr.proisstrict;

-- Check that all combine functions have signature
-- combine(transtype, transtype) returns transtype

SELECT a.aggfnoid, p.proname
FROM pg_aggregate as a, pg_proc as p
WHERE a.aggcombinefn = p.oid AND
    (p.pronargs != 2 OR
     p.prorettype != p.proargtypes[0] OR
     p.prorettype != p.proargtypes[1] OR
     NOT binary_coercible(a.aggtranstype, p.proargtypes[0]));

-- Check that no combine function for an INTERNAL transtype is strict.

SELECT a.aggfnoid, p.proname
FROM pg_aggregate as a, pg_proc as p
WHERE a.aggcombinefn = p.oid AND
    a.aggtranstype = 'internal'::regtype AND p.proisstrict;

-- serialize/deserialize functions should be specified only for aggregates
-- with transtype internal and a combine function, and we should have both
-- or neither of them.

SELECT aggfnoid, aggtranstype, aggserialfn, aggdeserialfn
FROM pg_aggregate
WHERE (aggserialfn != 0 OR aggdeserialfn != 0)
  AND (aggtranstype != 'internal'::regtype OR aggcombinefn = 0 OR
       aggserialfn = 0 OR aggdeserialfn = 0);

-- Check that all serialization functions have signature
-- serialize(internal) returns bytea
-- Also insist that they be strict; it's wasteful to run them on NULLs.

SELECT a.aggfnoid, p.proname
FROM pg_aggregate as a, pg_proc as p
WHERE a.aggserialfn = p.oid AND
    (p.prorettype != 'bytea'::regtype OR p.pronargs != 1 OR
     p.proargtypes[0] != 'internal'::regtype OR
     NOT p.proisstrict);

-- Check that all deserialization functions have signature
-- deserialize(bytea, internal) returns internal
-- Also insist that they be strict; it's wasteful to run them on NULLs.

SELECT a.aggfnoid, p.proname
FROM pg_aggregate as a, pg_proc as p
WHERE a.aggdeserialfn = p.oid AND
    (p.prorettype != 'internal'::regtype OR p.pronargs != 2 OR
     p.proargtypes[0] != 'bytea'::regtype OR
     p.proargtypes[1] != 'internal'::regtype OR
     NOT p.proisstrict);

-- Check that aggregates which have the same transition function also have
-- the same combine, serialization, and deserialization functions.
-- While that isn't strictly necessary, it's fishy if they don't.

SELECT a.aggfnoid, a.aggcombinefn, a.aggserialfn, a.aggdeserialfn,
       b.aggfnoid, b.aggcombinefn, b.aggserialfn, b.aggdeserialfn
FROM
    pg_aggregate a, pg_aggregate b
WHERE
    a.aggfnoid < b.aggfnoid AND a.aggtransfn = b.aggtransfn AND
    (a.aggcombinefn != b.aggcombinefn OR a.aggserialfn != b.aggserialfn
     OR a.aggdeserialfn != b.aggdeserialfn);

-- Cross-check aggsortop (if present) against pg_operator.
-- We expect to find entries for bool_and, bool_or, every, max, and min.

SELECT DISTINCT proname, oprname
FROM pg_operator AS o, pg_aggregate AS a, pg_proc AS p
WHERE a.aggfnoid = p.oid AND a.aggsortop = o.oid
ORDER BY 1, 2;

-- Check datatypes match

SELECT a.aggfnoid::oid, o.oid
FROM pg_operator AS o, pg_aggregate AS a, pg_proc AS p
WHERE a.aggfnoid = p.oid AND a.aggsortop = o.oid AND
    (oprkind != 'b' OR oprresult != 'boolean'::regtype
     OR oprleft != p.proargtypes[0] OR oprright != p.proargtypes[0]);

-- Check operator is a suitable btree opfamily member

SELECT a.aggfnoid::oid, o.oid
FROM pg_operator AS o, pg_aggregate AS a, pg_proc AS p
WHERE a.aggfnoid = p.oid AND a.aggsortop = o.oid AND
    NOT EXISTS(SELECT 1 FROM pg_amop
               WHERE amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree')
                     AND amopopr = o.oid
                     AND amoplefttype = o.oprleft
                     AND amoprighttype = o.oprright);

-- Check correspondence of btree strategies and names

SELECT DISTINCT proname, oprname, amopstrategy
FROM pg_operator AS o, pg_aggregate AS a, pg_proc AS p,
     pg_amop as ao
WHERE a.aggfnoid = p.oid AND a.aggsortop = o.oid AND
    amopopr = o.oid AND
    amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree')
ORDER BY 1, 2;

-- Check that there are not aggregates with the same name and different
-- numbers of arguments.  While not technically wrong, we have a project policy
-- to avoid this because it opens the door for confusion in connection with
-- ORDER BY: novices frequently put the ORDER BY in the wrong place.
-- See the fate of the single-argument form of string_agg() for history.
-- (Note: we don't forbid users from creating such aggregates; the policy is
-- just to think twice before creating built-in aggregates like this.)
-- The only aggregates that should show up here are count(x) and count(*).

SELECT p1.oid::regprocedure, p2.oid::regprocedure
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid < p2.oid AND p1.proname = p2.proname AND
    p1.prokind = 'a' AND p2.prokind = 'a' AND
    array_dims(p1.proargtypes) != array_dims(p2.proargtypes)
ORDER BY 1;

-- For the same reason, built-in aggregates with default arguments are no good.

SELECT oid, proname
FROM pg_proc AS p
WHERE prokind = 'a' AND proargdefaults IS NOT NULL;

-- For the same reason, we avoid creating built-in variadic aggregates, except
-- that variadic ordered-set aggregates are OK (since they have special syntax
-- that is not subject to the misplaced ORDER BY issue).

SELECT p.oid, proname
FROM pg_proc AS p JOIN pg_aggregate AS a ON a.aggfnoid = p.oid
WHERE prokind = 'a' AND provariadic != 0 AND a.aggkind = 'n';

-- **************** pg_opfamily ****************

-- Look for illegal values in pg_opfamily fields

SELECT p1.oid
FROM pg_opfamily as p1
WHERE p1.opfmethod = 0 OR p1.opfnamespace = 0;

-- Look for opfamilies having no opclasses.  While most validation of
-- opfamilies is now handled by AM-specific amvalidate functions, that's
-- driven from pg_opclass entries below, so an empty opfamily would not
-- get noticed.

SELECT oid, opfname FROM pg_opfamily f
WHERE NOT EXISTS (SELECT 1 FROM pg_opclass WHERE opcfamily = f.oid);

-- **************** pg_opclass ****************

-- Look for illegal values in pg_opclass fields

SELECT p1.oid
FROM pg_opclass AS p1
WHERE p1.opcmethod = 0 OR p1.opcnamespace = 0 OR p1.opcfamily = 0
    OR p1.opcintype = 0;

-- opcmethod must match owning opfamily's opfmethod

SELECT p1.oid, p2.oid
FROM pg_opclass AS p1, pg_opfamily AS p2
WHERE p1.opcfamily = p2.oid AND p1.opcmethod != p2.opfmethod;

-- There should not be multiple entries in pg_opclass with opcdefault true
-- and the same opcmethod/opcintype combination.

SELECT p1.oid, p2.oid
FROM pg_opclass AS p1, pg_opclass AS p2
WHERE p1.oid != p2.oid AND
    p1.opcmethod = p2.opcmethod AND p1.opcintype = p2.opcintype AND
    p1.opcdefault AND p2.opcdefault;

-- Ask access methods to validate opclasses
-- (this replaces a lot of SQL-level checks that used to be done in this file)

SELECT oid, opcname FROM pg_opclass WHERE NOT amvalidate(oid);

-- **************** pg_am ****************

-- Look for illegal values in pg_am fields

SELECT p1.oid, p1.amname
FROM pg_am AS p1
WHERE p1.amhandler = 0;

-- Check for index amhandler functions with the wrong signature

SELECT p1.oid, p1.amname, p2.oid, p2.proname
FROM pg_am AS p1, pg_proc AS p2
WHERE p2.oid = p1.amhandler AND p1.amtype = 'i' AND
    (p2.prorettype != 'index_am_handler'::regtype
     OR p2.proretset
     OR p2.pronargs != 1
     OR p2.proargtypes[0] != 'internal'::regtype);

-- Check for table amhandler functions with the wrong signature

SELECT p1.oid, p1.amname, p2.oid, p2.proname
FROM pg_am AS p1, pg_proc AS p2
WHERE p2.oid = p1.amhandler AND p1.amtype = 's' AND
    (p2.prorettype != 'table_am_handler'::regtype
     OR p2.proretset
     OR p2.pronargs != 1
     OR p2.proargtypes[0] != 'internal'::regtype);

-- **************** pg_amop ****************

-- Look for illegal values in pg_amop fields

SELECT p1.amopfamily, p1.amopstrategy
FROM pg_amop as p1
WHERE p1.amopfamily = 0 OR p1.amoplefttype = 0 OR p1.amoprighttype = 0
    OR p1.amopopr = 0 OR p1.amopmethod = 0 OR p1.amopstrategy < 1;

SELECT p1.amopfamily, p1.amopstrategy
FROM pg_amop as p1
WHERE NOT ((p1.amoppurpose = 's' AND p1.amopsortfamily = 0) OR
           (p1.amoppurpose = 'o' AND p1.amopsortfamily <> 0));

-- amopmethod must match owning opfamily's opfmethod

SELECT p1.oid, p2.oid
FROM pg_amop AS p1, pg_opfamily AS p2
WHERE p1.amopfamily = p2.oid AND p1.amopmethod != p2.opfmethod;

-- Make a list of all the distinct operator names being used in particular
-- strategy slots.  This is a bit hokey, since the list might need to change
-- in future releases, but it's an effective way of spotting mistakes such as
-- swapping two operators within a family.

SELECT DISTINCT amopmethod, amopstrategy, oprname
FROM pg_amop p1 LEFT JOIN pg_operator p2 ON amopopr = p2.oid
ORDER BY 1, 2, 3;

-- Check that all opclass search operators have selectivity estimators.
-- This is not absolutely required, but it seems a reasonable thing
-- to insist on for all standard datatypes.

SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.oprname
FROM pg_amop AS p1, pg_operator AS p2
WHERE p1.amopopr = p2.oid AND p1.amoppurpose = 's' AND
    (p2.oprrest = 0 OR p2.oprjoin = 0);

-- Check that each opclass in an opfamily has associated operators, that is
-- ones whose oprleft matches opcintype (possibly by coercion).

SELECT p1.opcname, p1.opcfamily
FROM pg_opclass AS p1
WHERE NOT EXISTS(SELECT 1 FROM pg_amop AS p2
                 WHERE p2.amopfamily = p1.opcfamily
                   AND binary_coercible(p1.opcintype, p2.amoplefttype));

-- Check that each operator listed in pg_amop has an associated opclass,
-- that is one whose opcintype matches oprleft (possibly by coercion).
-- Otherwise the operator is useless because it cannot be matched to an index.
-- (In principle it could be useful to list such operators in multiple-datatype
-- btree opfamilies, but in practice you'd expect there to be an opclass for
-- every datatype the family knows about.)

SELECT p1.amopfamily, p1.amopstrategy, p1.amopopr
FROM pg_amop AS p1
WHERE NOT EXISTS(SELECT 1 FROM pg_opclass AS p2
                 WHERE p2.opcfamily = p1.amopfamily
                   AND binary_coercible(p2.opcintype, p1.amoplefttype));

-- Operators that are primary members of opclasses must be immutable (else
-- it suggests that the index ordering isn't fixed).  Operators that are
-- cross-type members need only be stable, since they are just shorthands
-- for index probe queries.

SELECT p1.amopfamily, p1.amopopr, p2.oprname, p3.prosrc
FROM pg_amop AS p1, pg_operator AS p2, pg_proc AS p3
WHERE p1.amopopr = p2.oid AND p2.oprcode = p3.oid AND
    p1.amoplefttype = p1.amoprighttype AND
    p3.provolatile != 'i';

SELECT p1.amopfamily, p1.amopopr, p2.oprname, p3.prosrc
FROM pg_amop AS p1, pg_operator AS p2, pg_proc AS p3
WHERE p1.amopopr = p2.oid AND p2.oprcode = p3.oid AND
    p1.amoplefttype != p1.amoprighttype AND
    p3.provolatile = 'v';

-- **************** pg_amproc ****************

-- Look for illegal values in pg_amproc fields

SELECT p1.amprocfamily, p1.amprocnum
FROM pg_amproc as p1
WHERE p1.amprocfamily = 0 OR p1.amproclefttype = 0 OR p1.amprocrighttype = 0
    OR p1.amprocnum < 1 OR p1.amproc = 0;

-- Support routines that are primary members of opfamilies must be immutable
-- (else it suggests that the index ordering isn't fixed).  But cross-type
-- members need only be stable, since they are just shorthands
-- for index probe queries.

SELECT p1.amprocfamily, p1.amproc, p2.prosrc
FROM pg_amproc AS p1, pg_proc AS p2
WHERE p1.amproc = p2.oid AND
    p1.amproclefttype = p1.amprocrighttype AND
    p2.provolatile != 'i';

SELECT p1.amprocfamily, p1.amproc, p2.prosrc
FROM pg_amproc AS p1, pg_proc AS p2
WHERE p1.amproc = p2.oid AND
    p1.amproclefttype != p1.amprocrighttype AND
    p2.provolatile = 'v';

-- **************** pg_index ****************

-- Look for illegal values in pg_index fields.

SELECT p1.indexrelid, p1.indrelid
FROM pg_index as p1
WHERE p1.indexrelid = 0 OR p1.indrelid = 0 OR
      p1.indnatts <= 0 OR p1.indnatts > 32;

-- oidvector and int2vector fields should be of length indnatts.

SELECT p1.indexrelid, p1.indrelid
FROM pg_index as p1
WHERE array_lower(indkey, 1) != 0 OR array_upper(indkey, 1) != indnatts-1 OR
    array_lower(indclass, 1) != 0 OR array_upper(indclass, 1) != indnatts-1 OR
    array_lower(indcollation, 1) != 0 OR array_upper(indcollation, 1) != indnatts-1 OR
    array_lower(indoption, 1) != 0 OR array_upper(indoption, 1) != indnatts-1;

-- Check that opclasses and collations match the underlying columns.
-- (As written, this test ignores expression indexes.)

SELECT indexrelid::regclass, indrelid::regclass, attname, atttypid::regtype, opcname
FROM (SELECT indexrelid, indrelid, unnest(indkey) as ikey,
             unnest(indclass) as iclass, unnest(indcollation) as icoll
      FROM pg_index) ss,
      pg_attribute a,
      pg_opclass opc
WHERE a.attrelid = indrelid AND a.attnum = ikey AND opc.oid = iclass AND
      (NOT binary_coercible(atttypid, opcintype) OR icoll != attcollation);

-- For system catalogs, be even tighter: nearly all indexes should be
-- exact type matches not binary-coercible matches.  At this writing
-- the only exception is an OID index on a regproc column.

SELECT indexrelid::regclass, indrelid::regclass, attname, atttypid::regtype, opcname
FROM (SELECT indexrelid, indrelid, unnest(indkey) as ikey,
             unnest(indclass) as iclass, unnest(indcollation) as icoll
      FROM pg_index
      WHERE indrelid < 16384) ss,
      pg_attribute a,
      pg_opclass opc
WHERE a.attrelid = indrelid AND a.attnum = ikey AND opc.oid = iclass AND
      (opcintype != atttypid OR icoll != attcollation)
ORDER BY 1;

-- Check for system catalogs with collation-sensitive ordering.  This is not
-- a representational error in pg_index, but simply wrong catalog design.
-- It's bad because we expect to be able to clone template0 and assign the
-- copy a different database collation.  It would especially not work for
-- shared catalogs.

SELECT relname, attname, attcollation
FROM pg_class c, pg_attribute a
WHERE c.oid = attrelid AND c.oid < 16384 AND
    c.relkind != 'v' AND  -- we don't care about columns in views
    c.relkind != 'f' AND  -- GPDB: foreign/external tables are also OK.
    c.relkind != 'c' AND  -- GPDB: as well as composite types
    attcollation != 0 AND
    attcollation != (SELECT oid FROM pg_collation WHERE collname = 'C');

-- Double-check that collation-sensitive indexes have "C" collation, too.

SELECT indexrelid::regclass, indrelid::regclass, iclass, icoll
FROM (SELECT indexrelid, indrelid,
             unnest(indclass) as iclass, unnest(indcollation) as icoll
      FROM pg_index
      WHERE indrelid < 16384) ss
WHERE icoll != 0 AND
    icoll != (SELECT oid FROM pg_collation WHERE collname = 'C');

redpajama_set_name: RedPajamaGithub